How do I handle OAuth refresh token? - security

When I authorize on my OAuth server it returns me access / refresh tokens:
access_token: "ZjJlMGM2MDcxNDg5MDQ1NzA4ZjkyNzRiOTIwM2E5MWI4N2M0MWU0ZD..."
expires_in: 3600
refresh_token: "NWZjMzQ3YjNjMmY5YTEzYzMxMDYzNGVhNzRiNjAxZTdmZTdjNzE3z..."
scope: null
token_type: "bearer"
How do I use them in my client side javascript application?
Is it okay to save access token and refresh token in the cookies?
(is it safe? - but anyway I dont see any other place where I can
store them...)
I can request protected resources like this: /api/user?access_token=TOKEN . And when I access them I really get my protected data successful. But what will happen when this access token expired? Will it be automatically refreshed, or do I need to handle it manually?
Why do I need refresh token and when I should send it to the server?

three-legged ( User---client ---- Oauthserver)
1)In 3 legged authentication access Token is stored at the client side and is never transferred to the user.
two legged (user ----Oauthserver)
In 2 legged authentication the token is stored at the user side. Probably in the cookie.
2)When the token expires user explicitly has to use the refresh token to get a new auth token.
3) Each Auth token has an expiry and instead of reauthenticating itself with a username/password,User can present refresh Token to get a new valid Auth token.

Related

Does an id_token need to be stored, or can it just be used once to create a session?

I'm trying to implement Twitch login via the OIDC authorization flow, and am confused around how to correctly (and safely) use the id_token I get back. I know you should verify the authenticity of the token with Twitch before using it, but after that do I need to store the token somewhere for access on every request, or can I just use it once to initialize a session?
Pseudo-code for the logic where I don't store the id_token
id_token, access_token, refresh_token = twitchOIDCLogin()
verifyIdToken(id_token)
userId = extractUserId(id_token)
session.set({
userId: userId,
access_token: access_token,
refresh_token: refresh_token })
And then on subsequent requests, the user being "logged in" is solely determined by the sessionID cookie linking to a session in my session store.
Is this secure/correct, or should I be storing the id_token and verifying it on every request? And if so, should I then be forcing the user through the authentication flow again once the id_token expires?
The ID token often have a very short lifetime, like 5 minutes and after you have created your local session, you can just delete it as it has no further purpose.

Microsoft Graph API token expiring after 3600 seconds - NodeJS

I am using the Microsoft Graph API to generate oAuth 2.0 access token, which expires after 1 Hour. Route being used is: https://login.microsoftonline.com/[Tenant ID]/oauth2/v2.0/token
I am passing these values in the Query string.
{
grant_type: "client_credentials",
client_id: APP_ID,
client_secret: APP_PASSWORD,
scope: "https://graph.microsoft.com/.default",
}
Now, my current implementation I have added recursion in which I added retries before calling a graph api to extract user details from AD.
Is there a way I can get/fetch a refresh token, because refresh tokens last longer?
You need to follow the below steps to enable Refresh Tokens:
Request the scope 'offline_access'. This will tell the endpoint to provide a refresh_token along with the access_token and associated metadata.
You need to request a new access_token (and refresh_token as they come together) by repeating the same POST to /common/oauth2/v2.0/token with a slightly different body - grant_type is set to refresh_token and instead of a code, you supply a refresh_token property and value
For e.g.
POST /{tenant}/oauth2/v2.0/token
Host: https://login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
client_id=[client Id]
&scope=[scope]
&refresh_token=[refresh token]
&grant_type=refresh_token
&client_secret=[secret]
Please refer to the documentation here for refresh token request details.
In my view, use of refresh token along with client crendential flow is of no use. Why would you want to have an additional step added to get access token when you can get that straight away.
Flow with the client_credentials grant type:
Step 1: client authentication
OK access token is issued
Flow for obtaining Refresh_token
Step 1: client authentication
Step 2: Refresh token validation and use it to obtain access token
OK access token is issued.

Not able to handle Authorization using JWT

Im trying to create a protected route , once the user logs in user is issued a token and this token is checked when user tries to access a protected resource . Im able to generate the token and send it back as a response as the below code,
const token = jwt.sign({_id:found._id.toString()},process.env.KEY);
res.header('token', token );
res.render("dashboard");
So after a user is logged in , i go to the dashboard and i can see the response header where token is set as token .But when i try to navigate to the secret resource page the auth handler gets a request,but the request does not have a token in the header so im not able to verify it.
router.get('/secret',auth,function(req,res)
{
res.render('secret')
}
);
Trying to figure out how to set the token header correctly so it is issued and can verify it.
on client side, you should send token in header as authorization
after that, you can receive client's token on backend side using
req.get('Authorization')
and verify it using
jwt.verify

Security - JWT and Oauth2 (refresh token)

