ニジカ投稿局 https://tv.nizika.tv
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

113 lines
3.3 KiB

  1. import express from 'express'
  2. import { Socket } from 'socket.io'
  3. import { HttpStatusCode, HttpStatusCodeType, ServerErrorCodeType } from '@peertube/peertube-models'
  4. import { getAccessToken } from '@server/lib/auth/oauth-model.js'
  5. import { RunnerModel } from '@server/models/runner/runner.js'
  6. import { logger } from '../helpers/logger.js'
  7. import { handleOAuthAuthenticate } from '../lib/auth/oauth.js'
  8. function authenticate (req: express.Request, res: express.Response, next: express.NextFunction) {
  9. handleOAuthAuthenticate(req, res)
  10. .then((token: any) => {
  11. res.locals.oauth = { token }
  12. res.locals.authenticated = true
  13. return next()
  14. })
  15. .catch(err => {
  16. logger.info('Cannot authenticate.', { err })
  17. return res.fail({
  18. status: err.status,
  19. message: 'Token is invalid',
  20. type: err.name
  21. })
  22. })
  23. }
  24. function authenticateSocket (socket: Socket, next: (err?: any) => void) {
  25. const accessToken = socket.handshake.query['accessToken']
  26. logger.debug('Checking access token in runner.')
  27. if (!accessToken) return next(new Error('No access token provided'))
  28. if (typeof accessToken !== 'string') return next(new Error('Access token is invalid'))
  29. getAccessToken(accessToken)
  30. .then(tokenDB => {
  31. const now = new Date()
  32. if (!tokenDB || tokenDB.accessTokenExpiresAt < now || tokenDB.refreshTokenExpiresAt < now) {
  33. return next(new Error('Invalid access token.'))
  34. }
  35. socket.handshake.auth.user = tokenDB.User
  36. return next()
  37. })
  38. .catch(err => logger.error('Cannot get access token.', { err }))
  39. }
  40. function authenticatePromise (options: {
  41. req: express.Request
  42. res: express.Response
  43. errorMessage?: string
  44. errorStatus?: HttpStatusCodeType
  45. errorType?: ServerErrorCodeType
  46. }) {
  47. const { req, res, errorMessage = 'Not authenticated', errorStatus = HttpStatusCode.UNAUTHORIZED_401, errorType } = options
  48. return new Promise<void>(resolve => {
  49. // Already authenticated? (or tried to)
  50. if (res.locals.oauth?.token.User) return resolve()
  51. if (res.locals.authenticated === false) {
  52. return res.fail({
  53. status: errorStatus,
  54. type: errorType,
  55. message: errorMessage
  56. })
  57. }
  58. authenticate(req, res, () => resolve())
  59. })
  60. }
  61. function optionalAuthenticate (req: express.Request, res: express.Response, next: express.NextFunction) {
  62. if (req.header('authorization')) return authenticate(req, res, next)
  63. res.locals.authenticated = false
  64. return next()
  65. }
  66. // ---------------------------------------------------------------------------
  67. function authenticateRunnerSocket (socket: Socket, next: (err?: any) => void) {
  68. const runnerToken = socket.handshake.auth['runnerToken']
  69. logger.debug('Checking runner token in socket.')
  70. if (!runnerToken) return next(new Error('No runner token provided'))
  71. if (typeof runnerToken !== 'string') return next(new Error('Runner token is invalid'))
  72. RunnerModel.loadByToken(runnerToken)
  73. .then(runner => {
  74. if (!runner) return next(new Error('Invalid runner token.'))
  75. socket.handshake.auth.runner = runner
  76. return next()
  77. })
  78. .catch(err => logger.error('Cannot get runner token.', { err }))
  79. }
  80. // ---------------------------------------------------------------------------
  81. export {
  82. authenticate,
  83. authenticateSocket,
  84. authenticatePromise,
  85. optionalAuthenticate,
  86. authenticateRunnerSocket
  87. }