I am working on my first project of connecting Azure B2C with MERN App. I wanted to Sign In using Azure B2C and authorise my web API using the Access Token.
I configured everything and applied configurations to this sample React tutorial provide by their documentation.
The problem arises while calling the Web API. The Web API call are sending without any token. When I check the code, acquireTokenSilent function returning empty accessToken from response.
instance.acquireTokenSilent({
scopes: protectedResources.apiHello.scopes,
account: account
}).then(async (response) => {
console.log(response)
The Request is:
Even though I looked many forums and Microsoft technical forums, no answer is not working.
But what I noticed is, it is requesting for grant_type: authorization_code but am not seeing access token in the response. Posting here the API call, request and response.
The Response is producing id_token but not access token,
I gave grant permission in the SPA App permission for task.read scope. I tried everything but I am still receiving the access token as empty. How could I fix this issue?
I tried to reproduce the same in my environment and got below results:
I registered one Azure AD B2C application for app1 and added scopes(task.read) as below:
Now I created one SPA registration and added API permissions by granting consent like this:
I created Sign up and sign in policy and ran the user flow as below:
Please Check authentication and access token and id token:
I signed in as user it gave me auth code in address bar.
https://<tenant name >.b2clogin.com/<tenant name> .onmicrosoft.com/oauth2/v2.0/authorize?p=B2C_1_susi&client_id=<app id>&nonce=defaultNonce&redirect_uri=https://jwt.ms&scope=openid%20https%3A%2F%2F<tenant name>.onmicrosoft.com tasks.read&response_type=code&prompt=login&code_challenge_method=S256&code_challenge=<challenge paramater>
I generated the access token via Postman with commands like this:
POST https://tenant.b2clogin.com/tenant.onmicrosoft.com/policy/oauth2/v2.0/token
grant_type: authorization_code
client_id: SPA_appid
scope: https://tenant.onmicrosoft.com/app1/task.read
redirect_uri: redirect_uri
code: code
code_verifier: code_verifier
Postman
When I decode the token i getting scp in jwt .ms
Related
I have this Authorization request that works.
How can I replicate it in Python?
I am using an Azure AD to authenticate the access.
Since you are working with python, your case is a : Oauth2 login for SSR web applications with Microsoft
Goal
Get an access_token from interactive login using the oauth2 authorization code grant
Steps
Here I will list all the steps required to do it with any language
Create a web with session with at least these endpoints
/ : home page
/callback : server route or path able to receive query params like /callback?code=123456. This along with your base domain will be called redirect_uri. Sample : http://localhost:8080/callback or http://acme.com/callback
Create and configure an app in Azure Dev Console. Same process is in Google, Facebook, Linkedin, etc. As a result you should have a clientId, clientSecret and a redirect url
Create a simple web with classic session in which if user is not logged-in, redirect (302) to this url:
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=foo&response_type=code&redirect_uri=foo&response_mode=query&scope=offline_access%20user.read%20mail.read
clientid and redirect_uri are important here and should be the same of previous step
After that, browser should redirect the user to the platform login
If user enters valid credentials and accepts the consent warning, Microsoft will perform another redirect (302) to the provided redirect_uri but with special value: The auth code
http://acme.com/callback?code=123456798
In the backend of /callback get the code and send it to this new endpoint
Add a client_id & client_secret parameters
Add a code parameter with the code sent by microsoft
Add a redirect_uri parameter with previously used and registered on azure. Sample http://acme.com/callback or http://localhost:8080/callback
Add a grant_type parameter with a value of authorization_code
Issue the HTTP POST request with content-type: application/x-www-form-urlencoded
You should get a response with the precious access_token:
{
token_type: 'Bearer',
scope: 'Mail.Read User.Read profile openid email',
expires_in: 5020,
ext_expires_in: 5020,
access_token: 'eyJ0oVlKhZHsvMhRydQ',
refresh_token: 's_Rcrqf6xMaWcPHJxRFwCQFkL_qUYqBLM71UN6'
}
You could do with this token, whatever you configured in azure. Sample: If you want to access to user calendar, profile, etc on behalf of the user, you should have registered this in the azure console. So the clientid is related to that and human user will be prompted with something like this
Libraries
There is some libraries provided by microsoft (c#, nodejs) which will save you a little work. Anyway the previous explanation are very detailed.
Advice
Read about oauth2 spec: https://oauth.net/2/
Read about oauth2 authorization code flow login before the implementation with python
https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2
https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow
https://github.com/msusdev/microsoft_identity_platform_dev/blob/main/presentations/auth_users_msalnet.md
Check this to understand how configure the azure web console: https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app
Check my gist https://gist.github.com/jrichardsz/5b8ba730978fce7a7c585007d3fd06b4
In my java web application I want to get access to user's mailbox by using jakarta mail. For that purpose I followed https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth for OAuth2 authorization code flow.
On Azure port I setup my app and added API permissions as below
Now user is redirecting to below authorize endpoint:
https://login.microsoftonline.com/5426ee07-9b73-4a9e-8075-395ab439c6fa/oauth2/v2.0/authorize?client_id=b6067ad9-7195-430b-a35d-97b7aa7beb8f&response_type=code&redirect_uri=http://localhost:8080/callback/microsoft&response_mode=query&scope=offline_access%20https%3A%2F%2Fgraph.microsoft.com%2FIMAP.AccessAsUser.All%20https%3A%2F%2Fgraph.microsoft.com%2FSMTP.Send
After entering credentials and accepting the consent redirect_uri gets hit with auth code. Based on that auth code I formed token endpoint URL and hitting it from server, the token endpoint is as follow:
URL: https://login.microsoftonline.com/5426ee07-9b73-4a9e-8075-395ab439c6fa/oauth2/v2.0/token
Form Data:
client_id=b6067ad9-7195-430b-a35d-97b7aa7beb8f
scope=offline_access%20https%3A%2F%2Foutlook.office.com%2FIMAP.AccessAsUser.All
redirect_uri=http://localhost:8080/callback/microsoft
grant_type=authorization_code
client_secret=QUs8Q~aboLBiopTezMTKwzQjIwWsFFXjc2kCRaRs (I know I have shared the secret)
code={code received from authorize end point}
Response to this post request comes as:
{"error":"invalid_grant","error_description":"AADSTS65001: The user or administrator has not consented to use the application with ID 'b6067ad9-7195-430b-a35d-97b7aa7beb8f' named 'Email Connector'. Send an interactive authorization request for this user and resource.\r\nTrace ID: dc008ced-e23f-4919-bd45-b7ae7c68b000\r\nCorrelation ID: 9b6ede03-3c05-4a78-8975-036a3cb20773\r\nTimestamp: 2022-06-07 19:51:30Z","error_codes":[65001],"timestamp":"2022-06-07 19:51:30Z","trace_id":"dc008ced-e23f-4919-bd45-b7ae7c68b000","correlation_id":"9b6ede03-3c05-4a78-8975-036a3cb20773","suberror":"consent_required"}
Here, I don't understand why the error is saying The user or administrator has not consented to use the application, user has accepted the consent after entering credentials on authorize end point. Event more If we look at the screenshot above admin has already given grant to access the directory.
I tried to reproduce the same scenario in my environment and got the same error as below:
To resolve the error, please check the authorize endpoint you are using to get the code.
Avoid using Microsoft graph API scopes while getting the code.
Replace it with the scope you are using to get access token like below:
https://login.microsoftonline.com/Your_TenantID/oauth2/v2.0/authorize?
client_id=Your_ClientID
&response_type=code
&redirect_uri=http://localhost:8080/callback/microsoft
&response_mode=query
&scope= offline_access https://outlook.office.com/IMAP.AccessAsUser.All
&state=12345
Get the code from the above authorization endpoint.
I got the access token successfully after modifying the endpoint like below:
To validate the access token decode it in jwt.io and check the aud and scp claims like below:
I have some troubles trying to call an Azure Function (code) with Postman.
I have already set up the Authentication / Authorization and settings.
It's working with my browser (with login page).
But when I try to use Postman, I'm getting 401 :
"You do not have permission to view this directory or page."
I also tried to use the Postman built-in (see configuration) Oauth2 to login. I can successfully get the tokens (access and refresh). But it seems that my API request to functions are not working...
Here is the final API Call: postman screenshot
The aad tenant_id starts with 8d6, the application client_id starts with 226, and the app secret ends with Av2.
Is there anything wrong ... ? It looks like actually, Azure Functions handle only Cookies for the authentication, that's why it's working with the browser and not Postman. How can I make it works with the header Authorization / Bearer ?
Thanks for your help !
The way you got the access token is not correct. Just like #Marc said, in your Postman you are not specifying a resource or scope. The postman get new access token tool only has the scope parameter, so you should use the v2.0 endpoint to get the access token.
Auth URL:
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize
Access Token URL:
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token
Scope:
{clientId}/.default
We are testing locking down an API hosted on Azure Web Apps by using the built-in Azure Web App Authentication/Authorization with Azure Active Directory.
We are calling POST https://login.microsoftonline.com/{tenantIDhere}/oauth2/v2.0/token with the following parameters in Postman:
grant_type: password
client_id: {ID}
username: {username}#{tenenat}.onmicrosoft.com
password: {password}
scope: https://{webappname}.azurewebsites.net/.default
client_secret: {secret}
Below is the response I get:
"token_type":"Bearer","scope":"https://{webappname}.azurewebsites.net/user_impersonation https://{webappname}.azurewebsites.net/.default","expires_in":3599,"ext_expires_in":3599,"access_token":"{TOKEN HERE}"}
So I take that token and try and access the webpage by passing the token in the header and I get the below error using POST:
https://{webappname}.azurewebsites.net/api/url
Authorization: Bearer {TOKEN HERE}
Response (401 Unauthorized)
You do not have permission to view this directory or page.
I have spent days trying everything I can find. What am I missing?? As soon as I turn off authorization needed for the web app, I get the expected result. But using the grant_type: password, I CANNOT get in! I have a feeling its related to the scope, but I cannot find documentation on what I need here for this. Any ideas?
The user is able to manually login to the webpage and pull the data, so it is not a permission issue. It has something to do with the token I believe.
If you are using v2.0 endpoint, the scope should be {your_client_id}/.default. Replace https://{webappname}.azurewebsites.net with the client id/application id for your API app in Azure AD.
Edit:
As Wayne said, you could also set scope as {your_client_id}/User.Read to get access token.
I have registered a multitenant app at https://apps.dev.microsoft.com since the "admin consent" prompt wasn't available in the Azure AD apps. Admin consent is required for our app to retrieve info about users and their calendars.
I can provide admin consent from a completely different tenant than what this app is registered from and use the provided access token to retrieve all necessary information, however that obviously expires after an hour and we need offline access.
I have tried using the tenantId instead of 'common' in the https://login.windows.net/common/oauth2/token endpoint, however receive the same message as below.
The following is the data being submitted to the token endpoint in json format (converted within node to form encoded format before submitting):
{
grant_type: 'refresh_token',
client_id: 'e5c0d59d-b2c8-4916-99ac-3c06d942b3e3',
client_secret: '(redacted)',
refresh_token: '(redacted)',
scope: 'openid offline_access calendars.read user.read.all'
}
When I try to refresh the access token I receive an error:
{
"error":"invalid_grant",
"error_description":"AADSTS65001: The user or administrator has not consented to use the application with ID 'e5c0d59d-b2c8-4916-99ac-3c06d942b3e3'. Send an interactive authorization request for this user and resource.\r\nTrace ID: 2bffaa08-8c56-4872-8f9c-985417402e00\r\nCorrelation ID: c7653601-bf96-46c3-b1ff-4857fb25b7dc\r\nTimestamp: 2017-03-22 02:17:13Z",
"error_codes":[65001],
"timestamp":"2017-03-22 02:17:13Z",
"trace_id":"2bffaa08-8c56-4872-8f9c-985417402e00",
"correlation_id":"c7653601-bf96-46c3-b1ff-4857fb25b7dc"
}
This error occurs even when standard consent is used. I have also tried using the node-adal library instead of raw http requests which produces the exact same result.
I note that "offline_access" isn't a permission I am able to set within the MS apps portal, however I would guess the fact that I am getting a refresh token back means that I can refresh the access token?
For the record, the following is the node-adal code I used to see if I was doing something wrong:
var self = this;
var authenticationContext = new AuthenticationContext('https://login.windows.net/common');
authenticationContext.acquireTokenWithRefreshToken(
self.refreshToken,
self.clientId,
self.clientSecret,
'https://graph.microsoft.com/',
function(a) {
console.log(a);
}
);
Any help in getting this refresh process working is appreciated!
Please ensure that the tenant that you using for refreshing token is same as the tenant that you requesting for the access_token.
The refresh token request works well for me unless in the scenario of below:
register the app from protal using Microsoft account
user1 is in tenant1
add user1 as the external users to tenant2
request the access_token/refresh_token from tenant1(OK)
try to refresh the token using tenant1 in the request(OK)
try to refresh the token using tenant2 in the request(same error message)