Failing to authenticate BlobServiceClient and Azure AD - c#

I'm having issues using bloblserviceClient with azure Ad
I'm logged into account "X" in visual studio and also tools => optios => azure service authentication = account "X"
This is the following code
var uri = new Uri("https://testblob112.blob.core.windows.net/order");
var cred = new DefaultAzureCredential();
var client = new BlobClient(uri, cred);
await client.UploadAsync("test.txt");
User X also has Storage contributor access to the storage account order.
I'm getting the following error
ure.Identity.AuthenticationFailedException: SharedTokenCacheCredential authentication failed: AADSTS9002332: Application 'e406a681-f3d4-42a8-90b6-c2b029497af1'(Azure Storage) is configured for use by Azure Active Directory users only. Please do not use the /consumers endpoint to serve this request.
Am I missing anything?

Key access may be disabled.
Can you check these two options under Configuration in your Storage Account?

Related

Not able to get all users from Azure Active Directory

I am using solution mentioned here to get all users from Active Directory however I suspect the code is pulling disabled users from our old Active Directory. The new one is Azure Active Directory. Please let me know what change is required to get below details of only active users from Azure Active Directory:
First Name
Last Name
Email
Enterprise ID
Getting all users in Azure AD can use Microsoft Graph API. Here's the API for listing users. But it doesn't support personal Microsoft account, it only supports work or school accounts. By the way, I'm not sure what is Enterprise ID, could you pls take a look at this section to check if this API contained it?
I assume you have an asp.net core WEB API which is used to getting user list. So you should use code like below.
using Microsoft.Graph;
using Azure.Identity;
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "tenant_name.onmicrosoft.com";
var clientId = "aad_app_id";
var clientSecret = "client_secret";
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var users = await graphClient.Users.Request().GetAsync();
Then an Azure AD application is required for the variables in code above. Pls follow this document to register the Azure AD app. Since my assumption is based on a web API, no need to add redirect URL here. Now we can get tenantId , clientId in Overview blade, and created the client secret. We also need to modify API permissions blade and add required API permissions. What we need is Application permission User.Read.All,User.ReadWrite.All,Directory.Read.All, Directory.ReadWrite.All.

ImmutableID of the user missing when trying to acquire a token for MS Graph API (Windows auth)

I'm developing an API that uses the Microsoft Graph Client SDK to make multiples calls to a Sharepoint site.
To authenticate the users making the calls to the API, I'm using the Integrated Windows Provider method, with this very simple code:
var clientApp = PublicClientApplicationBuilder
.Create(_apiSettings.Value.AzureClientId)
.WithTenantId(_apiSettings.Value.AzureTenantId)
.Build();
var token = clientApp.AcquireTokenByIntegratedWindowsAuth(new string[] { _apiSettings.Value.MicrosoftGraphApiScopeUrl })
.ExecuteAsync().Result;
When calling the method containing this code in local, it works flawlessly. But when I deploy the app to our test server, and by using the NTLM authentication with the same user than in local, I'm having this error:
Microsoft.Identity.Client.MsalUiRequiredException: AADSTS90020: The
SAML 1.1 Assertion is missing ImmutableID of the user.
When printing the content of the HttpContext.User, I see that the same user, connected to the same group, is both used on the "online" and the local version.
I already tried adding this header, but it's not doing anything:
var immId = new Dictionary<string, string>();
immId.Add("Prefer", "IdType=\"ImmutableId\"");
var token = clientApp.AcquireTokenByIntegratedWindowsAuth(new string[] { _apiSettings.Value.MicrosoftGraphApiScopeUrl })
.WithExtraHttpHeaders(immId)
.ExecuteAsync().Result;
What can I do ?
Thanks!
If your application don't have the admin to consent to the application.You will get the MsalUiRequiredException.
Try with the adding the admin consent to application .
Or Try with adding tenant admin selected the Grant/revoke admin consent for {tenant domain} button on the API permissions tab of the registration for the application. For more information, see Add permissions to access your web API.
For more details refer this document

