Skip to content
This repository has been archived by the owner on Apr 3, 2019. It is now read-only.

Commit

Permalink
fix(tokens): invalidate refresh tokens on client-token DELETE action (#…
Browse files Browse the repository at this point in the history
…508)

Fixes #507
  • Loading branch information
vladikoff committed Dec 4, 2017
1 parent 9a95b3c commit df0ca82
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 11 deletions.
17 changes: 11 additions & 6 deletions lib/db/memory.js
Expand Up @@ -301,15 +301,20 @@ MemoryStore.prototype = {
return P.reject(new Error('clientId and uid are required'));
}

var ids = Object.keys(this.tokens);
for (var i = 0; i < ids.length; i++) {
var id = ids[i];
if (this.tokens[id].userId.toString('hex') === uid &&
this.tokens[id].clientId.toString('hex') === clientId) {
delete this.tokens[id];
function deleteToken(tokens) {
const ids = Object.keys(tokens);
for (let i = 0; i < ids.length; i++) {
const id = ids[i];
if (tokens[id].userId.toString('hex') === uid &&
tokens[id].clientId.toString('hex') === clientId) {
delete tokens[id];
}
}
}

deleteToken(this.tokens);
deleteToken(this.refreshTokens);

return P.resolve({});
},
generateRefreshToken: function generateRefreshToken(vals) {
Expand Down
14 changes: 13 additions & 1 deletion lib/db/mysql/index.js
Expand Up @@ -199,6 +199,8 @@ const QUERY_ACTIVE_CLIENT_TOKENS_BY_UID =
'LIMIT 10000;';
const DELETE_ACTIVE_TOKENS_BY_CLIENT_AND_UID =
'DELETE FROM tokens WHERE clientId=? AND userId=?';
const DELETE_ACTIVE_REFRESH_TOKENS_BY_CLIENT_AND_UID =
'DELETE FROM refreshTokens WHERE clientId=? AND userId=?';
// Scope queries
const QUERY_SCOPE_FIND =
'SELECT * ' +
Expand Down Expand Up @@ -468,10 +470,20 @@ MysqlStore.prototype = {
* @returns {Promise}
*/
deleteActiveClientTokens: function deleteActiveClientTokens(clientId, uid) {
return this._write(DELETE_ACTIVE_TOKENS_BY_CLIENT_AND_UID, [
const deleteTokens = this._write(DELETE_ACTIVE_TOKENS_BY_CLIENT_AND_UID, [
buf(clientId),
buf(uid)
]);

const deleteRefreshTokens = this._write(DELETE_ACTIVE_REFRESH_TOKENS_BY_CLIENT_AND_UID, [
buf(clientId),
buf(uid)
]);

return P.all([
deleteTokens,
deleteRefreshTokens
]);
},

generateRefreshToken: function generateRefreshToken(vals) {
Expand Down
31 changes: 27 additions & 4 deletions test/api.js
Expand Up @@ -2928,14 +2928,16 @@ describe('/v1', function() {

describe('DELETE /client-tokens/{client_id}', function() {

it('deletes all tokens for some client id', function() {
var user2ClientWriteToken;
it('deletes all tokens and refreshTokens for some client id', function() {
const scopes = ['profile'];
let user2ClientWriteToken;
let refreshTokenIdHash;
return db.registerClient(client2)
.then(function () {
return getUniqueUserAndToken(client2Id.toString('hex'), {
uid: user1.uid,
email: user1.email,
scopes: ['profile']
scopes: scopes
});
})
.then(function () {
Expand All @@ -2948,6 +2950,17 @@ describe('/v1', function() {
.then(function (res) {
user2ClientWriteToken = res.token;

// also create a refreshToken for user1
return db.generateRefreshToken({
clientId: client2Id,
userId: buf(user1.uid),
email: user1.email,
scope: scopes
});
})
.then(function (t) {
refreshTokenIdHash = encrypt.hash(t.token.toString('hex'));

return Server.api.get({
url: '/client-tokens',
headers: {
Expand All @@ -2958,6 +2971,12 @@ describe('/v1', function() {
.then(function (res) {
assert.equal(res.result.length, 2);
assertSecurityHeaders(res);

return db.getRefreshToken(refreshTokenIdHash);
})
.then(function (tok) {
assert.equal(tok.token.toString('hex'), refreshTokenIdHash.toString('hex'), 'refresh token was not deleted');

return Server.api.delete({
url: '/client-tokens/' + client2Id.toString('hex'),
headers: {
Expand Down Expand Up @@ -2999,8 +3018,12 @@ describe('/v1', function() {
assert.equal(res.result.code, 401, 'client:write token was deleted');
assert.equal(res.result.detail, 'Bearer token invalid');
assertSecurityHeaders(res);

return db.getRefreshToken(refreshTokenIdHash);
})
.then(function () {
.then(function (tok) {
assert.equal(tok, undefined, 'refresh token was deleted');

return Server.api.get({
url: '/client-tokens',
headers: {
Expand Down

0 comments on commit df0ca82

Please sign in to comment.