express-openid-connect
Advanced tools
Comparing version
71
API.md
@@ -73,3 +73,3 @@ ## The auth middleware can be configured with environment varabiles | ||
Every `req` object is augmented with the following properties: | ||
Every `req` object is augmented with the following properties when the request is authenticated | ||
@@ -81,2 +81,4 @@ - `req.openid.user`: contains the user information, use this if you need display an attribute of the user. You can change what's end up here by using the `getUser` parameter of the `auth` middleware. | ||
If the request is not authenticated `req.openid` is `undefined`. | ||
Every `res` object gets the following methods: | ||
@@ -90,2 +92,69 @@ | ||
## Authorization handling | ||
By default the library triggers the login process when authentication is required. | ||
An anonymous request to the home page in this case will trigger the login process: | ||
```js | ||
app.use(auth()); //Remember that required is true by default | ||
app.get('/', (req, res) => res.render('home')); | ||
``` | ||
The same happens in this case: | ||
```js | ||
app.use(auth()); //Remember that required is true by default | ||
app.get('/', requiresAuth(), (req, res) => res.render('home')); | ||
``` | ||
If you remove the `auth()` middleware above like this: | ||
```js | ||
// app.use(auth()); //Remember that required is true by default | ||
app.get('/', requiresAuth(), (req, res) => res.render('home')); | ||
``` | ||
Instead of triggering the login process we get a 401 Unauthorized error. | ||
It is a best practice to decouple your application logic from this library. If you need to raise a 401 error on your own logic and `requiresAuth` is not enough, you can add the `unauthorizedHandler` from this library: | ||
```js | ||
const { | ||
auth, | ||
requiresAuth, | ||
unauthorizedHandler | ||
} = require('express-openid-connect'); | ||
app.use(auth()); | ||
// your routes go here | ||
app.get('/a-route', (req, res, next) => { | ||
if (condition) { | ||
return next(new UnauthorizedError('unauthorized because of xyz')); | ||
} | ||
}); | ||
//trigger login transactions on 401 errors. | ||
app.use(unauthorizedHandler()); | ||
``` | ||
If you need an special logic for handling 401s, including the errors raised by this library, you can set `errorOnRequiredAuth` to `true` like this: | ||
```js | ||
const { auth, requiresAuth } = require('express-openid-connect'); | ||
app.use(auth({ errorOnRequiredAuth: true })); | ||
// your routes go here | ||
//handle unauthorized errors with the unauthorizedHandler or | ||
//with your own middleware like this: | ||
app.use((err, req, res, next) => { | ||
if (err.statusCode === 401) { | ||
return res.openid.login(); //trigger the login process like the `unauthorizedHandler`. | ||
} | ||
next(err); | ||
}); | ||
``` | ||
## Debugging | ||
@@ -92,0 +161,0 @@ |
const ResponseMode = require('./lib/ResponseMode'); | ||
const auth = require('./middleware/auth'); | ||
const requiresAuth = require('./middleware/requiresAuth'); | ||
const unauthorizedHandler = require('./middleware/unauthorizedHandler'); | ||
@@ -8,3 +9,4 @@ module.exports = { | ||
requiresAuth, | ||
unauthorizedHandler, | ||
ResponseMode, | ||
}; |
const { Issuer } = require('openid-client'); | ||
const memoize = require('p-memoize'); | ||
const urlJoin = require('url-join'); | ||
const url = require('url'); | ||
const request = require('request-promise-native').defaults({ | ||
simple: false, | ||
resolveWithFullResponse: true | ||
}); | ||
const pkg = require('../package.json'); | ||
@@ -19,24 +12,4 @@ | ||
//We need request to be installed as a dependency. | ||
Issuer.useRequest(); | ||
async function appendAuth0LogoutLogic(client) { | ||
let isAuth0Issuer = false; | ||
const auth0LogoutUrl = urlJoin(client.issuer.issuer, '/v2/logout'); | ||
try { | ||
isAuth0Issuer = (await request.get(auth0LogoutUrl)).statusCode === 200; | ||
} catch(err) { | ||
isAuth0Issuer = false; | ||
} | ||
if (!isAuth0Issuer) { return; } | ||
client.endSessionUrl = function(params) { | ||
const parsed = url.parse(auth0LogoutUrl); | ||
parsed.query = { | ||
returnTo: params.post_logout_redirect_uri, | ||
federated: params.federated || undefined | ||
}; | ||
return url.format(parsed); | ||
}; | ||
} | ||
async function get(config) { | ||
@@ -68,4 +41,2 @@ const authorizeParams = config.authorizationParams; | ||
await appendAuth0LogoutLogic(client); | ||
client.CLOCK_TOLERANCE = config.clockTolerance; | ||
@@ -72,0 +43,0 @@ |
@@ -27,5 +27,5 @@ const Joi = require('joi'); | ||
getUser: Joi.func().optional().default(getUser), | ||
required: Joi.boolean().optional().default(true), | ||
required: Joi.alternatives([ Joi.func(), Joi.boolean()]).optional().default(true), | ||
routes: Joi.boolean().optional().default(true), | ||
handleUnauthorizedErrors: Joi.boolean().optional().default(true), | ||
errorOnRequiredAuth: Joi.boolean().optional().default(false), | ||
}); | ||
@@ -32,0 +32,0 @@ |
@@ -32,3 +32,3 @@ const express = require('express'); | ||
* a function receiving a request and return a boolean to determine which routes needs authentication. | ||
* @param {boolean} [handleUnauthorizedErrors=true] automatically handle unauthorized errors by triggering the authentication process | ||
* @param {boolean} [errorOnRequiredAuth=false] automatically handle unauthorized errors by triggering the authentication process | ||
* @param {boolean|Function} [params.routes=true] a boolean indicating if the routes /login and /logout should be added to the application | ||
@@ -101,22 +101,26 @@ * @param {Object} [params.authorizationParams] The parameters for the authorization call. Defaults to | ||
const returnURL = params.returnTo || config.baseURL; | ||
if (req.session || !req.openid) { | ||
if (typeof req.session.destroy === 'function') { | ||
req.session.destroy(); | ||
} else { | ||
req.session = null; | ||
} | ||
} else { | ||
if (!req.session || !req.openid) { | ||
return res.redirect(returnURL); | ||
} | ||
try { | ||
const client = await getClient(config); | ||
const url = client.endSessionUrl({ | ||
post_logout_redirect_uri: returnURL, | ||
id_token_hint: req.openid.tokens, | ||
client_id: config.clientID | ||
}); | ||
res.redirect(url); | ||
} catch(err) { | ||
next(err); | ||
if (typeof req.session.destroy === 'function') { | ||
req.session.destroy(); | ||
} else { | ||
req.session = null; | ||
} | ||
res.redirect(returnURL); | ||
//This could be used in the future to logout from the OP. | ||
// try { | ||
// const client = await getClient(config); | ||
// const url = client.endSessionUrl({ | ||
// post_logout_redirect_uri: returnURL, | ||
// id_token_hint: req.openid.tokens, | ||
// }); | ||
// res.redirect(url); | ||
// } catch(err) { | ||
// next(err); | ||
// } | ||
}; | ||
@@ -128,3 +132,4 @@ } | ||
login: login(req, res, next), | ||
logout: () => res.redirect(config.baseURL) | ||
logout: () => res.redirect(config.baseURL), | ||
errorOnRequiredAuth: config.errorOnRequiredAuth, | ||
}; | ||
@@ -196,3 +201,2 @@ if (!req.session.openidTokens) { return next(); } | ||
let tokenSet; | ||
@@ -203,3 +207,2 @@ | ||
debugCallback('callback parameters: %O', callbackParams); | ||
tokenSet = await client.authorizationCallback(redirect_uri, callbackParams, { | ||
@@ -246,13 +249,3 @@ nonce, | ||
if(config.handleUnauthorizedErrors) { | ||
router.use((err, req, res, next) => { | ||
if (err.statusCode === 401) { | ||
if(req.xhr) { return res.sendStatus(401); } | ||
return res.openid.login(); | ||
} | ||
next(err); | ||
}); | ||
} | ||
return router; | ||
}; |
@@ -14,2 +14,5 @@ const createError = require('http-errors'); | ||
if (requiresLogin) { | ||
if (res.openid && res.openid.login && !res.openid.errorOnRequiredAuth) { | ||
return res.openid.login(); | ||
} | ||
return next(createError.Unauthorized('Authentication is required for this route.')); | ||
@@ -16,0 +19,0 @@ } |
{ | ||
"name": "express-openid-connect", | ||
"version": "0.0.2", | ||
"version": "0.0.3", | ||
"description": "An Express.js middleware to protect OpenID Connect web applications.", | ||
@@ -22,3 +22,2 @@ "homepage": "https://github.com/auth0/express-openid-connect", | ||
"request": "^2.88.0", | ||
"request-promise-native": "^1.0.5", | ||
"url-join": "^4.0.0" | ||
@@ -38,2 +37,3 @@ }, | ||
"proxyquire": "^2.1.0", | ||
"request-promise-native": "^1.0.5", | ||
"selfsigned": "^1.10.4", | ||
@@ -40,0 +40,0 @@ "sinon": "^7.1.1" |
59652
6.58%9
-10%33
6.45%1261
3.79%14
7.69%- Removed
- Removed
- Removed
- Removed