Call Azure AD protected Azure Function from console app/PowerShell w/delegated permission

What I want to do is have the user log in to the AAD prompt on their Windows Desktop machines, so I get a Bearer token that will work with my Azure Function.
I've followed the tutorial from this article on adatum but it only covers the application permission (not delegated permissions)
I already have an Azure Function that is set up for Azure AD
authentication.
I already have a client app that I registered (under
App Registrations).
I've configured it to use delegated permissions
for the Azure Function.
Here's my client code:
var clientId = "client id for my console app";//console app
var clientUrl = new Uri("https://login.microsoftonline.com/common/oauth2/nativeclient");
var tenant = "tenantid here";
string authority = "https://login.windows.net/" + tenant;
string resource = "https://myaadProtectedFunc.azurewebsites.net";
AuthenticationContext authenticationContext = new AuthenticationContext(authority, false);
var pp = new PlatformParameters(PromptBehavior.Auto);
var token = authenticationContext.AcquireTokenAsync(resource, clientId, clientUrl,
pp, UserIdentifier.AnyUser).Result;
Console.WriteLine("Got the token: {0}", token.AccessToken);
I get an error saying "[my client app] needs permission to access resources in your organization that only an admin can grant. Please ask an admin to grant permission to this app before you can use it."
Is there some other way to get a Bearer token that will work with my Azure Function?
I did a test and your code does work if you set up the azure side correctly. most likely in the azure function you do not have it set up correctly.
in the azure function did you set up the service principal?
eg. function app -> platform features -> authentication / authorization -> App Service Authentication to ON -> select azure active directory -> express -> create. -> press ok. -> save.
then in your app registration, you will now see 2. the app reg for your client, and app reg for your function app. in the app reg for your client go to api permissions and add the app registration for your function app with the user impersonation selected.
finally make sure your enterprise application has the user/groups you want to be allowed to access for each of the enterprise apps. (client and function app registration)
Hope that helps.
Ok it turns out that I don't need to make a separate client application at all.
I can just use the Client ID of the Azure Function.
The thing is that you will have to go to 'Advance' instead of 'Express' because the library Microsoft.Identity.Client uses v2.0 tokens.
This is to configure your Azure Function - keep all fields the same, but add a /v2.0 to the Issuer URL:
This is the code to get the delegated bearer token for the Azure Function, which uses the v2.0 token - I don't know how to change it to use the v1 token:
string[] scopes = new string[] { "profile", "email", "openid" };
string ClientId = [clientId of Azure Function];
string Tenant = [tenantId];
string Instance = "https://login.microsoftonline.com/";
var _clientApp = PublicClientApplicationBuilder.Create(ClientId)
.WithAuthority($"{Instance}{Tenant}")
.WithDefaultRedirectUri()
.Build();
var accounts = _clientApp.GetAccountsAsync().Result;
var authResult = _clientApp.AcquireTokenInteractive(scopes)
.WithAccount(accounts.FirstOrDefault())
.WithPrompt(Prompt.SelectAccount)
.ExecuteAsync().Result;
var bearerTokenForAzureFunction = authResult.IdToken;
Now I don't understand the need to register a client application at all if I can get the delegated bearer token this way...

Azure AD authentication failing when using ms live accounts other than my AAD acount

