SAP-BTP-Spielwiese/app1/node_modules/@sap/xssec/lib/strategies/passport-jwt.js

129 lines
3.7 KiB
JavaScript
Raw Normal View History

'use strict';
/*
* Authentication strategy for passport using JSON Web Token (JWT)
*
* If JWT token is present and it is successfully verified, following objects are created:
* - request.user - according to http://passportjs.org/guide/profile/ convention
* - id
* - name
* - givenName
* - familyName
* - emails [ { value: <email> } ]
* - request.authInfo - instance of xssec.SecurityContext
* - getHdbToken(...) - retrieve token for business user to pass to HANA
* - checkScope(...) - authorization checks
* - ...
*
* See http://jwt.io/
* See https://www.npmjs.com/package/passport
*/
var xssec = require('..');
var debug = require('debug');
var debugTrace = debug('xssec:jwtstrategy');
var debugError = debug('xssec:jwtstrategy');
debugError.log = console.error.bind(console);
debugTrace.log = console.log.bind(console);
const { FWD_CLIENT_CERT_HEADER } = require('../constants');
exports.JWTStrategy = JWTStrategy;
function JWTStrategy(options, forceType) {
this.options = options;
this.name = 'JWT';
this._forceType = forceType;
}
function SimpleError(errorStr) {
const errobj = new Error(errorStr);
this.getErrorObject = function () {
return errobj;
}
}
JWTStrategy.prototype.authenticate = function (req, options) {
var authorization = req.headers.authorization;
var authParams = options;
if (!authorization) {
debugTrace('Missing Authorization header');
req.tokenInfo = new SimpleError('Missing Authorization header');
return this.fail(401);
}
var parts = authorization.split(' ');
if (parts.length < 2) {
debugTrace('Invalid Authorization header format');
req.tokenInfo = new SimpleError('Invalid Authorization header format');
return this.fail(400);
}
var scheme = parts[0];
var token = parts[1];
if (scheme.toLowerCase() !== 'bearer') {
debugTrace('Authorization header is not a Bearer token');
req.tokenInfo = new SimpleError('Authorization header is not a Bearer token');
return this.fail(401);
}
const correlationId = req.headers["x-correlationid"] || req.headers["x-vcap-request-id"];
const x509Certificate = req.headers[FWD_CLIENT_CERT_HEADER];
try {
function callback(err, ctx, tokenInfo) {
req.tokenInfo = tokenInfo;
if (err) {
if(!req.tokenInfo) {
req.tokenInfo = new SimpleError(err.toString());
}
return err.statuscode ? self.fail(err.statuscode, err) : self.error(err);
}
if (authParams && authParams.scope) {
var scopes = Array.isArray(authParams.scope) ? authParams.scope : [authParams.scope];
for (var scope of scopes) {
if (!ctx.checkScope(self.options.xsappname + '.' + scope)) {
return self.fail(403);
}
}
}
var jwtLogonName = ctx.getLogonName();
var jwtGivenName = ctx.getGivenName();
var jwtFamilyName = ctx.getFamilyName();
var jwtEmail = ctx.getEmail();
var user = !jwtLogonName ? {} : {
id: jwtLogonName,
name: {
givenName: jwtGivenName,
familyName: jwtFamilyName
},
emails: [{ value: jwtEmail }]
};
// passport will set these in req.user & req.authInfo respectively
self.success(user, ctx);
};
var self = this;
var paramA = this._forceType ? this._forceType : callback;
var paramB = this._forceType ? callback : undefined;
const config = { ...options, credentials: this.options, correlationId };
if(x509Certificate) {
config.x509Certificate = x509Certificate;
}
xssec.createSecurityContext(token, config, paramA, paramB);
}
catch (err) {
debugError('JWT verification error: ', err);
this.error(err);
}
};