UNPKG

@equisoft/oauth2orize-jwt-to-bearer

Version:

JSON Web Token (JWT) Bearer Token Exchange Middleware for OAuth2orize.

116 lines (103 loc) 3.83 kB
/** * Module dependencies. */ const TokenError = require('oauth2orize/lib/errors/tokenerror'); const utils = require('./utils'); /** * JWTs as Authorization Grants. * * This exchange middleware is used to by clients to request an access token by * using a JSON Web Token (JWT) generated by the client and verified by a * Public Key stored on the server. * * Callbacks: * * This middleware requires an `issue` callback, for which the function * signature is as follows: * * function(client, scope, assertion, done) { ... } * * `client` is the authenticated client instance attempting to obtain an access * token. `assertion` is the JWT encoded header and claim set. `done` is * called to issue an access token: * * done(err, accessToken, refreshToken, params) * * `accessToken` is the access token that will be sent to the client. * `refreshToken` is the refresh token that will be sent to the client. Any * additional `params` will be included in the response. If an error occurs, * `done` should be invoked with `err` set in idomatic Node.js fashion. * * Options: * * userProperty property of `req` which contains the authenticated client (default: 'user') * scopeSeparator Character separating scopes (default: ' ') * * * Examples: * * server.exchange('urn:ietf:params:oauth:grant-type:jwt-bearer', oauth2orize.exchange.jwtBearer(function(client, scope, assertion, done) { * * AccessToken.create(client, scope, function(err, accessToken) { * if (err) { return done(err); } * done(null, accessToken); * }); * })); * * References: * - [JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants](https://tools.ietf.org/html/rfc7523#section-2.1) * - [JSON Web Token (JWT)](https://tools.ietf.org/html/rfc7519) * * * @param {Function} issue middleware callback function * @param {Object} options userProperty (default: 'user'), scopeSeparator (default: ' ') * @api public * @returns {Function} return middleware function */ module.exports = (issue, options = {}) => { if (!issue) throw new Error('OAuth 2.0 jwtBearer exchange middleware requires an issue function.'); const userProperty = options.userProperty || 'user'; const scopeSeparator = options.scopeSeparator || ' '; return (req, res, next) => { if (!req.body) { return next(new Error('Request body not parsed. Use bodyParser middleware.')); } // The 'user' property of `req` holds the authenticated user. In the case // of the token endpoint, the property will contain the OAuth 2.0 client. const client = req[userProperty]; const { assertion } = req.body; let { scope } = req.body; if (!assertion) { return next(new TokenError('missing assertion parameter', 'invalid_request')); } if (scope) { if (typeof scope !== 'string') { return next(new TokenError('Invalid parameter: scope must be a string', 'invalid_request')); } scope = scope.split(scopeSeparator); } else { scope = []; } function issued(err, accessToken, refreshToken = null, params = {}) { if (err) { return next(err); } if (!accessToken) { return next(new TokenError('Invalid authorization code', 'invalid_grant')); } const tok = {}; tok.access_token = accessToken; if (refreshToken !== null) { tok.refresh_token = refreshToken; } utils.merge(tok, params); tok.token_type = tok.token_type || 'Bearer'; const json = JSON.stringify(tok); res.setHeader('Content-Type', 'application/json'); res.setHeader('Cache-Control', 'no-store'); res.setHeader('Pragma', 'no-cache'); res.end(json); } issue(client, scope, assertion, issued); }; };