问题
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