1 import express from 'express'
2 import { generateOTPSecret, isOTPValid } from '@server/helpers/otp'
3 import { encrypt } from '@server/helpers/peertube-crypto'
4 import { CONFIG } from '@server/initializers/config'
5 import { Redis } from '@server/lib/redis'
6 import { asyncMiddleware, authenticate, usersCheckCurrentPasswordFactory } from '@server/middlewares'
8 confirmTwoFactorValidator,
9 disableTwoFactorValidator,
10 requestOrConfirmTwoFactorValidator
11 } from '@server/middlewares/validators/two-factor'
12 import { HttpStatusCode, TwoFactorEnableResult } from '@shared/models'
14 const twoFactorRouter = express.Router()
16 twoFactorRouter.post('/:id/two-factor/request',
18 asyncMiddleware(usersCheckCurrentPasswordFactory(req => req.params.id)),
19 asyncMiddleware(requestOrConfirmTwoFactorValidator),
20 asyncMiddleware(requestTwoFactor)
23 twoFactorRouter.post('/:id/two-factor/confirm-request',
25 asyncMiddleware(requestOrConfirmTwoFactorValidator),
26 confirmTwoFactorValidator,
27 asyncMiddleware(confirmRequestTwoFactor)
30 twoFactorRouter.post('/:id/two-factor/disable',
32 asyncMiddleware(usersCheckCurrentPasswordFactory(req => req.params.id)),
33 asyncMiddleware(disableTwoFactorValidator),
34 asyncMiddleware(disableTwoFactor)
37 // ---------------------------------------------------------------------------
43 // ---------------------------------------------------------------------------
45 async function requestTwoFactor (req: express.Request, res: express.Response) {
46 const user = res.locals.user
48 const { secret, uri } = generateOTPSecret(user.email)
50 const encryptedSecret = await encrypt(secret, CONFIG.SECRETS.PEERTUBE)
51 const requestToken = await Redis.Instance.setTwoFactorRequest(user.id, encryptedSecret)
59 } as TwoFactorEnableResult)
62 async function confirmRequestTwoFactor (req: express.Request, res: express.Response) {
63 const requestToken = req.body.requestToken
64 const otpToken = req.body.otpToken
65 const user = res.locals.user
67 const encryptedSecret = await Redis.Instance.getTwoFactorRequestToken(user.id, requestToken)
68 if (!encryptedSecret) {
70 message: 'Invalid request token',
71 status: HttpStatusCode.FORBIDDEN_403
75 if (await isOTPValid({ encryptedSecret, token: otpToken }) !== true) {
77 message: 'Invalid OTP token',
78 status: HttpStatusCode.FORBIDDEN_403
82 user.otpSecret = encryptedSecret
85 return res.sendStatus(HttpStatusCode.NO_CONTENT_204)
88 async function disableTwoFactor (req: express.Request, res: express.Response) {
89 const user = res.locals.user
94 return res.sendStatus(HttpStatusCode.NO_CONTENT_204)