Auth0 - get id_token from refresh_token - oauth

In our 7+ microservices we rely on the Auth0 id_token. When exchanging a refresh_token (POST myapp.auth0.com/oauth/token) I only get back an access_token and not a id_token.
How do I exchange a refresh_token for an id_token with Auth0's API?

Technically the refresh_token grant type is part of OAuth 2.0 and the id_token is part of OpenID Connect, an identity protocol built on top of OAuth 2.0.
The refresh_token grant type of OAuth 2.0 allows for renewing access tokens (only). OpenID Connect doesn't define additional behavior beyond that for a good reason: the id_token is defined as the result of a user authentication event and a "authentication refresh" without user interaction can thus not result in a new id_token. The user may have left, logged out or his/her account removed in the mean time.
Refreshing an id_token should be done by sending the user to the OpenID Connect Provider again, not by using a refresh token autonomously.

It appears the refresh token grant is for Auth0's new API Authorization feature. The endpoint I was looking for was /delegation.
Example Node.js code:
const tokenClient = axios.create({
baseURL: `https://${env.AUTH0_DOMAIN}`,
headers: {
'content-type': 'application/json'
}
})
const refreshTokenClient = {
getAccessToken: (refreshToken) => {
// The official Node.js SDK for Auth0 does not
// support this it would seem (it forces passing id_token)
return tokenClient.post('/delegation', {
client_id: env.AUTH0_CLIENT_ID,
target: env.AUTH0_CLIENT_ID,
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
refresh_token: refreshToken,
scope: 'openid',
api_type: 'auth0'
}).then(r => r.data)
}
}

Related

OAuth using login.microsoft.com returns inconsistent tokens

I'm using office-js-helpers Authentication library. Using the Microsft Azure AD 2.0 Converged auth endpoint, I have tested logins from both a AD user (belonging to an AD tenant) and a ...#gmail.com account registered with Microsoft.
They both return a similar payload, with an access_token property. The major difference is that for the AD user the access_token is a signed JWT, whereas for the non AD account the access token is a base64 encoded (and possibly encrypted/encoded) string.
I can use either token for other Microsoft APIs like the Graph API, so I'm not pointing out an error. However I was hoping to use the access_token as a JWT for my own API.
Is there any way to force the converged auth service to return a JWT for all logins?
Has anyone dealt with this and come up with a sensible workaround?
While MSA accounts don't return a JWT based access_token, you can request a JWT based id_token using OpenID Connect.
The simplest way to think of the OpenID flow is as a variation on the OAuth 2.0 Authorization Code grant. It uses the same general model with a few additional parameters.
When making the initial provider call:
Add id_token to your response_type query parameter.
Add openid, email, and profile to the scope query parameter
The final result should look something like this:
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?
client_id={ID}&response_type=id_token+code&
redirect_uri={URI}&scope=openid+email+profile+offline_access+user.read
You then complete the same workflow you're using today with the Authorization Code grant. The final step, however, will now include an additional id_token property in the JSON payload:
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...",
"token_type": "Bearer",
"expires_in": 3599,
"scope": "https%3A%2F%2Fgraph.microsoft.com%2Fmail.read",
"refresh_token": "AwABAAAAvPM1KaPlrEqdFSBzjqfTGAMxZGUTdM0t4B4...",
"id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJhdWQiOiIyZDRkMTFhMi1mODE0LTQ2YTctOD...",
}
This id_token will also be a JWT based token and can be easily decoded just like you're doing with the JWT access_token you're getting back from AAD.

Azure AD: Need to validate id_token received with access token?

I'm doing authorization with Azure AD (using /oauth2/v2.0/authorize) with these scopes:
openid email profile https://graph.microsoft.com/user.read
In response, I get an id_token and an authorization code. I ignore this id_token and use the authorization code to get an access token (using /oauth2/v2.0/token)
When I get the access token, I again get an id_token along with it.
The Microsoft docs state:
When your app receives an ID token, it must validate the signature to prove the token's authenticity and validate a few claims in the token to prove its validity.
But since my app received the ID token based on its own HTTPS post to a Microsoft server, is it safe to use the ID token without validating it?
According to what you have described,
You are using OpenID Connect
You are using the hybrid flow (with response_type=code id_token)
If you are not expecting an id token from authorization request, you can use use other either Authorization code flow or Implicit flow
These flow types are selected from response_type parameter and not from claims.
For authorization code flow,
response_type=code
For Implicit flow,
response_type=id_token token or response_type=id_token
Note that, implicit flow does not produce an access token and is intended for JavaScript or similar clients which cannot protect a refresh token.
Once you get the id token from the token endpoint or from authorization endpoint(based on implicit flow), you can validate it just once.

Incorrect audience claim using AppAuth for iOS and Azure AD

