I have registered xyz.com domain in Azure Active Directory. Then I registered a React single page app in Azure AD App registrations.
I am using domain_name/AllowAnonymous (http://example.com/user_impersonation) scope in react app to generate a token using msal-react.
The generated token from react app contains domain_name/AllowAnonymous (http://example.com/user_impersonation) as audience in JWT token claims.
In the backend, I am using client-id (api://<client-id/Allow.AllUsers>) as audience in JWT token validator to validate token.
But token has domain_name/AllowAnonymous (http://example.com/user_impersonation) as audience, due to which the token validation fails.
How can I get the domain_name by client-id in backend C# code to validate token by domain_name?
Is it secure to set client_id as scope in front-end application for generating JWT token?
I think you can configure the app based on this: https://learn.microsoft.com/en-us/azure/active-directory/develop/tutorial-v2-react
Client_Id is a public information, you can add it to the web app with no worry.
Also keep in mind that in the Azure Active Directory are 3 types of tokens: https://learn.microsoft.com/en-gb/azure/active-directory/develop/security-tokens
If you need to validate the token, take a look of the examples: https://learn.microsoft.com/en-us/azure/active-directory/develop/sample-v2-code
Related
I created a multi-tenant app on Azure Portal and sending request to get token with application's client Id. I am using the following URL to get token on Microsoft Azure AD
https://login.microsoftonline.com/common/oauth2/v2.0/authorize
Sending a get request with parameters client_id={clientId}&response_type=token&scope=user.read+openid+profile+offline_access
However it is returning an access_token on given call-back url
http://localhost:8082/my-callback-url#access_token=EwCIA8l6BAAU6k7%2bXVQzkGyMv7VHB/h4cHbJYRAAATb8xtkaxI5xsVkWM6etOevj7ADopBYP1/hj%2bUz%2bf1ZXH4lpykHkES1XBRBDNRDWwdqAA%2brO2tFlMygiuusVx1EJKvqeV0rPPaNDNX9azpWGzS45BN6WmXKcxzX623enNYJOdo%2bYyTtaMipFapvABOsjHve1nVwfq9zqpmcldnIhXBeGefdQsgqmBNjeAyAbWzifLNtdz6Ybxnbt8nMY5adb82Z8tsfddfDdjrqk%2bu%2b85%2bxKXO9Xop3wdRvrVC9FM46RniA6H3NUKjOMTJAsX4IQLjGjXM4eq9o95lmSzF3zgFOXI1rYwkDRVsFsLOgP8tx0occDcuVPQgMalXR6JREDZgAACIJRWLYJGUcWWAKPx26NmroNGG1xEkPB1kLeGk0Hf8324YZs2InsGvQBFUMU4XzGGNdj0s5rLYKK2ictDstHV1daM241F1M5FiaX1qCgdRXneR9uPzUsSIBOzPJtT1dD4k%2bDxp6Nr4hEnDPlymp5X0SR4v5vUA3aRhnsvmEzBVQDKR7cFvT7NSqVHSr/tTv/epdx81qgJcd6S6xF8oaMc7mn76jgU4YBn8jXYnTfGhUvhNZ8RJyyl71AqZrGr7JS2kStselZUgjavLqc9DdQD9cwPSWu1ketKmGgCjt6lVB3nlaw8Wxq%2by2/YhPznTRFD2wj/vzDOdTzCcZ9mJV%2bKMGcXYQqBiGE0MF8%2bWA1EKSXniT5UiegTfJkvnsgtx6G6sdV0rzFM7Xa9d/dHNDfyV5oGedZtJXE1WCUrEIUZZm/HNhhQyh0WSG0gWm3vOY7NAs13vey9lcIQ6Fllu6W/Ty3HE4llFp/9a3lNcujmlxsCASFUOX6R54xPJMt1ipF5lh5uyZCPoUda46UsrCDnNRg0dhuoSVwJMDHzDbs4NXhX4nhTOze/9koz6p5Ao4DtJ20LqmcylZDoLxUhXIU5vvnBYpiHwanBt2E/rG%2bqVEQbRy/v9fhi0chY0XPzldIm/Lz2l0%2b0MpJ/4l53f9YTRLdEMD8X8Umi35ZvpK9arAqgdRkx4/oWG9m8sxOMY2eASetiAJaU8yjtETgHpBGJTXbDVDpNA1s5NGc9QC%2brcSnGDV0BKIDYxBISR8TiJQVUaPqbNU1Mj3kGyQFnfS0jS83VGVfFCZ4cHkhDq/awLh2JrR0Ag%3d%3d&token_type=bearer&expires_in=3600&scope=User.Read%20openid%20profile
How can I validate this access token? or how can I get a JWT token instead?
Your scopes are user.read+openid+profile+offline_access.
That first one is a Microsoft Graph API scope.
It's actually short-hand for https://graph.microsoft.com/user.read.
So you will get an access token that is meant for Microsoft Graph API.
The other scopes you defined affect the id token (openid, profile) or get you a refresh token (offline_access).
This means you cannot and should not validate the token.
Only Microsoft Graph API should be validating this token, since the token is meant for it.
If you want an access token for your API, you need to use a scope defined in the API's app registration (Expose an API section).
Trying to set up Azure AD OAuth client credentials grant flow for my web api. I'm following the document in https://learn.microsoft.com/en-us/azure/active-directory/develop/v1-oauth2-client-creds-grant-flow. I have to expose my API to a 3rd party. I've created the APP in Azure AD (this is for the client that is requesting my API), generated the secrets and was able to get a response from oauth2/token endpoint. My questions are below:
What is the best way to validate the token? Is it by passing the JWT
(bearer token) as a HTTP header to my API, and then using the SDK to
validate the token
(System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler)? I'm using
C#.
What is the significance of Azure AD -> App Registrations -> "My
API App" -> under Manage, Expose an API? It has an option to
"Authorize client applications". How could I use this feature to
conditionally block and approve the client applications?
I will have to share the secret, client id and the App Id Uri with the 3rd party for them to generate the token and I will validate the token when I receive it.
You're on the right track.
This answer, Azure AD OAuth client credentials grant flow with Web API AuthorizeAttribute Roles, will walk you through one way to do this, using the roles claim in the token to authorize the call.
You will need to:
define roles
create an App registration for each 3rd party
assign their application to your desired roles
You can then use the AuthorizeAttribute to map which roles can execute which controllers/actions, like so:
[Authorize(Roles = "Reader,Requester,Editor,Approver,Administrator")]
Token validation
Once you complete token obtaining flow, you receive a JWT bearer access token. From token consuming end (your service), you need to perform a JWT validation. This is done by validating JWT signature and Claims. One of the most important claim you validate is the audience (aud) claim which must be the identifier (ex:- your service's URL, an ID) unique to token receiving service. Where you register this ? That's your second question.
Please read through MS's guide on token validation which explains key points - Microsoft identity platform access tokens
Service registration
This is where you register valid token receivable endpoints (ex:- your api app). If you check your token request, you provide resource parameter which must match to registered identifier. This allows Azure to validate the token request and issue an access token the mentioned resource. You find this as aud claim in the token. Hope you got the connection now.
App secret
No, only the token obtaining party require the client credentials. Your API or any token consuming party does not need the secret. They only require a valid access token and token signing certificate details. certificate details are exposed at jwks_uri in openid-configuration endpoint.
I have deployed one webapi into azure. After that I have register my API into Azure AD.
I got my API client-id and client-secret, now i just want to test my API not like
3rd application will access it so what will be recourse id in this case.
I have used oauth for authentication into that webapi.
I want to test that webapi so into POSTMAN i used this url to generate oauth token
which i will pass as header Authentication bearer token.
step 1 -
https://login.microsoftonline.com/{{OAuth_Tenant}}/oauth2/token
in header -
grant_type:client_credentials
client_id:{{client_id}} // i have my API client-id
client_secret:{{client_secret}} // i have my API client-secret
resource:{{resource}} // i have my API client-id
when i generate token using above values and send that bearer token it fail error unauthorized.
You need to register an app in Azure Active Directory to acquire access tokens.
Register an app there, and you can find the client id/application id there.
Then you can create a key for the app, that's your client secret.
Finally the resource should be the client id or app id URI for your API's app registration in Azure AD.
To implement this according to best practices, you'll also want to look into defining app permissions for your API, so you can then assign privileges to apps to call your API.
I am new to OAuth and I am working on app identity/client credential work flow using OAuth. Basically there will be a client application calling the API using the client app's app id. The API will trust whoever have the access to the client app.
The understand I have for the implementation is that:
register client app to Azure AD
put the app id of the client app into the API
enable OAuth request so the client app is able to receive access token from AAD
use the access token to call the API
But my confusion is the relationship between the web app's app id and the access token. I know we have to put the client's app id into the API so the API can somehow recognize the client app. How does the API know the access token is from that specific app id? How does it work exactly?
The app id also named client id, it represents a client application which makes protected resource requests on behalf of the resource owner.
The client application authenticates the resource owner and obtains its authorization, then the authorization server will issue the access token to the client application.
For more details about the relationship, you could see the Azure Active Directory developer glossary.
Update:
For example, I use the client credential flow to get the access token for MS Graph API. Then I decode it in https://jwt.io/ . You will find the claims "aud": "https://graph.microsoft.com/", "appid": "xxxxxx", "app_displayname": "joywebapp2", for more details, see Claims in access tokens.
The you use the access token to call MS Graph API, it will know the access token is from that specific client app as you asked.
There is a dedicated protocol/validation mechanism for this. Once token is received at resource server (ex:- API as in your example), it can perform a token introspection to identify the context of the token. OAuth 2.0 Token Introspection define how the introspection request should be build and what to expect from response.
This specification defines a protocol that allows authorized
protected resources to query the authorization server to determine
the set of metadata for a given token that was presented to them by
an OAuth 2.0 client.
Read through the introspection response section to identify what sort of data it will return. Client ID is also some valid claim.
Now there is an alternative approach too. This is what Azure AD has adopted. Azure Active Directory use JWT formatted access tokens.
Azure Active Directory access tokens
Access tokens enable clients to securely call APIs protected by Azure. Azure Active Directory (Azure AD) access tokens are JWTs, Base64 encoded JSON objects signed by Azure. Clients should treat access tokens as opaque strings, as the contents of the token are intended for the resource only.
JWT tokens are self contained, which mean the holder/receiver can validate the integrity of the token and verify claims valid. Go through token validation section which explain the complete process. One key claim you must focus is the audience claim. This denote the intended audience of JWT and can have multiple values (array).
I have an application registered in Azure AD.
If I am using the same Application ID at the level of Web API and at the level of client (SPA application), why do both Azure AD auth libraries
(ADAL JS for Azure AD v1 and MSAL.js for Azure AD v2)
use ID token as bearer token when calling Web API, instead of requesting and using an access token? Doesn't this go against the spec?
According to official documentation and this might be your case.
"The OAuth 2.0 implicit flow in Azure AD is designed to return an ID token when the resource for which the token is being requested is the same as the client application. In other words, when the JS client uses ADAL JS to request a token for its own backend web API registered with same App ID as the client, an ID token is returned and cached by the library. Note that in this case the resource should be set to the App ID of the client (App ID URI will not work). This ID token can then be used as a bearer token in the calls to your application's backend API."
You can find more about this here!
https://github.com/AzureAD/azure-activedirectory-library-for-js/wiki/Acquire-tokens