Update server dependencies
[oweals/peertube.git] / server / middlewares / oauth.ts
1 import * as express from 'express'
2 import { logger } from '../helpers/logger'
3 import { Socket } from 'socket.io'
4 import { getAccessToken } from '../lib/oauth-model'
5 import { oAuthServer } from '@server/lib/auth'
6
7 function authenticate (req: express.Request, res: express.Response, next: express.NextFunction, authenticateInQuery = false) {
8   const options = authenticateInQuery ? { allowBearerTokensInQueryString: true } : {}
9
10   oAuthServer.authenticate(options)(req, res, err => {
11     if (err) {
12       logger.warn('Cannot authenticate.', { err })
13
14       return res.status(err.status)
15         .json({
16           error: 'Token is invalid.',
17           code: err.name
18         })
19         .end()
20     }
21
22     return next()
23   })
24 }
25
26 function authenticateSocket (socket: Socket, next: (err?: any) => void) {
27   const accessToken = socket.handshake.query.accessToken
28
29   logger.debug('Checking socket access token %s.', accessToken)
30
31   if (!accessToken) return next(new Error('No access token provided'))
32
33   getAccessToken(accessToken)
34     .then(tokenDB => {
35       const now = new Date()
36
37       if (!tokenDB || tokenDB.accessTokenExpiresAt < now || tokenDB.refreshTokenExpiresAt < now) {
38         return next(new Error('Invalid access token.'))
39       }
40
41       socket.handshake.query.user = tokenDB.User
42
43       return next()
44     })
45     .catch(err => logger.error('Cannot get access token.', { err }))
46 }
47
48 function authenticatePromiseIfNeeded (req: express.Request, res: express.Response, authenticateInQuery = false) {
49   return new Promise(resolve => {
50     // Already authenticated? (or tried to)
51     if (res.locals.oauth?.token.User) return resolve()
52
53     if (res.locals.authenticated === false) return res.sendStatus(401)
54
55     authenticate(req, res, () => resolve(), authenticateInQuery)
56   })
57 }
58
59 function optionalAuthenticate (req: express.Request, res: express.Response, next: express.NextFunction) {
60   if (req.header('authorization')) return authenticate(req, res, next)
61
62   res.locals.authenticated = false
63
64   return next()
65 }
66
67 // ---------------------------------------------------------------------------
68
69 export {
70   authenticate,
71   authenticateSocket,
72   authenticatePromiseIfNeeded,
73   optionalAuthenticate
74 }