I have a angular client app and a .net web api server.
I'm trying to understand how to implement security in the best way using tokens.
I thought about few options, and I don't know which one is the best, or if there is a better way.
JWT with expiration
1.User login with credentials -> Server returns a JWT with expiration (for example 60 minutes from login time). Each valid request to the server within this 60 minutes the server returns a new JWT token with a new expiration of 60 minutes. If user didn't send server request for 60 minutes he must login again.
This solution is very similiar to sessions.
Oauth2 - I don't think I understand this protocol correctly, so I apologize if what I'm saying is not correct.
2.User login with credentials -> user gets a refresh_token and access_token.
For every request, the client attaches the access_token. If server returns 401 (unauthorized) the client uses the refresh_token to create a new access_token and re-send the failed request with the new token.
The problem in this flow, for me, is that I don't know if I got unauthorized because the token was invalid or the user tried to access unauthorized resources.
This led me to a third solution.
3.User login with credentials -> user gets a refresh_token, access_token and access_token_expiration. When the user wants to create a request to the server, he checks if access_token has expired. If expired, the client will request a new access_token with new expiration and only then perfroms the request.
And 2 more little question about auth2:
1.Why do I have a refresh_token and access_token? Both of them are stored in client local storage. Why not to always use the refresh_token? For the server it makes sense to have a refresh_token and access_token since the refresh_token is secured.
2.Does the refresh token have an expiration date?
If it does, how can I create a new refresh token?
If it doesn't, isn't it a little unsave to give the ability to stay connected forever?
Thank you very much for your help
Option 3, login with credentials and getting an access token, refresh token and expiration time is the usual way.
eg.:
{
"access_token": "eyJ0eXA....CqVJcc",
"token_type": "bearer",
"expires_in": 3599,
"refresh_token": "AQAAAN...H2JXjIUAQ"
}
the expiration time of the JWT access token can also be found in the token itself in the payload field exp, in form of a UNIX timestamp:
{
...
"exp": 1500547257,
"nbf": 1500543657
...
}
With that information you can implement your own mechanism to check if your access token is still valid and refresh it when necessary.
The refresh token usually also expires. When the refresh token is expired, you need to start again with the credentials.
Additionally you can read this for further information about the topic: https://auth0.com/learn/refresh-tokens/
And here is a tutorial that talks about handling of refresh tokens in Angular:
http://bitoftech.net/2014/07/16/enable-oauth-refresh-tokens-angularjs-app-using-asp-net-web-api-2-owin/

Why is my request for a new access token not returning a new refresh token?

I am using the following code, along with my refresh token, to request a new access token:
exports.getTokenFromRefreshToken = function (user, callback) {
request.post({
url:'https://login.microsoftonline.com/12345678-1234-1234-1234-2f189712345/oauth2/token',
form: {
grant_type: 'refresh_token',
refresh_token: refresh_token,
client_id: client_id,
client_secret: client_secret,
resource: 'https://graph.microsoft.com'
}
}, function(err, httpResponse, body) {
if (!err) {
var tokens = JSON.parse(httpResponse.body);
console.log('getTokenFromRefreshToken() tokens = ' + JSON.stringify(tokens));
callback(null, tokens);
}
})
};
The httpResponse includes everything that I get when I make the original token request (from the code), but without a new refresh token. I was under the impression that I would also receive a new refresh token. Is that not the case?
You get a new refresh token only when you are including the offline_access scope.
ref.: https://azure.microsoft.com/en-us/documentation/articles/active-directory-v2-scopes/
The offline_access scope gives your app access to resources on behalf of the user for an extended time. On the work account consent page, this scope appears as the "Access your data anytime" permission. On the personal Microsoft account consent page, it appears as the "Access your info anytime" permission. When a user approves the offline_access scope, your app can receive refresh tokens from the v2.0 token endpoint. Refresh tokens are long-lived. Your app can get new access tokens as older ones expire.
Refresh tokens aren't refreshed the same way you can get a new access token using the refresh token. When a refresh token expires, you will need to need to get the credentials and do the initial token acquisition again.
More info here: Refreshing an Access Token
It looks like it should work except you seem to be missing the redirect URI. I have a working version of this call but it includes this redirect_uri. It produces for me both a new access and refresh token.
--
http://graph.microsoft.io/en-us/docs/authorization/app_authorization
Renew expiring access token using refresh token
The redirect URL that the browser is sent to when authentication is complete. This should match the redirect_uri value used in the first request.
I had the exact same issue, caused a headache for a while until the problem was found.
Seems like you are probably logging in with a Guest MS account (previously known as Live) and thus getting a 12hr expiry refresh token with no rolling window.
You need to use a full MS account to get the refresh token back in the response body (which is a token that will last 14 days), with a rolling window of 90 days.
For as long as you use a Guest MSA you will not get a refresh token back. Your code is correctly structured as far as I can see, and I don't believe you need a redirect_uri header as stated above, they are optional fields according to doco.
For more information on the types of refresh tokens, see this blog post:
Azure tokens

Resources