-import * as express from 'express'
-import {
+import express from 'express'
+import OAuth2Server, {
InvalidClientError,
InvalidGrantError,
InvalidRequestError,
Response,
UnauthorizedClientError,
UnsupportedGrantTypeError
-} from 'oauth2-server'
-import { randomBytesPromise, sha1 } from '@server/helpers/core-utils'
+} from '@node-oauth/oauth2-server'
+import { randomBytesPromise } from '@server/helpers/core-utils'
+import { isOTPValid } from '@server/helpers/otp'
+import { CONFIG } from '@server/initializers/config'
import { MOAuthClient } from '@server/types/models'
-import { OAUTH_LIFETIME } from '../../initializers/constants'
+import { sha1 } from '@shared/extra-utils'
+import { HttpStatusCode } from '@shared/models'
+import { OTP } from '../../initializers/constants'
import { BypassLogin, getClient, getRefreshToken, getUser, revokeToken, saveToken } from './oauth-model'
+class MissingTwoFactorError extends Error {
+ code = HttpStatusCode.UNAUTHORIZED_401
+ name = 'missing_two_factor'
+}
+
+class InvalidTwoFactorError extends Error {
+ code = HttpStatusCode.BAD_REQUEST_400
+ name = 'invalid_two_factor'
+}
+
/**
*
* Reimplement some functions of OAuth2Server to inject external auth methods
*
*/
-
-const oAuthServer = new (require('oauth2-server'))({
- accessTokenLifetime: OAUTH_LIFETIME.ACCESS_TOKEN,
- refreshTokenLifetime: OAUTH_LIFETIME.REFRESH_TOKEN,
+const oAuthServer = new OAuth2Server({
+ // Wants seconds
+ accessTokenLifetime: CONFIG.OAUTH2.TOKEN_LIFETIME.ACCESS_TOKEN / 1000,
+ refreshTokenLifetime: CONFIG.OAUTH2.TOKEN_LIFETIME.REFRESH_TOKEN / 1000,
// See https://github.com/oauthjs/node-oauth2-server/wiki/Model-specification for the model specifications
model: require('./oauth-model')
})
}
-async function handleOAuthAuthenticate (
+function handleOAuthAuthenticate (
req: express.Request,
- res: express.Response,
- authenticateInQuery = false
+ res: express.Response
) {
- const options = authenticateInQuery
- ? { allowBearerTokensInQueryString: true }
- : {}
-
- return oAuthServer.authenticate(new Request(req), new Response(res), options)
+ return oAuthServer.authenticate(new Request(req), new Response(res))
}
export {
+ MissingTwoFactorError,
+ InvalidTwoFactorError,
+
handleOAuthToken,
handleOAuthAuthenticate
}
const user = await getUser(request.body.username, request.body.password, bypassLogin)
if (!user) throw new InvalidGrantError('Invalid grant: user credentials are invalid')
+ if (user.otpSecret) {
+ if (!request.headers[OTP.HEADER_NAME]) {
+ throw new MissingTwoFactorError('Missing two factor header')
+ }
+
+ if (await isOTPValid({ encryptedSecret: user.otpSecret, token: request.headers[OTP.HEADER_NAME] }) !== true) {
+ throw new InvalidTwoFactorError('Invalid two factor header')
+ }
+ }
+
const token = await buildToken()
return saveToken(token, client, user, { bypassLogin })
function getTokenExpiresAt (type: 'access' | 'refresh') {
const lifetime = type === 'access'
- ? OAUTH_LIFETIME.ACCESS_TOKEN
- : OAUTH_LIFETIME.REFRESH_TOKEN
+ ? CONFIG.OAUTH2.TOKEN_LIFETIME.ACCESS_TOKEN
+ : CONFIG.OAUTH2.TOKEN_LIFETIME.REFRESH_TOKEN
- return new Date(Date.now() + lifetime * 1000)
+ return new Date(Date.now() + lifetime)
}
async function buildToken () {