What happens during a AcquireTokenAsync call using the client certificate? - azure-active-directory

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.)

Related

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

Unable to get Access token in microsoft Oauth 2.0

I am developing the integration for Microsoft One Note with third party application using OAuth 2.0
And I have successfully authorised my Microsoft O365 account and provided my consent, but unable to get access token after the successful authorisation.
Error Message looks like : Invalid client secret is provided.
Timestamp: 2019-03-19 07:52:28Z
One Note Documentation : enterprise notebooks on Office 365 integration
As the document states format should be like below
POST https://login.live.com/oauth20_token.srf
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&client_id={client-id} // Your Azure portal register application ID
&client_secret={client-secret} // Key Of same registered application
&code={code}
&redirect_uri={redirect-uri}
You are providing invalid client secret key while you are requesting API
See the screen shot below and make sure you are providing right one
Note:
Check your EXPIRES of key as never expires
Update:
In your case you have to follow two step to get your access token
First need to get authorization code
Request for token with that authorization code
Authorization code request sample
Token Request sample with authorization code

How to obtain the attributes of a saml response sent by Azure Active Directory?

I have a saml response that gives me azure active directory when doing the process with saml 2.0, the whole process is done normally, I send a saml request and the azure active directory returns the saml response, to do the whole process I have based on this guide, I've been reading a bit and I've noticed that Azure AD in the saml response sends the values within this tag:
<xenc:CipherData>
<xenc:CipherValue>VALUE HERE</xenc:CipherValue
</xenc:CipherData>
And not inside:
<AttributeStatement><Attribute Name="IDPEmail"><AttributeValue>administrator#contoso.com</AttributeValue></Attribute></AttributeStatement>
as specified in the documentation. The question is, how to get the true values that azure active directory is sent to me and not these encoded values, I am using Python 3 and Google App Engine, in addition to mentioning azure active directory and saml 2.0 to do the login process, I leave the SAML response complete in this url in case it serves to give a better context to my question.
As mentioned above, the SAML response you are getting is encrypted. Specifically Azure is encrypting its assertions (including the ones you are looking for) inside an encrypted body called CipherData.
You have two options:
1 - Disable SAML response encryption.
Azure AD calls SAML response encryption as SAML token encryption which is a bit confusing. You can follow this guide to disable the response. You must have uploaded an encryption public key/cert before.
2 - Configure your service provider to supported encrypted SAML responses.
The SAML token is encrypted.
You need to get the client side certificate used for this and use that to decrypt it.

Do IdentityServer4 API Resources require a secret?

Does not having a secret defined for an IdentityServer4 API Resource introduce a security vulnerability?
I'm a little confused on the Introspection Endpoint, when it is used, and whether or not someone could use the Introspection endpoint to bypass Authorization and access an API without a defined secret (by a POST with just the API name as a parameter).
Is this possible? Or is the introspection endpoint only authorized through defined clients that use something like the Client Credential Grant?
The introspection endpoint will only validate a posted token, it shouldn't accept an API name in its request.
It can be used to validate reference tokens (or JWTs if the consumer does not have support for appropriate JWT or cryptographic libraries). The introspection endpoint requires authentication using a scope secret.
http://docs.identityserver.io/en/release/endpoints/introspection.html
This shouldn't be an endpoint you need to implement, it is included by identity server in the same way as the '.well-known/openid-configuration'.
A use case for this endpoint would be an API being passed a token and wanting to confirm its genuine and still valid (not expired or revoked), the response would include the claims associated with the token (users claims with the tokens scope taken into consideration)
For introspection security considerations see the RFC 7662 Section 4
An API Resource requires a Client Secret when you are using the Authorization Code Flow as its sending claims on the back channel.
If you are using Reference tokens you will also require a Client Secret, as the access token is never presented to the client, but instead the reference token is passed from the client to the api resource, and then onto the identity server in exchange for the access token.
It really depends on the client and the flow.

How to interact with back-end after successful auth with OAuth on front-end?

