New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

express-openid-connect

Package Overview
Dependencies
Maintainers
46
Versions
44
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

express-openid-connect - npm Package Compare versions

Comparing version 2.11.0 to 2.12.0

33

index.d.ts

@@ -178,2 +178,14 @@ // Type definitions for express-openid-connect

logout: (opts?: LogoutOptions) => Promise<void>;
/**
* Provided by default via the `/callback` route. Call this to override or have other
* callback routes with
*
* ```js
* app.get('/callback', (req, res) => {
* res.oidc.callback({ redirectUri: 'https://example.com/callback' });
* });
* ```
*/
callback: (opts?: CallbackOptions) => Promise<void>;
}

@@ -201,3 +213,5 @@

/**
* Override the default {@link ConfigParams.authorizationParams authorizationParams}
* Override the default {@link ConfigParams.authorizationParams authorizationParams}, if also passing a custom callback
* route then {@link AuthorizationParameters.redirect_uri redirect_uri} must be provided here or in
* {@link ConfigParams.authorizationParams config}
*/

@@ -232,2 +246,15 @@ authorizationParams?: AuthorizationParameters;

interface CallbackOptions {
/**
* This is useful to specify in addition to {@link ConfigParams.baseURL} when your app runs on multiple domains,
* it should match {@link LoginOptions.authorizationParams.redirect_uri}
*/
redirectUri: string;
/**
* Additional request body properties to be sent to the `token_endpoint.
*/
tokenEndpointParams?: TokenParameters;
}
/**

@@ -661,3 +688,3 @@ * Configuration parameters passed to the `auth()` middleware.

*/
signSessionStoreCookie: boolean;
signSessionStoreCookie?: boolean;

@@ -677,3 +704,3 @@ /**

*/
requireSignedSessionStoreCookie: boolean;
requireSignedSessionStoreCookie?: boolean;