I'm developing an iOS app which requires users to authenticate against an Azure AD (not B2C) and then use the JWT token to call a WebAPI.
I'm using the AppAuth library:
OIDAuthorizationService.discoverConfiguration(forDiscoveryURL: url) { configuration, error in
...
}
And then
let request = OIDAuthorizationRequest(configuration: configuration, clientId:<NativeApp AppID>, scopes: [OIDScopeOpenID], redirectURL: redirectURL, responseType: OIDResponseTypeCode, additionalParameters: ["resource": "<WebAPI AppID>"])
OIDAuthState.authState(byPresenting: request, presenting: presentingViewController) { state, error in
...
}
But the problem is, my JWT token's audience claim has the AppID of my client, and not the AppID of the WebAPI, even though I'm passing the resource parameter with the WebAPI AppID.
As a result, my WebAPI is rejecting the JWT token as the audience claim is incorrect.
What do I need to do to have my JWT token's audience claim to be the WebAPI's AppID?
When requesting access to another resource Azure AD returns you an ID token and an access token. I was using the ID token, which always has it's audience claim set to your client. Using the access token (which is also a JWT token) has the correct audience claim for the resource you're requesting access to.

OAuth Client Credential Flow - Refresh Tokens

The Scenario
I've recently built an API, and have protected its resources using OAuth Bearer Access Tokens.
I've used the Client_Credentials Flow, as it will be accessed by clients as opposed to users.
Here's the thing, when a client has successfully provided the client_id and the client_secret they receive a response like the following :-
{
"access_token": "<Access Token>",
"token_type": "bearer",
"expires_in": 1199,
"refresh_token": "<Refresh Token>"
}
Refresh Tokens.
Not knowing much about refresh tokens, i immediately assumed that a client would be able to provide the OAuth Server the refresh_token to retrieve a fresh Access_Token.
This is 'kind of' correct.
In order to use the refresh_token the client still needs to pass the client_id and client_secret along with the refresh_token to get a new access token.
The grant_type also needs to be changed to refresh_token.
Where is the benefit of a refresh_token using this flow? If I need to pass the client_id and client_secret each time, surely you would just avoid using a refresh token altogether?
The issuance of a refresh token with the client credential grant has no benefit.
That is why the RFC6749 section 4.4.3 indicates A refresh token SHOULD NOT be included. Thus its issuance is at the discretion of the authorization server.
From my point of view an authorization server should never issue a refresh token with the client credentials grant as the access token issuance process will take an additional and unnecessary step:
The issuance of he access token with the client_credentials grant type is done on the first request.
The issuance of he access token with the refresh_token grant type is done after at least two requests, depending on the way you issued to first access token.
The benefit is that he request token normally has a much longer life span than the access token.
Access token is used in communicating with the resource server.
Request token is used when communicating with the authorization server.
You could read this as that you may be authorized but that the exact extend of your authorization needs to be reevaluated from time to time. So request token has it use.

DocuSign OAuth Flow

I am implementing DocuSign's OAuth flow by following OAuth2 Authentication Support in DocuSign REST API
According to the documentation, in order to carry out the OAuth Token Request the client application should show a UI to prompt the user for email/password and is responsible to keep the information confidential and not store it locally.
I would like to know if DocuSign supports OAuth in the manner where the client application does not take hold of the user's email and password and is just concerned with the authentication token of the user.
The DocuSign Developer Center has some info on the OAuth process on their SOBO (Send-On-Behalf-Of) feature page. Check out Explore -> Features -> SOBO.
It's pretty easy to request an access token, just make the following call:
URL
https://{server}/restapi/{apiVersion}/oauth2/token
METHOD
POST
BODY
grant_type=password&client_id={IntegratorKey}&username={email}&password={password}&scope=api
For the body make sure you replace IntegratorKey, email, and password with your credentials.
A successful call will generate the following response:
{
"access_token": "<access token for user>",
"scope": "api",
"token_type": "bearer"
}
And finally, you can then use that access token in subsequent api calls using the Authorization: bearer header like so:
Authorization: bearer <access_token>
One important thing to remember is that you are only allowed 10 OAuth tokens in your account (which can be seen on the Preferences -> Connected Apps screen in the DocuSign Console). If you have 10 and request a new token the call will fail, you'll need to revoke an existing one in that case if you want to create a new one.
According to the DocuSign documentation, it supports two grants: (1) the Resource Owner Password Credentials Grant and (1) the SAML2 Grant, which is an extension to the base OAuth2 spec. Neither of these grants issue an authentication token. In the first grant, the resource owner must share his credentials with the client application. In the second grant, the resource owner approves access by the client application in advance. The client app generates a SAML assertion which is validated by the authorization server and (if the assertion is valid) is issued an access token.
The authentication token is used only by the Authentication Code Grant which, according to the DocuSign documentation, is not supported.

Resources