Different authorities for user JWTs vs. client_credentials JWTs - azure-active-directory

I have noticed that when I obtain a JWT from Azure AD after logging on, the JWT specifies "https://login.microsoftonline.com" as the issuing authority. However, if I obtain a JWT using the client_credentials flow, the issuing authority is "https://sts.windows.net". Having dissimilar issuing authorities makes it difficult to configure an application to consume both kinds of JWTs, since the configuration process only allows you to specify a single authority.
Is there a reason why Microsoft uses different issuing authorities for JWTs? I assumed that it was because MSFT wants to segregate the two usage scenarios. That is, they want to discourage the creation of applications that switch between user-based and non-based security contexts. Is there some other reason I'm missing?

The changes in format of Issuer Authority value for the token that you're observing are most likely due to the different versions of token i.e. Azure AD v1.0 token or Azure AD v2.0 token (and probably not because you used client credentials flow or say auth code flow for acquiring access token for same application)
Azure AD v2.0 token - issuer format
https://login.microsoftonline.com/<Azure AD Tenant GUID>/v2.0
Azure AD v1.0 token - issuer format
https://sts.windows.net/<Azure AD Tenant GUID>/
Please look at this Microsoft Documentation - Access Tokens Reference - Sample Tokens
Notice this one has issuer format for each of the sample tokens there.
Also take a look at the important note in the same Microsoft Documentation Link shared.
As the documentation says, tokens are created based on the 'audience'. It also gives an example of using accessTokenAcceptedVersion.
You mention that even though you're using Azure AD v2 endpoint to acquire token with client credentials flow, you're seeing issuer as per v1 format.
I think that the application that you are acquiring the token for is important here, and if it accepts v1 token, then you will get back v1 token (even though you used v2 endpoint).
Also, if possible please share decoded tokens (minus sensitive info) in your question for more clarity.

Related

What scope does "idp" belong to in IdentityServer4?

My MVC client's access token contains an "idp" claim that my simple server-to-server client's token doesn't. I don't explicitly request idp on either clients, so where is this claim coming from? I thought it was part of "openid", and since it is available by default to MVC client, you don't need to request it, but I couldn't find any documentation/specification that confirms it. By the way, I am unable to add the openid scope to my serer-to-server client, as I am getting "invalid scope" error when I do that. What I am trying to do here is to get the "idp" claim into the token for my server-to-server client as well, but not sure if that's possible. Can someone point me to the right direction?
When you do server to server communication using the client-credentials flow, there is no user involved and hence the openid scope has no purpose. As its core purpose is to ask for the subject claim (the user Id).
The idp claim is not part of any scope and is usually added by IdentityServer.
Why do you neeed the idp claim? Your API and client both trusts the shared IdentiyServer.
idp claim in Identityserver stands for external identity provider (such as Google). That's why it does not have any sense when you request a token from your local IdP with "service_credentials" flow. If you are interested in the info about the token's issuer, just use iss claim instead. If you are sure you need the idp (or any other custom) claim in each and every token, you can involve a custom ClaimsService as I explained in my previous answer.

IdentityServer4 - Understanding flows and Endpoints. How is it related to OAuth and OpenIDConnect?

