I have followed all steps to use client credentials grant flow to authenticate IMAP.
Registered my app on Azure AD (multitenant)
Set App permissions (Screenshot attached)
Set Service Principals
Acquiring token with scope- "https://outlook.office365.com/.default" and doing post- https://login.microsoftonline.com/{TenantId}/oauth2/v2.0/token
I do get the token but it throws "NO AUTHENTICATE FAILED" error.
Here's the issue- The app was created and permissions set using TESTDOMAIN1 account. So it works/authenticates without any problems for emails with abc#TESTDOMAIN1.com.
But if I try to access a guest account(account added in Azure using invitation) like xyz#TESTDOMAIN2.com, it generates the token but throws NO AUTHENTICATE FAILED error.
I tried updating the service principal as well to access this emailbox but I got error there too. (Screenshot attached)
Please suggest if I'm missing something here. All I want to do is access any of my users (Azure AD Users or external users) to access my app and be able to use the api and give access to mailbox.
ApiPermissions
GuestAccount
ServicePrincipalError
I tried to reproduce the same in my environment and got the below results:
I created an Azure AD application and added permission like below:
I generated the authorization code with below parameters.
GET
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?
client_id=e626f30a-80ea-4530-81e9-ebxxxxx
&response_type=code
&redirect_uri=https://jwt.ms
&response_mode=query
&scope=https://graph.microsoft.com/IMAP.AccessAsUser.All offline_access
&state=12345
I generated access token successfully like below.
https://login.microsoftonline.com/common/oauth2/v2.0/token
grant_type:authorization_code
client_id:e626f30a-80ea-4530-81e9-ebxxxxx
client_secret:client_secret
scope://graph.microsoft.com/IMAP.AccessAsUser.All offline_access
redirect_uri:https://jwt.ms
code:code
Problem: How to authenticate in MS Graph using Azure AAD access token.
Current flow:
My web app has AAD configured with "Log in with AAD"
If I log into AAD my demo app is showing and if I go to https://******.azurewebsites.net/.auth/me
then I get the access_token.
What I tried:
So I tried a couple of things and this was the last, I copied the access_token as code and tried to send it, didn't work.
I'm searching for a solution to silently use the already logged-in user and call MS Graph.
The reason for the error is that you have used the wrong code. Don't try to send the access token as a code, you should request an authorization code in your browser.
https://login.microsoftonline.com/{tenant id}/oauth2/v2.0/authorize?
client_id={client id}
&response_type=code
&redirect_uri={redirect_uri}
&response_mode=query
&scope=https://graph.microsoft.com/.default
&state=12345
In addition, redirect_uri is also a required parameter.
For the already logged in user you need follow the below steps for access:
Make sure you have enable the allow access token for the register app as below
Write code to acquire access token for the for the logged in user Reference
Now you can pass this token in other successive call to get the result.
I'm trying to get user information from Active Directory (email, phone number and assigned groups) using Microsoft graph and implicit flow in angular + asp.net web api application after user logges into the system.
Now we've set up some privileges for the application registered in Azure AD and all the code seems to be working fine using below set up.
The problem is those permissions seem high just for reading profile info and groups of a single user.
According to microsoft documentation delegated User.Read should be enough - link but after changing to below setup and removing User.Read.All for application
below error is thrown:
{
"StatusCode":500,
"Message":"Code: Authorization_RequestDenied Message: Insufficient privileges to complete the operation.
Inner error: AdditionalData: date: x request-id: x client-request-id: x ClientRequestId: x "
}
The error is thrown when calling Users from graphClient:
GraphServiceClient graphClient = GetClient();
return await graphClient.Users[userObjectId].Request()
.GetAsync();
private GraphServiceClient GetClient()
{
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(ADClientId)
.WithTenantId(TenantId)
.WithClientSecret(ApplicationSecret)
.Build();
ClientCredentialProvider authProvider = new ClientCredentialProvider(confidentialClientApplication);
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
return graphClient;
}
Now I'm not sure how to limit those privileges. Whether there is something incorrect with the flow, the C# code or maybe the privileges are incorrect.
Any help would be greatly appreciated.
Regards.
User.Read Delegated permission allows users to sign-in to the app, and allows the app to read the profile of signed-in users. It also allows the app to read basic company information of signed-in users.
So you can only get https://graph.microsoft.com/v1.0/me or https://graph.microsoft.com/v1.0/user/{userObjectId of the signed-in user} with this permission.
If you want to get other user's information, please use User.ReadBasic.All or User.Read.All Delegated permission (based on your needs). Please note you need to add Delegated permission rather than Application permission.
Reference here.
When trying to access the Graph Service Client using I am receiving the error:
Code: Authorization_RequestDenied
Message: Insufficient privileges to complete the operation.
After researching this error the most common solution was to set the permissions for the API. This had already been done and has permissions to read basic/full profiles.
I've delete and re-added the APIs.
Below is the code in my AzureAuthenticationProvider class which inherits from IAuthenticationProvider:
public class AzureAuthenticationProvider : IAuthenticationProvider
{
private string _azureDomain = "myDevDom.onmicrosoft.com";
public async Task AuthenticateRequestAsync(HttpRequestMessage request)
{
try
{
string clientId = "2b823c67-1b0d-4a10-a9e1-737142516f5q";
string clientSecret = "xxxxxx";
AuthenticationContext authContext = new AuthenticationContext("https://login.windows.net/" + _azureDomain + "/oauth2/token");
ClientCredential credentials = new ClientCredential(clientId, clientSecret);
AuthenticationResult authResult = await authContext.AcquireTokenAsync("https://graph.microsoft.com/", credentials);
request.Headers.Add("Authorization", "Bearer " + authResult.AccessToken);
}
catch (Exception ex)
{
}
}
}
I've tried changing the client secret to an invalid Id and it threw an error, so the client key is correct. I've also tried to verify that the access token is valid by altering the access token, this also returns a error.
The above code seems to work fine.
Below is the code where I'm trying to access Azure AD:
public async Task<IGraphServiceUsersCollectionPage> GetUsersByLastName(string lastname)
{
GraphServiceClient graphClient = new GraphServiceClient(new AzureAuthenticationProvider());
string filter = String.Format("startswith(surname, '{0}')", lastname);
IGraphServiceUsersCollectionPage users = await graphClient.Users.Request().Filter(filter).GetAsync(); //Fails on this line
return users;
}
Please refer to below steps :
From your screenshot , seems you grant Read and write directory data application permission for Windows Azure Active Directory(azure ad graph api) . Since you are using microsoft graph (https://graph.microsoft.com/) , you need to grant application permission for Microsoft Graph :
Since you are admin in your AAD, You could grant permission for users in organization by click Grant permission button shown in above screenshot .
Then you could use your code (client credential flow to get the token) and query users information . If you check the claims in access token issued by azure ad , you could find Directory.Read.All permission in roles claim .
Make sure click "Grant Permissions" and than Yes for all users accounts.
In my case, delete user was not working. I took below steps & it started working for me.
Go to Azure Active Directory > Roles and administrators > Click on 'User administrator' > click on '+ Add assignment' to add your app. (i.e. console app using AAD Graph REST API to interact with Azure Active Directory).
Hope it helps someone.
For me the key to solve this problem was hint:
To use the Graph API with your B2C tenant, you will need to register a dedicated application by using the generic App Registrations menu (All Services and there it is by default not Favourite starred) in the Azure Portal, NOT Azure AD B2C's Applications menu. You can't reuse the already-existing B2C applications that you registered in the Azure AD B2C's Applications menu.
Find more on page AD B2C API access demo
In some cases the actual issue happens because we use "Application permissions" instead of "Delegated permissions". In my application, I have tried to list all the users with application permissions and it wasn't working. When I switched to a delegated permissions, it worked.
So, some quick check would be like this:
Check if you are using Microsoft Graph API or something else
Use Delegated permissions
Click Grant permissions button to propagate permissions :)
Hopefully, this would help someone.
Suppose you want to create group in azure active directory
i have to performer the following steps to solve this problem
AD > App Registered > your app
Select Required Permission
Click Add and select Microsoft Graph and add it
select Microsoft Graph
select Read and write all groups from delegated permission list
And save it
Select Windows Azure Active Directory and grant all application permission
Save it
Grant permissions by ticking 'Directory.Read.All/ Write' is not enough.
I run into the same issue. and solved by adding service principle to administrator role.
If you application is created recently, this can be done Azure AD Powershell.
$pricinple = Get-AzureADServicePrincipal || Where-Object {$_.DisplayName -eq 'youappname'}
$role = Get-AzureADDirectoryRole | Where-Object {$_.displayName -eq 'Company Administrator'}
Add-AzureADDirectoryRoleMember -ObjectId $role.ObjectId -RefObjectId $pricinple.ObjectId
for detail, see https://learn.microsoft.com/en-us/powershell/module/Azuread/Add-AzureADDirectoryRoleMember?view=azureadps-2.0
If you application was created long time ago, you will need to use MSOnline.
see: https://learn.microsoft.com/en-us/powershell/module/msonline/Add-MsolRoleMember?view=azureadps-1.0
I am using Credentials flow
https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow
and my problem was setting Delegate Permissions instead of Application Permission.
I could not get a user because I wasn't using User.Read.All from Application Permissions
https://learn.microsoft.com/en-us/graph/api/user-get?view=graph-rest-1.0&tabs=http
Application User.Read.All, User.ReadWrite.All, Directory.Read.All, Directory.ReadWrite.All
I had to add all "groups" (ID, Access, SAML) into the token.
This can be configurated in the Azure Active Directory Token Configuration and checked via https://jwt.io/.
you should give Directory.Read role to the service principal in the AD page, not the app register page.
by the way. I am use python sdk azure-graphrbac with serviceprincipal
from msrestazure.azure_active_directory import ServicePrincipalCredentials
credential = ServicePrincipalCredentials(ServicePrincipal_APP_ID,ServicePrincipal_SECRET_VALUE,tenant=ServicePrincipal_TENANT_ID,resource="https://graph.windows.net/")
self.client=GraphRbacManagementClient(credential,TENANT_ID,base_url)
Go to Azure Portal -> Active Directory -> App registrations -> Select Your Application -> API permissions
Now, Click on Add a permission and choose Microsoft Graph, select Application Permission and search for User.Read.All
Add these permissions to your application and it should work.
I try to implement "Resource Owner Password Credentials Grant" on an Azure AD scenario.
I have a web api (DemoWebApi) and a console (DemoConsole) declared as native application.
I was able to make "Authorization Code Grant" and "Client Credentials Grant" working, but I encounter some issue with "Resource Owner Password Credentials Grant".
First I read this:
http://www.cloudidentity.com/blog/2014/07/08/using-adal-net-to-authenticate-users-via-usernamepassword/
and more especially the NO MSA section.
So I created a user in my Azure AD tenant, now I get this error message:
The user or administrator has not consented to use the application with ID 'bd274da6-80f2-458a-b74b-...'. Send an interactive authorization request for this user and resource.
I can't figure out what I should do
This is my source code:
string authority = "https://login.microsoftonline.com/7dda5ce2-2fb6-4f82-bc27-...";
AuthenticationContext authenticationContext = new AuthenticationContext(authority, false);
UserPasswordCredential credentials = new UserPasswordCredential(login, password);
AuthenticationResult res = await authenticationContext.AcquireTokenAsync(webApiClientId, consoleClientId, credentials);
If you are using it for example as LoginController action in order to provide your customize login screen, it is worth to read one scenario which I encounter when I was working on it.
Resource Owner Password Credential flow token issued even for Incorrect Password
After one successful token allocation for correct password.
There is possibility that you need to call login controller to get access token in order to authenticate users. Now when for the first time you acquired access token by AuthenticationContext (by providing all the required information such as client id, resource id, tenant, credentials) and you again want to get access token but this time user provides a wrong password but correct client id , the Azure AD still provides the access token for the object. Wola !!!!
I have experienced this issue and I have produced this scenario 5-10 times to ensure this is actually happening.
Based on my understanding about Azure AD I reach to the conclusion that Azure AD stores access token in its TokenCache and whenever the AuthenticationContext object requests an access token it first looks for cache even before validating incoming password credentials, though it definitely looks for client id against which token has been issued. This is when things started getting interesting and you will realize how on earth they are providing the access token for the wrong password (Remember : The scenarios is first time you get access token for correct password and then next time with wrong password you still get access token when using AuthenicationContext)
Solution
If you are having the similar requirements, to resolve this possible issue you need to clear token cache of the authentication context object right after getting the AuthenticationResult from AcquireTokenAsync method.
authenticationContext.TokenCache.Clear();
and that's it :).
I guess this has never been documented and I am sure this will be helpful for anybody who is working on such requirement to design custom login page using resource owner credential flow. Although Azure strictly recommend to use other authentication flows which it provides.
You need to provide more information to help us reproduce the issue , for example , how do you register the app ,using azure portal ,powershell or visual studio.What is the user type of the new added user and how do you add that user .
Users do not have any opportunity of providing consent if username & password are passed directly. To fix that issue, you could try to grant permissions for that api in portal(better login with administrator account) :