oauth-model.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import { AccessDeniedError } from 'oauth2-server'
  2. import { logger } from '../helpers/logger'
  3. import { UserModel } from '../models/account/user'
  4. import { OAuthClientModel } from '../models/oauth/oauth-client'
  5. import { OAuthTokenModel } from '../models/oauth/oauth-token'
  6. import { CONFIG } from '../initializers/constants'
  7. import { Transaction } from 'sequelize'
  8. type TokenInfo = { accessToken: string, refreshToken: string, accessTokenExpiresAt: Date, refreshTokenExpiresAt: Date }
  9. const accessTokenCache: { [ accessToken: string ]: OAuthTokenModel } = {}
  10. const userHavingToken: { [ userId: number ]: string } = {}
  11. // ---------------------------------------------------------------------------
  12. function deleteUserToken (userId: number, t?: Transaction) {
  13. clearCacheByUserId(userId)
  14. return OAuthTokenModel.deleteUserToken(userId, t)
  15. }
  16. function clearCacheByUserId (userId: number) {
  17. const token = userHavingToken[userId]
  18. if (token !== undefined) {
  19. accessTokenCache[ token ] = undefined
  20. userHavingToken[ userId ] = undefined
  21. }
  22. }
  23. function clearCacheByToken (token: string) {
  24. const tokenModel = accessTokenCache[ token ]
  25. if (tokenModel !== undefined) {
  26. userHavingToken[tokenModel.userId] = undefined
  27. accessTokenCache[ token ] = undefined
  28. }
  29. }
  30. function getAccessToken (bearerToken: string) {
  31. logger.debug('Getting access token (bearerToken: ' + bearerToken + ').')
  32. if (accessTokenCache[bearerToken] !== undefined) return accessTokenCache[bearerToken]
  33. return OAuthTokenModel.getByTokenAndPopulateUser(bearerToken)
  34. .then(tokenModel => {
  35. if (tokenModel) {
  36. accessTokenCache[ bearerToken ] = tokenModel
  37. userHavingToken[ tokenModel.userId ] = tokenModel.accessToken
  38. }
  39. return tokenModel
  40. })
  41. }
  42. function getClient (clientId: string, clientSecret: string) {
  43. logger.debug('Getting Client (clientId: ' + clientId + ', clientSecret: ' + clientSecret + ').')
  44. return OAuthClientModel.getByIdAndSecret(clientId, clientSecret)
  45. }
  46. function getRefreshToken (refreshToken: string) {
  47. logger.debug('Getting RefreshToken (refreshToken: ' + refreshToken + ').')
  48. return OAuthTokenModel.getByRefreshTokenAndPopulateClient(refreshToken)
  49. }
  50. async function getUser (usernameOrEmail: string, password: string) {
  51. logger.debug('Getting User (username/email: ' + usernameOrEmail + ', password: ******).')
  52. const user = await UserModel.loadByUsernameOrEmail(usernameOrEmail)
  53. if (!user) return null
  54. const passwordMatch = await user.isPasswordMatch(password)
  55. if (passwordMatch === false) return null
  56. if (user.blocked) throw new AccessDeniedError('User is blocked.')
  57. if (CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION && user.emailVerified === false) {
  58. throw new AccessDeniedError('User email is not verified.')
  59. }
  60. return user
  61. }
  62. async function revokeToken (tokenInfo: TokenInfo) {
  63. const token = await OAuthTokenModel.getByRefreshTokenAndPopulateUser(tokenInfo.refreshToken)
  64. if (token) {
  65. clearCacheByToken(token.accessToken)
  66. token.destroy()
  67. .catch(err => logger.error('Cannot destroy token when revoking token.', { err }))
  68. }
  69. /*
  70. * Thanks to https://github.com/manjeshpv/node-oauth2-server-implementation/blob/master/components/oauth/mongo-models.js
  71. * "As per the discussion we need set older date
  72. * revokeToken will expected return a boolean in future version
  73. * https://github.com/oauthjs/node-oauth2-server/pull/274
  74. * https://github.com/oauthjs/node-oauth2-server/issues/290"
  75. */
  76. const expiredToken = token
  77. expiredToken.refreshTokenExpiresAt = new Date('2015-05-28T06:59:53.000Z')
  78. return expiredToken
  79. }
  80. async function saveToken (token: TokenInfo, client: OAuthClientModel, user: UserModel) {
  81. logger.debug('Saving token ' + token.accessToken + ' for client ' + client.id + ' and user ' + user.id + '.')
  82. const tokenToCreate = {
  83. accessToken: token.accessToken,
  84. accessTokenExpiresAt: token.accessTokenExpiresAt,
  85. refreshToken: token.refreshToken,
  86. refreshTokenExpiresAt: token.refreshTokenExpiresAt,
  87. oAuthClientId: client.id,
  88. userId: user.id
  89. }
  90. const tokenCreated = await OAuthTokenModel.create(tokenToCreate)
  91. return Object.assign(tokenCreated, { client, user })
  92. }
  93. // ---------------------------------------------------------------------------
  94. // See https://github.com/oauthjs/node-oauth2-server/wiki/Model-specification for the model specifications
  95. export {
  96. deleteUserToken,
  97. clearCacheByUserId,
  98. clearCacheByToken,
  99. getAccessToken,
  100. getClient,
  101. getRefreshToken,
  102. getUser,
  103. revokeToken,
  104. saveToken
  105. }