I trying to read user data from their Microsoft live account. I have written code as below:
public void GetUserData(){
var authContext = new AuthenticationContext("https://login.microsoftonline.com/common/");
var result = _authenticationContext
.AcquireTokenAsync("https://graph.microsoft.com", "<my client/app ID>", "<redirect URI>", new PlatformParameters(PromptBehavior.RefreshSession))
.Result;
var accessToken = result.AccessToken;
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",accessToken);
var userResponse = httpClient.GetStringAsync("https://graph.microsoft.com/beta/me/").Result;
//DO SOMTHING WITH DATA
}
my code is working fine when I used my AAD credentials, but when I used my personal account it is giving the following error.
AADSTS50020: User account 'XXXX#outlook.com' from identity provider
'live.com' does not exist in tenant 'Default Directory' and cannot
access the application 'XXXXXXXXXXXXXXXXX' in that
tenant. The account needs to be added as an external user in the
tenant first. Sign out and sign in again with a different Azure Active
Directory user account.
Here is the screenshot:
It's similar to this question. could someone help me out?
v1 endpoints require that the user is a member in a directory.
You should probably use the v2.0 endpoints for this: https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-appmodel-v2-overview
If you expect only consumer MS accounts to login, you can specify the authorize URL as:
https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize
First, for the error massage in your question, you need to add the live account into your directory first and then try to use Azure AD v2 endpoint to authenticate. You can not sign in the app with the external account which was not in that directory.
I assume that you want any Microsoft live account can use your app.
Based on this requirement, I suggest you can use Azure AD B2C to achieve this. Azure AD B2C can enables your application to authenticate with any Microsoft account. You can add Microsoft Account as a social identity providers. So that any live accounts can sign up and sign in your App through Azure AD B2C.
You can see more details about Providing sign-up and sign-in to consumers with Microsoft accounts in this official document.
Hope this helps.

How can I create an Azure AD application using the fluent API?

I am using the following code to try to programmatically register an application in Azure Active Directory:
var application = azure.ActiveDirectoryApplications.Define(applicationName)
.WithSignOnUrl(url)
.WithIdentifierUrl(url)
.WithAvailableToOtherTenants(false)
.DefinePasswordCredential(id)
.WithPasswordValue(secret)
.Attach()
.Create();
Where azure is an instance of Microsoft.Azure.Management.Fluent.Azure.
When I run the above to create an Azure Active Directory Application, an Microsoft.Azure.Management.Fluent.Azure exception is thrown with the message Operation returned an invalid status code 'Forbidden'. Creation of other Azure resources (like resource groups and app services) work just fine.
Looking at the exception details, I can see that a request is made to the following endpoint:
https://graph.windows.net/{myTenantId}/applications?api-version=1.6
The following is in the response body:
{"odata.error":{"code":"Authorization_RequestDenied","message":{"lang":"en","value":"Insufficient privileges to complete the operation."}}}
Since the bodies says "Insufficient privileges to complete the operation", it appears to be a simple permission issue, but I have granted the following permissions (while signed in as a global administrator) for the Microsoft.Azure.ActiveDirectory API for the application that's running the code:
Access the directory as the signed-in user
Read and write directory data
Are these privileges not enough? What am I missing? As I said, creation of other resources using the fluent API works just fine.
The scope Directory.AccessAsUser.All and Directory.ReadWrite.All User.Read is sufficient permission to create applications in the Azure Active Directory. Since you doesn't provide how you construct the azure instance, I would provide a working code sample:
static void Main(string[] args)
{
var url = "http://adfei.onmicrosoft.com/appFluent";
var id = "abc";
var secret = "secret";
var applicationName = "appFluent";
var credFile = new AzureCredentials(new UserLoginInformation
{
ClientId = "{appId of native application}",
UserName = "{userName}",
Password = "{password}"
},
"adfei.onmicrosoft.com", AzureEnvironment.AzureGlobalCloud);
IAzure azure = Azure.Authenticate(credFile).WithDefaultSubscription();
var application = azure.ActiveDirectoryApplications.Define(applicationName)
.WithSignOnUrl(url)
.WithIdentifierUrl(url)
.WithAvailableToOtherTenants(false)
.DefinePasswordCredential(id)
.WithPasswordValue(secret)
.Attach()
.Create();
Console.Read();
}
And please ensure the scope is include in the access token to ensure that you have the permission for this operation. You can capture the request via Fiddler to check the token and decode the token from this site to check scp claims in the access token.

Categories