I am integrating the security aspect of webapplication. I have decided to use OAuth,
so we have a REST WebApi in AspNet Core 3.0, the client which is a SPA created in React, and the Identity Server 4.0 app which is also in AspNet Core 3.0.
I read that OAuth is created for Authorization and not for Authentication.
For Authentication, seems that exists something else called OpenIDConnect, so the first question that comes to my mind, and on which I cannot find an easy answer is: are OAuth, OpenIDConnect and IdentityServer related technology?
Which is the best solution for authentication, considering that I would like to create users in a SqlServer Database, and if it's possible I would like to use Entity Framework for the porpose?
The flow for my authentication would be:
User writes Username and Password, if they are right he receive the JWT Token, without redirecting him/her to the authorization page.
At this point the problem are:
which is the right endpoint to do this flow:
is it the /authorize or the /token endpoint?
I have a lot of confusion for the questions above.
The second thing, what is the best way to retrieve the user informations?
For example if my endpoint needs to understand from the logged in user what are his data, I think that or I retrieve from the endpoint or from the JWT token.
Even here I have no clue on which is the best.
I read that OAuth is created for Authorization and not for Authentication. For Authentication, seems that exists something else called OpenIDConnect, so the first question that comes to my mind, and on which I cannot find an easy answer is: are OAuth, OpenIDConnect and IdentityServer related technology?
That's right. OAuth was the first one introduced and allows the person requesting it access to the resources (its handing out access tokens). OIDC (OpenID Connect) on the other-side extends this concept by an identity, the authentication part.
The identity token verifies the identity of the person to your application. Instead of providing identity via username + password (i.e. user creating an account on your website), they get redirected to your authentication provider/app and enter their login there and you get an identity token in return (and/or an access token, depending on the flow and scopes you request).
The identity token is an JWT token (or reference token). The JWT token contains all of the users identity information required for your application (user id, email, displayname, age, etc.) and is cryptographically signed. Only the Identity Server knows the key used to sign it up and you can verify it with the public key from the OIDC (IdSrv here) provider.
Reference token works similar, but claims are requested on the server side and cached.
With identity token you can not access the users resources. Example: Facebook.
When you sign in your application with an facebook account, most page will only request identity token to verify that its the same user (instead of using a username / password combination). But with that one, the application can't access your facebook posts or do posts in your name.
If the application requests an access token (token scope), then also an access token will be returned (if the application is allowed to via allowed scopes). You will be asked to grant the permissions to the resources which the application requests.
With that token, the application can read your posts or post in your name.
Which is the best solution for authentication, considering that I would like to create users in a SqlServer Database, and if it's possible I would like to use Entity Framework for the porpose?
Doesn't really matter. Either one can be used, all you really need is the "sid" (subject id) claim and associate that one with your user.
Identity Server can issue both, depending on what the client asks (if client asks for id_token response type, it will receive an identity token, if it asks for token an access token. Both can be specified or just one).
At this point the problem are: which is the right endpoint to do this flow: is it the /authorize or the /token endpoint? I have a lot of confusion for the questions above.
/authorize is used to authorize the user (have him login, and send back to your website). Its used for so called interactive flows, where the user enters credentials
/token endpoint you can only retrieve a token (resource owner flow (username + password), client credentials (for machine to machine authentication), refresh token (to get a new access token by using an refresh token (if you asked for offline_access scope, which gives and refresh token)
The second thing, what is the best way to retrieve the user informations?
the /userinfo endpoint, see docs: http://docs.identityserver.io/en/latest/endpoints/userinfo.html
As the doc says to access that, the client needs to request the openid scope.
For example if my endpoint needs to understand from the logged in user what are his data, I think that or I retrieve from the endpoint or from the JWT token.
Yes you can retrieve it from JWT token, if you use JWT token. If you use reference token, its just an ID.
And last but not least the /introspection endpoint can be used to validate the token (if your consuming application has no libraries to decrypt and validate signature of the token.
If you can, its best to use the Identity Server client libraries (i.e. IdentityServer4.AccessTokenValidation package for ASP.NET Core or oidc-client for npm/javascript based applications) which should be picking up the correct endpoints, so you don't have to worry about it

Azure client credentials grant oath not working in hybrid setup for Graph Mail API access

In hybrid setup if client credentials grant type is used to get token and if that token is used to get on-prem user messages (https://graph.microsoft.com/v1.0/users('onpremuser#onpremdomain.com')/messages/) using graph api it fails by providing UnknownError.
When debugged on IIS logs error shown was "This token profile 'V1S2SAppOnly' is not applicable for the current protocol." error_category="invalid_token".
However if authorization code grant or resource owner password credential (ROPC) grant if used to obtain token , we were able to get messages of on prem user using graph API.
Have attached screenshot of token for both. How to make client credentials grant work for on-prem user messages access using graph API (in hybrid setup) ?
Update
Update i went and edited web.config of rest in Exchange server to have V1S2SAppOnly in profiles. After that previous error is gone and new error is seen.
Bearer+client_id="00000002-0000-0ff1-ce00-000000000000",+trusted_issuers="00000001-0000-0000-c000-000000000000#ea6064aa-d6fc-48d3-abb8-1728e1f39e0b",+token_types="app_asserted_user_v1+service_asserted_app_v1",+error="invalid_token" 2000008;reason="The+token+should+have+valid+permissions+or+linked+account+associated+with+partner+application+'00000003-0000-0000-c000-000000000000'.";error_category="invalid_grant"
I think the problem is with the aud claim, i.e. the audience for token.
For the first token that you have shared
aud value is 00000002-0000-0000-c000-000000000000. This is the resource Id for Azure AD Graph API and not Microsoft Graph API. For Microsoft Graph API, you should be using https://graph.microsoft.com or Id 00000003-0000-0000-c000-000000000000
this token is probably the one where you used client credentials grant, as there isn't any user claim
For the second token that you have shared
aud value is https://graph.microsoft.com which is correct
this token is acquired in context of a user name anoop so I guess this is the one which is working for you.
What you want is:
Application with Client credentials => Graph API => Local Exchange.
This scenario isn't supported out-of-the-box, but you can however tell your local exchange server to accept those tokens. See this answer https://stackoverflow.com/a/56131954/639153
In a nutshell, you need to change the authentication config of your front-end exchange servers to accept client credentials from the graph api. By default only delegated credentials are supported, and these settings are not documented on the exchange side.
Warning, we tested these settings, and it's working but not supported by Microsoft
This is the blog where I've found the answer to your question. https://blog.thenetw.org/2019/05/13/using-client_credentials-with-microsoft-graph-in-hybrid-exchange-setup/

What is the difference between 0Auth and JWT in Azure AD the best practice for using access tokens in Azure AD?

I am a newbie to Azure AD. What is the best practice for using Azure AD access tokens?
What is the difference between an 0Auth and JWT token and which one should I use to follow best practices?
I used the below code to get the Token. Do I need to convert it to an 0Auth Token?
var AzureData = await DependencyService.Get<IAuthenticator>()
.Authenticate(App.tenanturl, App.GraphResourceUri, App.ApplicationID, App.ReturnUri);
App.AuthenticationResult = AzureData;
var userToken = Azuredata.AccessToken;
Please help. Thanks.
JWT is a type of Token, and OAuth is a Framework.
JWT (JSON Web Tokens) is just a token format, it defines a compact and self-contained mechanism for transmitting data between parties in a way that can be verified and trusted because it is digitally signed.
Oauth is an authentication framework, where it has a general procedures and setups defined by framework. JWT can be used as a mechanism inside OAuth. You do not need to convert your token.
Use JWT when...
Federation is desired. For example, you want to use Azure AD as the token issuer, and then use Apigee Edge as the token validator. With JWT, an app can authenticate to Azure AD, receive a token, and then present that token to Apigee Edge to be verified. (Same works with Google Sign-In. Or Paypal. Or Salesforce.com. etc)
Asynchrony is required. For example, you want the client to send in a request, and then store that request somewhere, to be acted on by a separate system "later". That separate system will not have a synchronous connection to the client, and it may not have a direct connection to a central token dispensary. a JWT can be read by the asynchronous processing system to determine whether the work item can and should be fulfilled at that later time. This is, in a way, related to the Federation idea above. Be careful here, though: JWT expire. If the queue holding the work item does not get processed within the lifetime of the JWT, then the claims should no longer be trusted.
Use OAuth when...
There is no federation. The issuer of the token is the same party that validates the token. All API requests bearing the token will go through the token dispensary.
There is no need or desire to allow the holder of the token to examine the claims within the token.
When you wish to unilaterally allow token revocation. It is not possible to revoke JWT. They expire when they are marked to expire at creation time.
See this thread for more details.

What happens during a AcquireTokenAsync call using the client certificate?

In Azure AD, when we make a call such as AuthenticationContext.AcquireTokenAsync(resource, new ClientAssertionCertificate(_clientId, _cert)) it is not clear what exactly happens.
What part of the certificate gets exchanged if any?
Is there a challenge/response taking place?
Is the private key needed on the client as a part of this?
There are two ways you could go about finding the answer to you questions. One would be to look at the Microsoft Active Directory Authentication Library (ADAL) for .NET source code on GitHub, since this is open-source. The other (which we'll do here) is to looking at the network request that AcquireTokenAsync(String, ClientAssertion) generates, and work backwards from there.
Using Fiddler (or any other traffic analyzer), we can see something like the following (formatted for readability):
POST https://login.microsoftonline.com/{tenant-id}/oauth2/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&resource=https%3A%2F%2Fgraph.windows.net
&client_id={app-id}
&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
&client_assertion=eyJhbGciOiJSUzI1N...VE8wHSf-HZvGQ
Breaking it down:
grant_type=client_credentials tells us this is a token request using the OAuth 2.0 Client Credentials Grant flow.
resource=https%3A%2F%2Fgraph.windows.net gives the URI of the resource the client is requesting an access token for. In this case, it's for the Azure AD Graph API.
client_id={app-id} is the client identifier. In Azure AD, this is the app ID of the application that was registered.
The presence of client_assertion_type and client_assertion are indicative that the client is using an assertion to authenticate:
client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer says that client assertion being used is a signed JSON Web Token (JWT).
client_assertion=eyJhbGciOiJSUzI1N...VE8wHSf-HZvGQ is the aforementioned signed JWT token. The authorization server (e.g. Azure AD) will validate the contents, and check that the token was indeed signed by the certificate authorized for the client in question.
So, what ADAL does is:
Construct a token with a set of claims about the client (your app)
Use your certificate's private key to generate a cryptographic signature of those claims
Bundle that up into a signed JWT
Make an appropriately formed token request to the authority
During AcquireTokenAsync, only the certificate's thumbprint is provided (it's included in the JWT header to help the authorization server look up the corresponding public key). The JWT's signature is what proves that the client is in possession of the private key. However, before AcquireTokenAsync(String, ClientAssertion) can be used successfully, the client owner (i.e. you) needs to have provided Azure AD with the certificate's public key.
There is no challenge/response taking place here. The token is obtained in a single request, initiated by the client.
For a lot more detail, you can review the standards that this all implements:
RFC 6749: The OAuth 2.0 Authorization Framework
RFC 7521: Assertion Framework for OAuth 2.0 Client Authentication and Authorization Grants
RFC 7523: JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants
RFC 7519: JSON Web Token (JWT)
(Note that ADAL has a cache. Everything I described above will take place only if ADAL does not find a valid access token in the token cache. You can use AuthenticationContext.TokenCache.Clear() to clear the cache for experimentation.)

Resources