Refresh tokens in oauth2 should not be replaced when getting a new access token

自作多情 提交于 2019-12-06 01:34:05

问题


Is the statement in the title correct? I'm basing the question on the work done by Taiseer Joudeh (thanks for your work on this subject, btw) at http://bitoftech.net/2014/07/16/enable-oauth-refresh-tokens-angularjs-app-using-asp-net-web-api-2-owin/.

If I understand the behavior of refresh tokens correctly, when an access token expires, we should call the token endpoint of our auth server with something like

'grant_type=refresh_token&refresh_token=' + token

and we will get back a new access token. That request will have a refresh token as part of the payload, but shouldn't that refresh token be the same one we just used? Or at the very least, it should have the same expiration? If not, then really, the refresh lifetime is infinite.

Here are the the frisby.js tests I would expect to pass, but using Taiseer's implementation for Web Api 2, the final expectation fails. We get a new refresh token with a new expiration on that token.

'use strict';

var frisby = require('frisby');
var config = require('../test-config.json');

var args = config[process.env.test || 'local'];
var host = args.host,
    clientId = args.clientId,
    usr = args.user1,
    pwd = args.password1;

frisby.create('Try and fail to get a protected resource')
    .get(host + '/api/test')
    .expectStatus(401)
    .expectHeaderContains('WWW-Authenticate', 'bearer')
    .toss();

frisby.create('Log in and get a protected resource')
    .post(host + '/token', {
        grant_type: 'password',
        username: usr,
        password: pwd,
        client_id: clientId
    })
    .expectJSONTypes({
        access_token: String,
        token_type: String,
        expires_in: Number,
        userName: String,
        refresh_token: String,
        'as:client_id': String,
        '.issued': String,
        '.expires': String
    })
    .expectJSON({
        token_type: 'bearer',
        userName: 'test2@test.com'
    })
    .afterJSON(function (json) {
        frisby.create('and now get protected resource with attached bearer token')
            .get(host + '/api/test', {
                headers: { 'Authorization': 'Bearer ' + json.access_token }
            })
            .expectStatus(200)
            .toss();
        frisby.create('and try to get a new access token with our refresh token')
            .post(host + '/token', {
                grant_type: 'refresh_token',
                refresh_token: json.refresh_token,
                client_id: clientId
            })
            .afterJSON(function (json2) {
                //we should receive a new access token
                expect(json.access_token).not.toEqual(json2.access_token);
                //but shouldn't the refresh token remain the same until *it* expires?
                expect(json.refresh_token).toEqual(json2.refresh_token);
            })
            .toss();
    })
    .toss();

回答1:


You are 100% correct, the current implementation of refresh token has sliding expiration for the refresh token because with each use for grant_type=refresh_token we are issuing new access token and refresh token identifier, and this was perfect for my case because I want the user to be logged in forever as long as he is using the application, if he didn't use the application for a period greater then the expiration date for the refresh token then he will receive 401 when he tries to obtain new access token using the refresh token.

To change this behavior you need to issue only single refresh token identifier and return the same identifier when the user asks for new access token using the refresh token. And you can do this by customizing the business logic in this method and this too.



来源:https://stackoverflow.com/questions/27725304/refresh-tokens-in-oauth2-should-not-be-replaced-when-getting-a-new-access-token

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!