I want to build small application. There will be some users. I don't want to make my own user system. I want to integrate my application with oauth/oauth2.0.
There is no problem in integration of my front-end application and oauth 2.0. There are so many helpful articles, how to do this, even on stackoverflow.com. For example this post is very helpful.
But. What should I do after successful authorization on front-end? Of course, I can just have flag on client, which says "okay, mate, user is authenticated", but how I should interact with my backend now? I can not just make some requests. Back-end - some application, which provides API functions. EVERYONE can access this api.
So, I need some auth system anyway between my FE and BE. How this system should work?
ps I have some problems with English and may be I can not just correctly 'ask google' about it. Can you provide correct question, please :) or at least give some articles about my question.
UPD
I am looking for concept. I don't want to find some solution for my current problem. I don't think it is matters which FE and BE I use (anyway I will
provide information about it below)
FE and BE will use JSON for communication. FE will make requests, BE will send JSON responses. My application will have this structure (probably):
Frontend - probably AngularJS
Backend - probably Laravel (laravel will implement logic, also there is database in structure)
Maybe "service provider" like google.com, vk.com, twitter.com etc remembers state of user? And after successful auth on FE, I can just ask about user state from BE?
We have 3 main security concerns when creating an API.
Authentication: An identify provider like Google is only a partial solution. Because you don't want to prompt the user to login / confirm their identity for each API request, you must implement authentication for subsequent requests yourself. You must store, accessible to backend:
A user's ID. (taken from the identity provider, for example: email)
A user token. (A temporary token that you generate, and can verify from the API code)
Authorization: Your backend must implement rules based on the user ID (that's your own business).
Transport security: HTTPS and expiring cookies are secure and not replayable by others. (HTTPS is encrypting traffic, so defeats man-in-the-middle attacks, and expiring cookies defeats replay attacks later in time)
So your API / backend has a lookup table of emails to random strings. Now, you don't have to expose the user's ID. The token is meaningless and temporary.
Here's how the flow works, in this system:
User-Agent IdentityProvider (Google/Twitter) Front-End Back-End
|-----------------"https://your.app.com"---------->|
|---cookies-->|
your backend knows the user or not.
if backend recognizes cookie,
user is authenticated and can use your API
ELSE:
if the user is unknown:
|<--"unknown"-|
|<----"your/login.js"----------+
"Do you Authorize this app?"
|<------------------+
|--------"yes"----->|
+----------auth token--------->|
|<---------/your/moreinfo.js---|
|-------access_token ---------->|
1. verify access token
2. save new user info, or update existing user
3. generate expiring, random string as your own API token
+----------->|
|<-------------- set cookie: your API token --------------------|
NOW, the user can directly use your API:
|--------------- some API request, with cookie ---------------->|
|<-------------- some reply, depends on your logic, rules ------|
EDIT
Based on discussion - adding that the backend can authenticate a user by verifying the access token with the identity provider:
For example, Google exposes this endpoint to check a token XYZ123:
https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=XYZ123
I read through all the answers very carefully, and more than half the people who responded are missing the question completely. OP is asking for the INITIAL connection between FE & BE, after the OAuth token has been issued by the Service Provider.
How does your backend know that the OAuth token is valid? Well keep in mind that your BE can send a request to the Service Provider & confirm the validity of the OAuth token, which was first received by your FE. This OAuth key can be decrypted by the Service Provider only because only they have the secret key. Once they decrypt the key, they usually will respond with information such as username, email and such.
In summary:
Your FE receives OAuth token from Service Provider after user gives authorization. FE passes OAuth token to BE. BE sends OAuth token to Service Provider to validate the OAuth token. Service Provider responds to BE with username/email information. You can then use the username/email to create an account.
Then after your BE creates the account, your BE should generate its own implementation of an OAuth token. Then you send your FE this OAuth token, and on every request, your FE would send this token in the header to your BE. Since only your BE has the secret key to validate this token, your application will be very safe. You could even refresh your BE's OAuth token on every request, giving your FE a new key each time. In case someone steals the OAuth token from your FE, that token would be quickly invalidated, since your BE would have already created a new OAuth token for your FE.
There's more info on how your BE can validate the OAuth token. How to validate an OAuth 2.0 access token for a resource server?
let's use OAuth concept to begin,FE here is Client , BE here is Resource Server.
Since your client already authorized, Authorization server should grant
Access token to the client.
Client make request to the resource server with the Access token
Resource server validate the Access token, if valid, handle the request.
You may ask, what is the Access token, Access token was issued by authorization server, grant to client, and recognized by resource server.
Access token is a string indicate the authorization information(e.g. user info, permission scope, expires time...).
Access token may encrypted for security, and you should make sure resource server can decrypt it.
for more details, please read OAuth2.0 specification https://www.rfc-editor.org/rfc/rfc6749.
Well you don'y need User-System on your Front End side.
The front end is just a way to interact with your server and ask for token by valid user and password.
Your server supposed to manage users and the permissions.
User login scenario
User asking for token by entering his username and password.
The server-API accept the request because it's anonymous method (everyone can call this method without care if he's logged in or not.
The server check the DB (Or some storage) and compare the user details to the details he has.
In case that the details matches, the server will return token to the user.
From now, the user should set this token with any request so the server will recognize the user.
The token actually hold the user roles, timestamp, etc...
When the user request for data by API, it fetch the user token from the header, and check if the user is allowed to access that method.
That's how it works in generally.
I based on .NET in my answer. But the most of the BE libaries works like that.
As am doing a project for SSO and based on my understanding to your question, I can suggest that you create an end-point in your back-end to generate sessions, once the client -frontend- has successfully been authorized by the account owner, and got the user information from the provider, you post that information to the back-end endpoint, the back-end endpoint generates a session and stores that information, and send back the session ID -frequently named jSessionId- with a cookie back to the client -frontend- so the browser can save it for you and every request after that to the back-end considered an authenticated user.
to logout, simply create another endpoint in the back-end to accepts a session ID so the back-end can remove it.
I hope this be helpful for you.
You need to store the token in the state of your app and then pass it to the backend with each request. Passing to backend can be done in headers, cookies or as params - depends on how backend is implemented.
Follow the code to see a good example of all the pieces in action (not my code)
This example sets the Authorization: Bearer TOKEN header
https://github.com/cornflourblue/angular-registration-login-example

Resources