Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[QUERY]Getting TokenCredentials to connect to azure resources for Desktop Applications #25066

Closed
ShrutiJaiswal1494 opened this issue Nov 2, 2021 · 10 comments
Assignees
Labels
Azure.Identity Client This issue points to a problem in the data-plane of the library. customer-reported Issues that are reported by GitHub users external to the Azure organization. needs-team-attention Workflow: This issue needs attention from Azure service team or SDK team question The issue doesn't require a change to the product in order to be resolved. Most issues start as that

Comments

@ShrutiJaiswal1494
Copy link

ShrutiJaiswal1494 commented Nov 2, 2021

Hi All,

I am working on a .Net Core Desktop Application that needs to connect to Azure Blob Storage to download some files. To authenticate the requests to storage we need a token to be given during the blob service client creation and I am not sure what’s the correct way to get this token credential.

Using DefaultAzureCredential
Reading the documentation here it seems there is an option to use DefaultAzureCredential that looks for credentials in multiple places.. It is working fine for my local dev environment as it's getting the credential from VS Code/Azure CLI. But for prod, I assume that this approach is for applications running in Azure. However, my application is a desktop application. Can I still use this to acquire TokenCredential in the prod environment as well or is there anything else I need to set up to make sure it works fine for other users when distributed as a packaged application (I want to avoid user interaction as much as possible)?

Using ClientSecretCredential
Another approach to get the credentials is to use the ClientSecretCredential class by passing the teantId, clientId, and clientSecret for the registered App. Since clientSecret should not be stored in the source code, how can I get this value in my application? I thought of using a KeyVault for this but again the issue is how to get the TokenCredentials to connect to KeyVault?

or is there any other approach that I can use to get the TokenCredential to connect to Azure?

P.S: I am using Microsoft.Identity.Client to authenticate users with Microsoft account following the example here . Is there a way I can use the AccessToken retrieved here to get a TokenCredential for blob client?

code for reference

var blobClient = new BlobClient(new Uri(s_InstallerURI), DefaultAzureCredential);
                var blobServiceClient = blobClient.GetParentBlobContainerClient().GetParentBlobServiceClient();
                UserDelegationKey key = blobServiceClient.GetUserDelegationKey(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddHours(1));
                var sasBuilder = new BlobSasBuilder()
                {
                    BlobContainerName = blobClient.BlobContainerName,
                    BlobName = blobClient.Name,
                    Resource = "b",
                    StartsOn = DateTimeOffset.UtcNow,
                    ExpiresOn = DateTimeOffset.UtcNow.AddHours(1)
                };
                sasBuilder.SetPermissions(BlobSasPermissions.All);
                var blobUriBuilder = new BlobUriBuilder(blobClient.Uri)
                {
                    Sas = sasBuilder.ToSasQueryParameters(key, blobClient.AccountName)
                };
                var packageManager = new PackageManager();
                packageManager.AddPackageAsync(blobUriBuilder.ToUri(), null, DeploymentOptions.ForceApplicationShutdown).AsTask().Wait();

Any help is much appreciated. Thanks in advance.

Environment:

  • To connect to azure blob I am using Azure.Storage.Blobs Version=12.9.1
  • Hosting platform - macOS and Windows using .Net5
  • IDE : Visual Studio 2019
@ghost ghost added needs-triage Workflow: This is a new issue that needs to be triaged to the appropriate team. customer-reported Issues that are reported by GitHub users external to the Azure organization. question The issue doesn't require a change to the product in order to be resolved. Most issues start as that labels Nov 2, 2021
@jsquire jsquire added Azure.Identity Client This issue points to a problem in the data-plane of the library. needs-team-attention Workflow: This issue needs attention from Azure service team or SDK team labels Nov 2, 2021
@ghost ghost removed the needs-triage Workflow: This is a new issue that needs to be triaged to the appropriate team. label Nov 2, 2021
@jsquire
Copy link
Member

jsquire commented Nov 2, 2021

Thank you for your feedback. Tagging and routing to the team members best able to assist.

@christothes
Copy link
Member

Hi @ShrutiJaiswal1494 - One clarification: Are you intending to connect to the storage account using a specific that you own identity rather than the identity of the user of the application? Because this is a desktop environment, I don't think there would be a way to protect your credential, no matter how it is acquired.

Have you considered using a SAS token instead? This would allow you to delegate constrained and timeboxed access to users of the desktop app.

@christothes christothes added the needs-author-feedback Workflow: More information is needed from author to address the issue. label Nov 2, 2021
@ghost ghost removed the needs-team-attention Workflow: This issue needs attention from Azure service team or SDK team label Nov 2, 2021
@ShrutiJaiswal1494
Copy link
Author

Hey @christothes, Thanks for the reply. My application will be Microsoft internal. So I want everyone with Microsoft account to have access but I am not sure how to do it. For your suggestion of SAS token, I am already using a SAS with user delegation key to time-bound the access.
My only concern is how to get a TokenCredential to build a service client for different users when using the App. Otherwise, I will need to store the account name and key in the code which is not preferred.

