-
-
Notifications
You must be signed in to change notification settings - Fork 10.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
🐛 🎨 old accesstokens are not cleaned up (#8065)
closes #8035 - create auth/utils - use authUtils.createTokens for all cases - decrease the expiry of the old access token before creating a new one
- Loading branch information
1 parent
23c0d69
commit fa38257
Showing
8 changed files
with
207 additions
and
123 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
var Promise = require('bluebird'), | ||
_ = require('lodash'), | ||
debug = require('ghost-ignition').debug('auth:utils'), | ||
models = require('../models'), | ||
globalUtils = require('../utils'), | ||
knex = require('../data/db').knex, | ||
_private = {}; | ||
|
||
/** | ||
* The initial idea was to delete all old tokens connected to a user and a client. | ||
* But if multiple browsers/apps are using the same client, we would log out them out. | ||
* So the idea is to always decrease the expiry of the old access token if available. | ||
* This access token auto expires and get's cleaned up on bootstrap (see oauth.js). | ||
*/ | ||
_private.decreaseOldAccessTokenExpiry = function decreaseOldAccessTokenExpiry(data, options) { | ||
debug('decreaseOldAccessTokenExpiry', data, options); | ||
|
||
if (!data.token) { | ||
return Promise.resolve(); | ||
} | ||
|
||
return models.Accesstoken.findOne(data, options) | ||
.then(function (oldAccessToken) { | ||
if (!oldAccessToken) { | ||
return Promise.resolve(); | ||
} | ||
|
||
return models.Accesstoken.edit({ | ||
expires: Date.now() + globalUtils.FIVE_MINUTES_MS | ||
}, _.merge({id: oldAccessToken.id}, options)); | ||
}); | ||
}; | ||
|
||
_private.destroyOldRefreshToken = function destroyOldRefreshToken(options) { | ||
debug('destroyOldRefreshToken', options); | ||
|
||
if (!options.token) { | ||
return Promise.resolve(); | ||
} | ||
|
||
return models.Refreshtoken.destroyByToken(options); | ||
}; | ||
|
||
/** | ||
* A user can have one token per client at a time. | ||
* If the user requests a new pair of tokens, we decrease the expiry of the old access token | ||
* and re-add the refresh token (this happens because this function is used for 3 different cases). | ||
* If the operation fails in between, the user can still use e.g. the refresh token and try again. | ||
*/ | ||
module.exports.createTokens = function createTokens(options) { | ||
options = options || {}; | ||
debug('createTokens'); | ||
|
||
var oldAccessToken = options.oldAccessToken, | ||
oldRefreshToken = options.oldRefreshToken, | ||
newAccessToken = globalUtils.uid(191), | ||
newRefreshToken = oldRefreshToken || globalUtils.uid(191), | ||
accessExpires = Date.now() + globalUtils.ONE_MONTH_MS, | ||
refreshExpires = Date.now() + globalUtils.SIX_MONTH_MS, | ||
clientId = options.clientId, | ||
userId = options.userId, | ||
modelOptions; | ||
|
||
return knex.transaction(function (transaction) { | ||
modelOptions = {transacting: transaction}; | ||
|
||
return _private.decreaseOldAccessTokenExpiry({token: oldAccessToken}, modelOptions) | ||
.then(function () { | ||
return _private.destroyOldRefreshToken(_.merge({ | ||
token: oldRefreshToken | ||
}, modelOptions)); | ||
}) | ||
.then(function () { | ||
return models.Accesstoken.add({ | ||
token: newAccessToken, | ||
user_id: userId, | ||
client_id: clientId, | ||
expires: accessExpires | ||
}, modelOptions); | ||
}) | ||
.then(function () { | ||
return models.Refreshtoken.add({ | ||
token: newRefreshToken, | ||
user_id: userId, | ||
client_id: clientId, | ||
expires: refreshExpires | ||
}, modelOptions); | ||
}) | ||
.then(function () { | ||
return { | ||
access_token: newAccessToken, | ||
refresh_token: newRefreshToken, | ||
expires_in: globalUtils.ONE_MONTH_S | ||
}; | ||
}); | ||
}); | ||
}; | ||
|
||
module.exports.getBearerAutorizationToken = function (req) { | ||
var parts, | ||
scheme, | ||
token; | ||
|
||
if (req.headers && req.headers.authorization) { | ||
parts = req.headers.authorization.split(' '); | ||
scheme = parts[0]; | ||
|
||
if (/^Bearer$/i.test(scheme)) { | ||
token = parts[1]; | ||
} | ||
} else if (req.query && req.query.access_token) { | ||
token = req.query.access_token; | ||
} | ||
|
||
return token; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.