I am using ZF2 Apigility and am working on setting up an OAuth2 workflow for an API I am writing.
So far I can get the following to work:
Call the API and get a token
{
"access_token": "62f6109dcbce42b38f9117b21529faf30fc0ee86",
"expires_in": 3600,
"token_type": "Bearer",
"scope": null
}
Now I know I need to use this token in the headers of my next request in order to access my API.
I am just not sure how to go about doing this with PostMan?
Click on Headers
then add
Authorization
as Header
and
Bearer 62f6109dcbce42b38f9117b21529faf30fc0ee86
as Value
Related
According to step 3 "Get a token" in https://learn.microsoft.com/en-us/graph/auth-v2-user
The API should return,
{
"token_type": "Bearer",
"scope": "user.read%20Fmail.read",
"expires_in": 3600,
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...",
"refresh_token": "AwABAAAAvPM1KaPlrEqdFSBzjqfTGAMxZGUTdM0t4B4..."
}
but it is returning, [Refresh token missing]
{
"token_type": "Bearer",
"scope": "user.read Fmail.read",
"expires_in": 3599,
"ext_expires_in": 3599,
"access_token": "eyJ0eXAiOiJKV1QiLCJub25jZ9...."
}
Can you please help with what am I missing?
You have to add offline_access to the scope to get a refresh token:
With the Microsoft identity platform endpoint, permissions are
requested using the scope parameter. In this example, the Microsoft
Graph permissions requested are for User.Read and Mail.Read, which
will allow the app to read the profile and mail of the signed-in user.
The offline_access permission is requested so that the app can get a
refresh token, which it can use to get a new access token when the
current one expires.
Source
We are not receiving the refresh_token when requesting the token despite the documentation says that always you request a token you will receive a refresh token.
Might be accidentally missing/misunderstanding something ?
This is a piece of the code we are using:
var app = ConfidentialClientApplicationBuilder.Create("...")
.WithAuthority(AzureCloudInstance.AzurePublic, "...")
.WithClientSecret(CLIENTSECRET)
.Build();
AuthenticationResult result = await app.AcquireTokenForClient(ewsScopes)
.ExecuteAsync();
And here is the reference to the documentation that we are basing our expectation on:
https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-configurable-token-lifetimes#refresh-tokens
Refresh tokens
When a client acquires an access token to access a protected resource, the client also receives a refresh token.
You are using Client Credentials flow here in your code here to acquire the token.
See here for documentation - IConfidentialClientApplication.AcquireTokenForClient(IEnumerable) Method
AuthenticationResult result = await app.AcquireTokenForClient(ewsScopes)
.ExecuteAsync();
Read here about the Client Credentials flow in more detail, and specifically what a successful response looks like in this case, which is only expected to have an access_token and no refresh_token.
{
"token_type": "Bearer",
"expires_in": 3599,
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1uQ19WWmNBVGZNNXBP..."
}
A different flow, like Authorization Code flow (usually used by web apps) returns back an access_token as well as a refresh_token.
You can read more about that flow and a response in that case here - Authorization Code Flow
{
"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...",
}
Steps.
1. GET https://<canvas-install-url>/login/oauth2/auth?client_id=XXX&response_type=code&redirect_uri=https://example.com/oauth_complete&state=YYY&scope=<value_1>%20<value_2>%20<value_n>
2. POST /login/oauth2/token [grant_type=authorization_code]
Response:
{
"access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
"token_type": "Bearer",
"user": {"id":42, "name": "Jimi Hendrix"},
"refresh_token": "tIh2YBWGiC0GgGRglT9Ylwv2MnTvy8csfGyfK2PqZmkFYYqYZ0wui4tzI7uBwnN2",
"expires_in": 3600
}
3. POST /login/oauth2/token [grant_type=refresh_token]
Response:
{
"access_token": "new_1/fFAGRNJru1FTz70BzhT3Zg",
"token_type": "Bearer",
"user": {"id":42, "name": "Jimi Hendrix"},
"refresh_token": "tIh2YBWGiC0GgGRglT9Ylwv2MnTvy8csfGyfK2PqZmkFYYqYZ0wui4tzI7uBwnN2",
"expires_in": 3600
}
From step 2:
"access_token": "1/fFAGRNJru1FTz70BzhT3Zg" - using this token returns an invalid access token error
From step 3:
"access_token": "new_1/fFAGRNJru1FTz70BzhT3Zg_new" - works!
My question is,
Is this the expected behaviour?
or
Should the access token from step 2 be valid until it expires(3600s)?
No When you use the refresh token and refresh it will generate a new access token and attach to the refresh token. Old access tokens will no longer work after that.
Expires in is a maximum TTL of the access token after which refresh is compulsory but there is no minimum threshold for refreshing an access token.
(I wanted to respond to your comment in shazin's answer. But I have no reputation :( )
AFAIK The old access token is invalidated when the refresh token is used to get a new access token.
I briefly looked at the OAuth2 Spec but could not find anything saying that the old access token is invalidated when the refresh token is used. Perhaps because it is assumed the refresh token is only used when the access token is invalid.
Anyway perhaps these 2 references from the spec will help.
Refresh token
Refreshing an Access Token
In the documentation at https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols-oauth-code
... it states that a successful response to a token request looks like:
{
"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...",
}
After the first step of authentication completes, I receive a code on the redirect and use it to request a token.
However, I only receive this:
{
"token_type": "Bearer",
"id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJhdWQiOiIyZDRkMTFhMi1mODE0LTQ2YTctOD...",
}
My scope is set to openid email profile.
Why do I not receive the access_token?
Access token will be returned only when resource specific scopes are requested, so that it can used to access the protected resource. Try including a scope like "https://graph.microsoft.com/mail.read" as indicated in sample present in the documentation link posted with the question.
Is is possible to obtain the scope(Google API's) an Oauth token can access??
I have tried searching for it but no luck.
However facebook has something called as access token debugger which does the job does google have something similar to it ?
you can call Google's tokeninfo endpoint, as in:
curl https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=<access_token>
and get back something similar to:
{
"issued_to": "<>
"audience": "<>
"user_id": "<>
"scope": "https://www.googleapis.com/auth/plus.me",
"expires_in": 3245,
"access_type": "offline"
}