@ghost ghost added needs-team-attention Workflow: This issue needs attention from Azure service team or SDK team and removed needs-author-feedback Workflow: More information is needed from author to address the issue. labels Nov 2, 2021
@christothes
Copy link
Member

Your choices are essentially to build the service client for a single user (some credential you own) or for the user that is running the application (DefaultAzureCredential or specific local credential such as AzureCliCredential). If you build it for the user running the app, you'd just need to decide how to assign roles to an AAD security group that your users would be a member of.

With SAS, you could do something like create a web service that issues SAS tokens to your client application.

@ShrutiJaiswal1494
Copy link
Author

  1. If I build the service client based on the credentials which I own then what is the best pay to store those credentials in a desktop app?
  2. If I build the client using their local credential like using DefaultAzureCredential how do I make sure that it works for them for cases when they are not logged into azure CLI/PowerShell or VS. ?
    (I believe Environment variable and Managed identity is not an option for me as Managed identity requires the app to run on Azure and setting the env var on each user's desktop will disclose the secret. Correct me if I am wrong.)

@christothes
Copy link
Member

  1. If I build the service client based on the credentials which I own then what is the best pay to store those credentials in a desktop app?

There isn't a great way that doesn't compromise the credential, since it is a desktop app.

  1. If I build the client using their local credential like using DefaultAzureCredential how do I make sure that it works for them for cases when they are not logged into azure CLI/PowerShell or VS. ?

You can't - that is a pre-requisite that you could handle in your app's error messages.

(I believe Environment variable and Managed identity is not an option for me as Managed identity requires the app to run on Azure and setting the env var on each user's desktop will disclose the secret. Correct me if I am wrong.)

Correct.

@ShrutiJaiswal1494
Copy link
Author

  1. If I use the includeInteractiveCredentials with DefaultAzureCredential, will it still throw an error if the user is not logged in azure CLI/PowerShell or VS, or will it prompt the user to login?
  2. I have verified all Microsoft users through Microsoft.Identity.Client. Is there a way to use the Access Token that I receive from Microsoft.Identity.Client to get a TokenCredential for Azure?

@schaabs
Copy link
Member

schaabs commented Nov 2, 2021

@ShrutiJaiswal1494 if your intent is to authenticate users in your app as you are doing directly with msal in the link you gave here. I would suggest using the InteractiveBrowserCredential, as it is the closest analogue to how you are authenticating with the PublicClientApplication. The InteractiveBrowserCredential will launch the system browser to authenticate the user in net core apps, or use the embedded browser to authenticate users in WPF or WinForms apps.

Also, if you wish to persist tokens across app executions you can enable this by using the TokenCachePeristenceOptions and AuthenticationRecord. Our Client Side User Authentiation sample walks through this scenario in detail.

@schaabs
Copy link
Member

schaabs commented Nov 2, 2021

I have verified all Microsoft users through Microsoft.Identity.Client. Is there a way to use the Access Token that I receive from Microsoft.Identity.Client to get a TokenCredential for Azure?

If you would rather continue using MSAL's PublicClientApplication to authenitcate users, it's fairly trivial to wrap this in a TokenCredential implementation. An example of how to do this can be found in our Authenticating with MSAL Directly sample. This sample details how to wrap the MSAL application object in a TokenCredential implementation. The sample shows wrapping the ConfidentialClientApplication, but wrapping PublicClientApplication should be fairly similar.

@ShrutiJaiswal1494
Copy link
Author

@ShrutiJaiswal1494 if your intent is to authenticate users in your app as you are doing directly with msal in the link you gave here. I would suggest using the InteractiveBrowserCredential, as it is the closest analogue to how you are authenticating with the PublicClientApplication. The InteractiveBrowserCredential will launch the system browser to authenticate the user in net core apps, or use the embedded browser to authenticate users in WPF or WinForms apps.

Also, if you wish to persist tokens across app executions you can enable this by using the TokenCachePeristenceOptions and AuthenticationRecord. Our Client Side User Authentiation sample walks through this scenario in detail.

Thanks for the reply @schaabs. I am thinking to use the InteractiveBrowserCredential approach to authenticate the users however I had some doubts. Since I want the blob storage to be accessed by everyone in Microsoft, will I need to give access to each and every MS employee to my blob storage? If yes, then is there a security group or something that I can give access to?

@github-actions github-actions bot locked and limited conversation to collaborators Mar 27, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Azure.Identity Client This issue points to a problem in the data-plane of the library. customer-reported Issues that are reported by GitHub users external to the Azure organization. needs-team-attention Workflow: This issue needs attention from Azure service team or SDK team question The issue doesn't require a change to the product in order to be resolved. Most issues start as that
Projects
None yet
Development

No branches or pull requests

4 participants