@@ -680,0 +707,0 @@ /**

7

lib/client.js

@@ -21,4 +21,2 @@ const { Issuer, custom } = require('openid-client');

const getIssuer = memoize((issuer) => Issuer.discover(issuer));
async function get(config) {

@@ -45,3 +43,3 @@ const defaultHttpOptions = (options) => {

applyHttpOptionsCustom(Issuer);
const issuer = await getIssuer(config.issuerBaseURL);
const issuer = await Issuer.discover(config.issuerBaseURL);
applyHttpOptionsCustom(issuer);

@@ -103,2 +101,5 @@

token_endpoint_auth_method: config.clientAuthMethod,
...(config.clientAssertionSigningAlg && {
token_endpoint_auth_signing_alg: config.clientAssertionSigningAlg,
}),
},

@@ -105,0 +106,0 @@ jwks

@@ -197,3 +197,6 @@ const Joi = require('joi');

]).default('/logout'),
callback: Joi.string().uri({ relativeOnly: true }).default('/callback'),
callback: Joi.alternatives([
Joi.string().uri({ relativeOnly: true }),
Joi.boolean().valid(false),
]).default('/callback'),
postLogoutRedirect: Joi.string().uri({ allowRelative: true }).default(''),

@@ -200,0 +203,0 @@ })

@@ -6,2 +6,3 @@ const url = require('url');

const { strict: assert } = require('assert');
const createError = require('http-errors');

@@ -11,5 +12,12 @@ const debug = require('./debug')('context');

const { get: getClient } = require('./client');
const { encodeState } = require('../lib/hooks/getLoginState');
const { cancelSilentLogin } = require('../middleware/attemptSilentLogin');
const { encodeState, decodeState } = require('../lib/hooks/getLoginState');
const {
cancelSilentLogin,
resumeSilentLogin,
} = require('../middleware/attemptSilentLogin');
const weakRef = require('./weakCache');
const {
regenerateSessionStoreId,
replaceSession,
} = require('../lib/appSession');

@@ -165,3 +173,5 @@ function isExpired() {

const { config } = weakRef(this);
return urlJoin(config.baseURL, config.routes.callback);
if (config.routes.callback) {
return urlJoin(config.baseURL, config.routes.callback);
}
}

@@ -211,3 +221,3 @@

}
stateValue.nonce = transient.generateNonce();
if (options.silent) {

@@ -217,11 +227,2 @@ stateValue.attemptingSilentLogin = true;

const usePKCE =
options.authorizationParams.response_type.includes('code');
if (usePKCE) {
debug(
'response_type includes code, the authorization request will use PKCE'
);
stateValue.code_verifier = transient.generateCodeVerifier();
}
const validResponseTypes = ['id_token', 'code id_token', 'code'];

@@ -246,2 +247,3 @@ assert(

};
const authParams = {

@@ -252,4 +254,9 @@ ...options.authorizationParams,

const usePKCE =
options.authorizationParams.response_type.includes('code');
if (usePKCE) {
authVerification.code_verifier = transient.generateNonce();
debug(
'response_type includes code, the authorization request will use PKCE'
);
authVerification.code_verifier = transient.generateCodeVerifier();

@@ -319,4 +326,75 @@ authParams.code_challenge_method = 'S256';

}
async callback(options = {}) {
let { config, req, res, transient, next } = weakRef(this);
next = once(next);
try {
const client = await getClient(config);
const redirectUri = options.redirectUri || this.getRedirectUri();
let tokenSet;
try {
const callbackParams = client.callbackParams(req);
const authVerification = transient.getOnce(
config.transactionCookie.name,
req,
res
);
const checks = authVerification ? JSON.parse(authVerification) : {};
req.openidState = decodeState(checks.state);
tokenSet = await client.callback(redirectUri, callbackParams, checks, {
exchangeBody: {
...(config && config.tokenEndpointParams),
...options.tokenEndpointParams,
},
});
} catch (error) {
throw createError(400, error.message, {
error: error.error,
error_description: error.error_description,
});
}
let session = Object.assign({}, tokenSet); // Remove non-enumerable methods from the TokenSet
if (config.afterCallback) {
session = await config.afterCallback(
req,
res,
session,
req.openidState
);
}
if (req.oidc.isAuthenticated()) {
if (req.oidc.user.sub === tokenSet.claims().sub) {
// If it's the same user logging in again, just update the existing session.
Object.assign(req[config.session.name], session);
} else {
// If it's a different user, replace the session to remove any custom user
// properties on the session
replaceSession(req, session, config);
// And regenerate the session id so the previous user wont know the new user's session id
regenerateSessionStoreId(req, config);
}
} else {
// If a new user is replacing an anonymous session, update the existing session to keep
// any anonymous session state (eg. checkout basket)
Object.assign(req[config.session.name], session);
// But update the session store id so a previous anonymous user wont know the new user's session id
regenerateSessionStoreId(req, config);
}
resumeSilentLogin(req, res);
} catch (err) {
if (!req.openidState || !req.openidState.attemptingSilentLogin) {
return next(err);
}
}
res.redirect(req.openidState.returnTo || config.baseURL);
}
}
module.exports = { RequestContext, ResponseContext };
const express = require('express');
const createError = require('http-errors');
const debug = require('../lib/debug')('auth');
const { once } = require('../lib/once');
const { get: getConfig } = require('../lib/config');
const { get: getClient } = require('../lib/client');
const { requiresAuth } = require('./requiresAuth');

@@ -13,4 +10,2 @@ const attemptSilentLogin = require('./attemptSilentLogin');

const appSession = require('../lib/appSession');
const { regenerateSessionStoreId, replaceSession } = appSession;
const { decodeState } = require('../lib/hooks/getLoginState');

@@ -64,118 +59,12 @@ const enforceLeadingSlash = (path) => {

// Callback route, configured with routes.callback.
{
let client;
if (config.routes.callback) {
const path = enforceLeadingSlash(config.routes.callback);
const callbackStack = [
(req, res, next) => {
debug('%s %s called', req.method, path);
next();
},
async (req, res, next) => {
next = once(next);
client =
client ||
(await getClient(config).catch((err) => {
next(err);
}));
if (!client) {
return;
}
try {
const redirectUri = res.oidc.getRedirectUri();
let tokenSet;
try {
const callbackParams = client.callbackParams(req);
const authVerification = transient.getOnce(
config.transactionCookie.name,
req,
res
);
const { max_age, code_verifier, nonce, state } = authVerification
? JSON.parse(authVerification)
: {};
req.openidState = decodeState(state);
const checks = {
max_age,
code_verifier,
nonce,
state,
};
let extras;
if (config.tokenEndpointParams) {
extras = { exchangeBody: config.tokenEndpointParams };
}
tokenSet = await client.callback(
redirectUri,
callbackParams,
checks,
extras
);
} catch (err) {
throw createError(400, err.message, {
error: err.error,
error_description: err.error_description,
});
}
let session = Object.assign({}, tokenSet); // Remove non-enumerable methods from the TokenSet
if (config.afterCallback) {
session = await config.afterCallback(
req,
res,
session,
req.openidState
);
}
if (req.oidc.isAuthenticated()) {
if (req.oidc.user.sub === tokenSet.claims().sub) {
// If it's the same user logging in again, just update the existing session.
Object.assign(req[config.session.name], session);
} else {
// If it's a different user, replace the session to remove any custom user
// properties on the session
replaceSession(req, session, config);
// And regenerate the session id so the previous user wont know the new user's session id
regenerateSessionStoreId(req, config);
}
} else {
// If a new user is replacing an anonymous session, update the existing session to keep
// any anonymous session state (eg. checkout basket)
Object.assign(req[config.session.name], session);
// But update the session store id so a previous anonymous user wont know the new user's session id
regenerateSessionStoreId(req, config);
}
attemptSilentLogin.resumeSilentLogin(req, res);
next();
} catch (err) {
// Swallow errors if this is a silentLogin
if (req.openidState && req.openidState.attemptingSilentLogin) {
next();
} else {
next(err);
}
}
},
(req, res) => res.redirect(req.openidState.returnTo || config.baseURL),
];
debug('adding GET %s route', path);
router.get(path, ...callbackStack);
router.get(path, (req, res) => res.oidc.callback());
debug('adding POST %s route', path);
router.post(
path,
express.urlencoded({ extended: false }),
...callbackStack
router.post(path, express.urlencoded({ extended: false }), (req, res) =>
res.oidc.callback()
);
} else {
debug('callback handling route not applied');
}

@@ -182,0 +71,0 @@

{
"name": "express-openid-connect",
"version": "2.11.0",
"version": "2.12.0",
"description": "Express middleware to protect web applications using OpenID Connect.",

@@ -19,2 +19,3 @@ "homepage": "https://github.com/auth0/express-openid-connect",

"test:ci": "nyc --reporter=lcov npm test",
"test:types": "tsd .",
"docs": "typedoc --options typedoc.js index.d.ts",

@@ -55,3 +56,3 @@ "test:end-to-end": "mocha end-to-end"

"memorystore": "^1.6.4",
"mocha": "^7.2.0",
"mocha": "^10.2.0",
"nock": "^11.9.1",

@@ -67,2 +68,3 @@ "nyc": "^15.1.0",

"sinon": "^7.5.0",
"tsd": "^0.25.0",
"typedoc": "^0.23.18",

@@ -69,0 +71,0 @@ "typescript": "^4.8.4"

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc