@sap/cds
Version:
SAP Cloud Application Programming Model - CDS for Node.js
56 lines (48 loc) • 2.1 kB
JavaScript
module.exports = function basic_auth (options) {
const cds = require ('../../../index')
const DEBUG = cds.debug('basic|auth')
// use configured mocked users
const users = require ('./mocked-users') (options)
// determine if login is required based on options, environment, and multitenancy
const login_required = (
options.login_required ||
options.credentials && process.env.NODE_ENV === 'production' ||
cds.requires.multitenancy
)
/**
* Authentication middleware for HTTP Basic Authentication with mock users.
* Supports anonymous access, with logins triggered if required.
* Upon successful authentication, it sets:
* - `cds.context.user` with user id (same in `req.user`)
* - `cds.context.tenant` with the tenant id, if any
* - `cds.context.features` with the feature flags, if any
* @type { import('express').Handler } express_handler
*/
return async function basic_auth (req, res, next) {
req._login = login // allow subsequent code to request a user login
const auth = req.headers.authorization // get basic authorization header
// allow anonymous access unless login is required
if (!auth?.match(/^basic/i)) return login_required ? req._login() : next()
// decode user credentials from autorization header
const [id,pwd] = Buffer.from(auth.slice(6),'base64').toString().split(':')
// verify username and password
const u = await users.verify (id, pwd)
// re-request login in case of wrong credentials
if (u.failed) return req._login()
// user authenticated...
const {tenant} = u, {features} = req.headers || u
let ctx = cds.context; ctx.user = req.user = u
if (tenant) ctx.tenant = tenant
if (features) ctx.features = features
DEBUG?.('authenticated:', { user: u.id, tenant, features })
next()
}
/**
* Error middleware to trigger login from subsequent layers.
* @this {import('express').Request}
*/
function login() {
DEBUG?.(401, '> login required')
return this.res.set('WWW-Authenticate', `Basic realm="Users"`).sendStatus(401)
}
}