strongloop / loopback-component-oauth2

oAuth 2.0 server for LoopBack
http://www.strongloop.com
Other
62 stars 63 forks source link

Integrate with MongoDB TTL function #28

Closed kalun1988 closed 7 years ago

kalun1988 commented 9 years ago

By Strongloop oauth2 component default setting (password grant), there is a big problem that the records in OAuthAccessToken Table will be accumulated when using refresh token to renew the access token. It causes following problems: -- The records in table accumulated by time -- the old refresh tokens are still valid. -- the old access token are still valid until expiry time. -- More than one access token may be valid for same device at same time

Phase 1: Update record, instead of Create Record

After refreshing token, we wrap the save function by delete function. node_modules/loopback-component-oauth2/lib/models/oauth2-loopback.js

/*

Phase 2:Apply TTL in MongoDB

Consider the TTL function in mongoDB, refer to "Expire Data from Collections by Setting TTL" We can set an sparse index to tell mongodb to housekeep the records, preventing accumulation occurs. we apply expireAfterSeconds index on issuedAt. We do not need to further config in mongo shell.

node_modules/loopback-component-oauth2/common/models/oauth-token.json

"issuedAt": {
  "type": "date",
  "index": {
    "expireAfterSeconds": 30
  }
},

Phase 3:Add one more TTLToken Table, Revise save, delete logic

Based on the default OAuthToken data structure. The refreshToken will be deleted after applying mongoDB TTL in Phase 2

Solution:

First, we make another table (TTLToken) based on OAuthToken (reverse what have be done in phase 2) /node_modules/loopback-component-oauth2/common/models/ttl-token.json { "name": "TTLAccessToken", "base": "PersistedModel",

… "issuedAt": { "type": "date", "index": { "expireAfterSeconds": 30 } },

node_modules/loopback-component-oauth2/lib/models/oauth2-model.js

add: var ttlDef = require('../../common/models/ttl-token.json');

add: var TTLToken = dataSource.createModel( ttlDef.name, ttlDef.properties, getSettings(ttlDef));

At bottom add:

return { TTLToken: TTLToken,

node_modules/loopback-component-oauth2/lib/models/index.js

add: var ttlTokenModel = oauth2.TTLToken;

var models = {

ttlTokens: customModels.ttlTokens || token,

The following parts, we revise the logic on 1) how to save Access Token 2) how to check Access Token 3) how to renew Access Token 4) how to revoke Access Token

1)When we save the token, we store it in two tables. Edit token.save() , called in new token/ refresh token node_modules/loopback-component-oauth2/lib/models/index.js

token.save = function(token, clientId, resourceOwner, scopes, refreshToken, done) {

… ttlTokenModel.create(tokenObj); //new ttlToken oAuthTokenModel.create(tokenObj, done);

2)When we check the access token, find token from ttlTokenModel

node_modules/loopback-component-oauth2/lib/models/index.js

var token = {}; token.find = function(accessToken, done) { ttlTokenModel.findOne({where: { // oAuthTokenModel.findOne({where: { id: accessToken }}, done); };

3)renew token node_modules/loopback-component-oauth2/lib/models/index.js

token.delete = function(clientId, token, tokenType, done) { var where = { appId: clientId }; if (tokenType === 'access_token') { where.id = token; } else { where.refreshToken = token; } ttlTokenModel.destroyAll(where); oAuthTokenModel.destroyAll(where, done); };

(same as Phase 1)

delete and save in both access and ttl token node_modules/loopback-component-oauth2/lib/oauth2-loopback.js

/*

4)revoke token in both accesstoken and ttltoken table handled in delete method just revised

raymondfeng commented 9 years ago

@kalun1988 Thank you for sharing your enhancement to token housekeeping. It would be even better with a github pull request to see the diffs.

richardpringle commented 8 years ago

connect to strongloop/loopback-component-oauth2#29

stale[bot] commented 7 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 7 years ago

This issue has been closed due to continued inactivity. Thank you for your understanding. If you believe this to be in error, please contact one of the code owners, listed in the CODEOWNERS file at the top-level of this repository.