| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- 'use strict'
- const basicAuth = require('basic-auth')
- const config = require('config')
- const HTTPStatus = require('http-status')
- const jwt = require('jsonwebtoken')
- const tsscmp = require('tsscmp')
- function setupBasicHttpAuthForSwaggerDocs(app) {
- app.use('/docs', function (req, res, next) {
- if (hasValidBasicAuthCredentials(req)) {
- return next()
- }
- res.header('WWW-Authenticate', 'Basic realm="Application"')
- res.status(HTTPStatus.UNAUTHORIZED).end()
- })
- }
- exports.setupBasicHttpAuthForSwaggerDocs = setupBasicHttpAuthForSwaggerDocs
- function hasValidBasicAuthCredentials(req) {
- const credentials = basicAuth(req)
- if (!credentials) return false
- // No security in the name, so just use straight comparison.
- if (credentials.name !== 'staging') return false
- const password = config.get('basicHttpAuth.password')
- if (password && tsscmp(credentials.pass, password)) return true
- // Support an old password so we can change the password without downtime.
- if (config.has('basicHttpAuth.oldPassword')) {
- const oldPassword = config.get('basicHttpAuth.oldPassword')
- if (oldPassword && tsscmp(credentials.pass, oldPassword)) return true
- }
- return false
- }
- function setupSSL(app) {
- const httpsOnly = config.get('httpsOnly') === 'true'
- if (!httpsOnly) {
- return
- }
- app.enable('trust proxy')
- app.use(function (req, res, next) {
- if (req.protocol === 'https') {
- next()
- return
- }
- if (req.method === 'GET' || req.method === 'HEAD') {
- res.redirect('https://' + req.headers.host + req.url)
- } else {
- res
- .status(HTTPStatus.FORBIDDEN)
- .send('Please use HTTPS when submitting data to this server.')
- }
- })
- }
- exports.setupSSL = setupSSL
- function handleJWTAuth(req, authOrSecDef, scopesOrApiKey, next) {
- // as a temporary solution, to make the OT demo still work
- // this handler will also check for basic authorization
- if (hasValidBasicAuthCredentials(req)) {
- return next()
- }
- let token, err
- if (authOrSecDef.name === 'token') {
- token = req.query.token
- } else if (
- req.headers.authorization &&
- req.headers.authorization.split(' ')[0] === 'Bearer'
- ) {
- token = req.headers.authorization.split(' ')[1]
- }
- if (!token) {
- err = new Error('jwt missing')
- err.statusCode = HTTPStatus.UNAUTHORIZED
- err.headers = { 'WWW-Authenticate': 'Bearer' }
- return next(err)
- }
- let decoded
- try {
- decoded = decodeJWT(token)
- } catch (error) {
- if (
- error instanceof jwt.JsonWebTokenError ||
- error instanceof jwt.TokenExpiredError
- ) {
- err = new Error(error.message)
- err.statusCode = HTTPStatus.UNAUTHORIZED
- err.headers = { 'WWW-Authenticate': 'Bearer error="invalid_token"' }
- return next(err)
- }
- throw error
- }
- if (decoded.project_id.toString() !== req.swagger.params.project_id.value) {
- err = new Error('Wrong project_id')
- err.statusCode = HTTPStatus.FORBIDDEN
- return next(err)
- }
- next()
- }
- /**
- * Verify and decode the given JSON Web Token
- */
- function decodeJWT(token) {
- const key = config.get('jwtAuth.key')
- const algorithm = config.get('jwtAuth.algorithm')
- try {
- return jwt.verify(token, key, { algorithms: [algorithm] })
- } catch (err) {
- // Support an old key so we can change the key without downtime.
- if (config.has('jwtAuth.oldKey')) {
- const oldKey = config.get('jwtAuth.oldKey')
- return jwt.verify(token, oldKey, { algorithms: [algorithm] })
- } else {
- throw err
- }
- }
- }
- function handleBasicAuth(req, authOrSecDef, scopesOrApiKey, next) {
- if (hasValidBasicAuthCredentials(req)) {
- return next()
- }
- const error = new Error()
- error.statusCode = HTTPStatus.UNAUTHORIZED
- error.headers = { 'WWW-Authenticate': 'Basic realm="Application"' }
- return next(error)
- }
- function getSwaggerHandlers() {
- const handlers = {}
- if (!config.has('jwtAuth.key') || !config.has('basicHttpAuth.password')) {
- throw new Error('missing authentication env vars')
- }
- handlers.jwt = handleJWTAuth
- handlers.basic = handleBasicAuth
- handlers.token = handleJWTAuth
- return handlers
- }
- exports.getSwaggerHandlers = getSwaggerHandlers
|