@okta/oidc-middleware
Advanced tools
Comparing version 0.1.3 to 1.0.0
@@ -0,1 +1,31 @@ | ||
# 1.0.0 | ||
### Features | ||
- Attach the requested tokens to the user context object ([#226](https://github.com/okta/okta-oidc-js/issues/226)) | ||
```javascript | ||
app.get('/', (req, res) => { | ||
if (req.userContext) { | ||
const tokenSet = req.userContext.tokens; | ||
const userinfo = req.userContext.userinfo; | ||
console.log(`Access Token: ${tokenSet.access_token}`); | ||
console.log(`Id Token: ${tokenSet.id_token}`); | ||
console.log(`Claims: ${tokenSet.claims}`); | ||
console.log(`Userinfo Response: ${userinfo}`); | ||
res.send(`Hi ${userinfo.sub}!`); | ||
} else { | ||
res.send('Hi!'); | ||
} | ||
}); | ||
``` | ||
- Basic configuration validation for catching common input mistakes. | ||
### Breaking Changes | ||
- `req.userinfo` is now nested within `req.userContext` ([#226](https://github.com/okta/okta-oidc-js/issues/226)). Please update any use of `req.userinfo` to `req.userContext.userinfo`. | ||
# 0.1.3 | ||
@@ -2,0 +32,0 @@ |
{ | ||
"name": "@okta/oidc-middleware", | ||
"version": "0.1.3", | ||
"version": "1.0.0", | ||
"description": "OpenId Connect middleware for authorization code flows", | ||
@@ -22,3 +22,3 @@ "repository": "https://github.com/okta/okta-oidc-js", | ||
"test:integration": "sh tools/runIntegrationTests.sh", | ||
"test:unit": "mocha test/unit/*.js" | ||
"test:unit": "jest test/unit" | ||
}, | ||
@@ -44,3 +44,3 @@ "engines": { | ||
"express-session": "^1.15.5", | ||
"mocha": "^5.0.0", | ||
"jest": "^23.6.0", | ||
"nock": "^9.1.6", | ||
@@ -47,0 +47,0 @@ "protractor": "^5.1.2", |
@@ -14,2 +14,22 @@ # oidc-middleware | ||
## Table of Contents | ||
- [Installation](#installation) | ||
- [Prerequisites](#prerequisites) | ||
- [Usage Example](#usage-example) | ||
- [ExpressOIDC API](#expressoidc-api) | ||
- [new ExpressOIDC(config)](#new-expressoidcconfig) | ||
- [oidc.router](#oidcrouter) | ||
- [oidc.on('ready', callback)](#oidconready-callback) | ||
- [oidc.on('error', callback)](#oidconerror-callback) | ||
- [oidc.ensureAuthenticated({ redirectTo?: '/uri' })](#oidcensureauthenticated-redirectto-uri) | ||
- [req.isAuthenticated()](#reqisauthenticated) | ||
- [req.logout()](#reqlogout) | ||
- [req.userContext](#requsercontext) | ||
- [Customization](#customization) | ||
- [Customizing Routes](#customizing-routes) | ||
- [Using a Custom Login Page](#using-a-custom-login-page) | ||
- [Extending the User](#extending-the-user) | ||
- [Using Proxy Servers](#using-proxy-servers) | ||
## Installation | ||
@@ -23,3 +43,3 @@ | ||
* You will need an Okta Developer Org, you can sign up for an account at https://developer.okta.com/signup/.. | ||
* You will need an Okta Developer Org, you can sign up for an account at <https://developer.okta.com/signup/>. | ||
* An OIDC application in your Org, configured for Web mode. If you are new to Okta or this flow, we suggest following the [Express.js Quickstart][express-quickstart]. | ||
@@ -39,5 +59,5 @@ * This integration depends on sessions to store user information. Ensure the [express-session middleware](https://github.com/expressjs/session) is added before you add `ExpressOIDC`. By default, the session middleware uses a MemoryStore, which is not designed for production use. Use [another session store](https://github.com/expressjs/session#compatible-session-stores) for production. | ||
const oidc = new ExpressOIDC({ | ||
issuer: 'https://{yourOktaDomain}.com/oauth2/default', | ||
client_id: 'XXXXX', | ||
client_secret: 'XXXXX', | ||
issuer: 'https://{yourOktaDomain}/oauth2/default', | ||
client_id: '{clientId}', | ||
client_secret: '{clientSecret}', | ||
redirect_uri: 'http://localhost:3000/authorization-code/callback', | ||
@@ -54,4 +74,4 @@ scope: 'openid profile' | ||
app.get('/', (req, res) => { | ||
if (req.userinfo) { | ||
res.send(`Hello ${req.userinfo.name}! <a href="logout">Logout</a>`); | ||
if (req.userContext) { | ||
res.send(`Hello ${req.userContext.userinfo.name}! <a href="logout">Logout</a>`); | ||
} else { | ||
@@ -78,3 +98,2 @@ res.send('Please <a href="/login">login</a>'); | ||
### new ExpressOIDC(config) | ||
@@ -88,6 +107,6 @@ | ||
const oidc = new ExpressOIDC({ | ||
issuer: YOUR_ISSUER, | ||
client_id: YOUR_CLIENT_ID, | ||
client_secret: YOUR_CLIENT_SECRET, | ||
redirect_uri: YOUR_REDIRECT_URI, | ||
issuer: 'https://{yourOktaDomain}/oauth2/default', | ||
client_id: '{clientId}', | ||
client_secret: '{clientSecret}', | ||
redirect_uri: '{redirectUri}', | ||
scope: 'openid profile' | ||
@@ -99,6 +118,6 @@ }); | ||
* **issuer** - The OIDC provider (e.g. `https://YOUR_ORG.oktapreview.com/oauth2/default`) | ||
* **issuer** - The OIDC provider (e.g. `https://{yourOktaDomain}/oauth2/default`) | ||
* **client_id** - An id provided when you create an OIDC app in your Okta Org | ||
* **client_secret** - A secret provided when you create an OIDC app in your Okta Org | ||
* **redirect_uri** - The callback for your app. Locally, this is usually `http://localhost:3000/authorization-code/callback`. When deployed, this should be `https://YOUR_PROD_DOMAIN/authorization-code/callback`. | ||
* **redirect_uri** - The callback for your app. Locally, this is usually `http://localhost:3000/authorization-code/callback`. When deployed, this should be `https://{yourProductionDomain}/authorization-code/callback`. | ||
@@ -189,10 +208,23 @@ Optional config: | ||
### req.userinfo | ||
### req.userContext | ||
This provides information about the authenticated user, and is obtained from the [userinfo endpoint of the authorization server](https://developer.okta.com/docs/api/resources/oidc.html#get-user-information) and depends on the scope requested (see scope option above): | ||
This provides information about the authenticated user and contains the requested tokens. The `userContext` object contains two keys: | ||
1. `userinfo`: The response from the [userinfo endpoint of the authorization server](https://developer.okta.com/docs/api/resources/oidc.html#get-user-information). | ||
2. `tokens`: [TokenSet object](https://github.com/panva/node-openid-client#tokenset) containing the `accessToken`, `idToken`, and/or `refreshToken` requested from the authorization server. | ||
> Note: Claims reflected in the userinfo response and token object depend on the scope requested (see scope option above). | ||
```javascript | ||
app.get('/', (req, res) => { | ||
if (req.userinfo) { | ||
res.send(`Hi ${req.userinfo.sub}!`); | ||
if (req.userContext) { | ||
const tokenSet = req.userContext.tokens; | ||
const userinfo = req.userContext.userinfo; | ||
console.log(`Access Token: ${tokenSet.access_token}`); | ||
console.log(`Id Token: ${tokenSet.id_token}`); | ||
console.log(`Claims: ${tokenSet.claims}`); | ||
console.log(`Userinfo Response: ${userinfo}`); | ||
res.send(`Hi ${userinfo.sub}!`); | ||
} else { | ||
@@ -204,2 +236,4 @@ res.send('Hi!'); | ||
## Customization | ||
### Customizing Routes | ||
@@ -273,6 +307,8 @@ | ||
function addUserContext(req, res, next) { | ||
if (!req.userinfo) return next(); | ||
if (!req.userContext) { | ||
return next(); | ||
} | ||
// request additional info from your database | ||
User.findOne({ id: req.userinfo.sub }, (err, user) => { | ||
User.findOne({ id: req.userContext.userinfo.sub }, (err, user) => { | ||
if (err) return next(err); | ||
@@ -295,1 +331,20 @@ req.user = user; | ||
[Okta Developer Forum]: https://devforum.okta.com/ | ||
### Using Proxy Servers | ||
The underlying [openid-client][] library can be configured to use the [request][] library. Do this by adding these lines to your app, before you call `new ExpressOIDC()`: | ||
```javascript | ||
const Issuer = require('openid-client').Issuer; | ||
Issuer.useRequest(); | ||
const oidc = new ExpressOIDC({ | ||
... | ||
}); | ||
``` | ||
Once you have done that you can read the documentation on the [request][] library to learn which environment variables can be used to define your proxy settings. | ||
[openid-client]: https://github.com/panva/node-openid-client | ||
[request]: https://github.com/request/request |
@@ -25,3 +25,3 @@ /*! | ||
const oidcRouter = new Router(); | ||
oidcRouter.use(passport.initialize({ userProperty: 'userinfo' })); | ||
oidcRouter.use(passport.initialize({ userProperty: 'userContext' })); | ||
oidcRouter.use(passport.session()); | ||
@@ -109,2 +109,2 @@ | ||
} | ||
} | ||
}; |
@@ -14,9 +14,12 @@ /*! | ||
const EventEmitter = require('events').EventEmitter; | ||
const uuid = require('uuid'); | ||
const _ = require('lodash'); | ||
const oidcUtil = require('./oidcUtil'); | ||
const connectUtil = require('./connectUtil'); | ||
const { | ||
assertIssuer, | ||
assertClientId, | ||
assertClientSecret, | ||
assertRedirectUri | ||
} = require('./configUtil'); | ||
class OIDCMiddlewareError extends Error {} | ||
/** | ||
@@ -40,2 +43,3 @@ * Class to easily integrate OpenId Connect with Express | ||
* @param {number} [options.maxClockSkew=120] The maximum discrepancy allowed between server clocks in seconds | ||
* @param {Object} [options.testing] Testing overrides for disabling configuration validation | ||
* @param {Object} [options.routes] | ||
@@ -60,11 +64,14 @@ * @param {Object} [options.routes.login] | ||
const missing = []; | ||
if (!issuer) missing.push('issuer'); | ||
if (!client_id) missing.push('client_id'); | ||
if (!client_secret) missing.push('client_secret'); | ||
if (!redirect_uri) missing.push('redirect_uri'); | ||
if (missing.length) { | ||
throw new OIDCMiddlewareError(`${missing.join(', ')} must be defined`); | ||
} | ||
// Validate the issuer param | ||
assertIssuer(issuer, options.testing); | ||
// Validate the client_id param | ||
assertClientId(client_id); | ||
// Validate the client_secret param | ||
assertClientSecret(client_secret); | ||
// Validate the redirect_uri param | ||
assertRedirectUri(redirect_uri); | ||
// Add defaults to the options | ||
@@ -71,0 +78,0 @@ options = _.merge({ |
@@ -68,3 +68,3 @@ /*! | ||
}); | ||
} | ||
}; | ||
@@ -78,4 +78,9 @@ oidcUtil.bootstrapPassportStrategy = context => { | ||
client: context.client | ||
}, (tokens, userinfo, done) => { | ||
done(null, userinfo); | ||
}, (tokenSet, userinfo, done) => { | ||
return tokenSet && userinfo | ||
? done(null, { | ||
userinfo: userinfo, | ||
tokens: tokenSet | ||
}) | ||
: done(null); | ||
}); | ||
@@ -82,0 +87,0 @@ |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
41467
9
384
0
340