openid-client (with request)
openid-client is a server side OpenID Relying Party (RP, Client) implementation for Node.js, supports passport.
Differences from openid-client
This package has been modified to use the request
library for making HTTP connections,
rather than using got
. This makes it more compatible with tunneling agents where
you might be behind a proxy.
Table of Contents
- Implemented specs & features
- Certification
- Example
- Get started
- Usage
- Usage with passport
- Configuration
Implemented specs & features
The following client/RP features from OpenID Connect/OAuth2.0 specifications are implemented by openid-client.
- OpenID Connect Core 1.0 incorporating errata set 1
- Authorization Callback
- Authorization Code Flow
- Implicit Flow
- Hybrid Flow
- UserInfo Request
- Fetching Distributed Claims
- Unpacking Aggregated Claims
- Offline Access / Refresh Token Grant
- Client Credentials Grant
- Password Grant
- Client Authentication
- client_secret_basic
- client_secret_post
- client_secret_jwt
- private_key_jwt
- Authorization Callback
- OpenID Connect Discovery 1.0 incorporating errata set 1
- Discovery of OpenID Provider (Issuer) Metadata
- Discovery of OpenID Provider (Issuer) Metadata via user provided inputs (see #WebFinger)
- OpenID Connect Dynamic Client Registration 1.0 incorporating errata set 1
- Dynamic Client Registration request
- Client initialization via registration client uri
- RFC7009 - OAuth 2.0 Token revocation
- Client Authenticated request to token revocation
- RFC7662 - OAuth 2.0 Token introspection
- Client Authenticated request to token introspection
Certification
Filip Skokan has certified that openid-client conforms to the RP Basic, RP Implicit, RP Hybrid, RP Config and RP Dynamic profiles of the OpenID Connect™ protocol.
Example
Head over to the example folder to see the library in use. This example is deployed and configured to use an example OpenID Connect Provider here. The provider is using oidc-provider library.
Get started
On the off-chance you want to manage multiple clients for multiple issuers you need to first get an Issuer instance.
via Discovery (recommended)
const Issuer = Issuer;Issuer // => Promise ;
manually
const Issuer = Issuer;const googleIssuer = issuer: 'https://accounts.google.com' authorization_endpoint: 'https://accounts.google.com/o/oauth2/v2/auth' token_endpoint: 'https://www.googleapis.com/oauth2/v4/token' userinfo_endpoint: 'https://www.googleapis.com/oauth2/v3/userinfo' jwks_uri: 'https://www.googleapis.com/oauth2/v3/certs'; // => Issuerconsole;
Now you can create your Client.
manually (recommended)
You should provide the following metadata; client_id, client_secret
. You can also provide
id_token_signed_response_alg
(defaults to RS256
) and token_endpoint_auth_method
(defaults to
client_secret_basic
);
const client = client_id: 'zELcpfANLqY7Oqas' client_secret: 'TQV5U29k1gHibH5bx1layBo0OSAvAbRT3UYW3EWrSYBB5swxjVfWUa1BS8lqzxG/0v9wruMcrGadany3'; // => Client
via registration client uri
Should your oidc provider have provided you with a registration client uri and registration access token you can also have the Client discovered.
registration_client_uri registration_access_token // => Promise ;
Usage
Getting authorization url
client; // => String (URL)
You can also get HTML body of a self-submitting form to utilize POST to the authorization url with
#authorizationPost
method, same signature as #authorizationUrl
.
client; // => String (Valid HTML body)
Processing callback
client // => Promise ;
Processing callback with state, nonce or max_age check
const state = sessionstate;const nonce = sessionnonce; client // => Promise ;
Handling multiple response modes
When handling multiple response modes with one single pass you can use #callbackParams
to get the params object from the koa/express/node request object or a url string.
(http.IncomingMessage). If form_post is your response_type you need to include a body parser prior.
client; // => { code: 'code' };client; // => { code: 'code' }; // koa v1.x w/ koa-bodyapp;app; // express w/ bodyParserapp;app;
Refreshing a token
client // => Promise ;
Tip: accepts TokenSet as well as direct refresh token values;
Revoke a token
client // => Promise ;
Introspect a token
client // => Promise ;
Fetching userinfo
client // => Promise ;
Tip: accepts TokenSet as well as direct access token values;
via POST
client; // => Promise
with extra query/body payload
client; // => Promise
auth via query
client; // => Promise
auth via body
client; // => Promise
userinfo also handles (as long as you have the proper metadata configured) responses that are:
- signed
- signed and encrypted (nested JWT)
- just encrypted
Fetching Distributed Claims
let claims = sub: 'userID' _claim_names: credit_history: 'src1' email: 'src2' _claim_sources: src1: endpoint: 'https://src1.example.com/claims' access_token: 'foobar' src2: endpoint: 'https://src2.example.com/claims' ; client // => Promise ; // when rejected the error will have a property 'src' with the source name it relates to
Unpacking Aggregated Claims
let claims = sub: 'userID' _claim_names: credit_history: 'src1' email: 'src2' _claim_sources: src1: JWT: 'probably.a.jwt' src2: JWT: 'probably.another.jwt' ; client // => Promise, autodiscovers JWT issuers, verifies signatures ; // when rejected the error will have a property 'src' with the source name it relates to
Custom token endpoint grants
Use when the token endpoint also supports client_credentials or password grants;
client; // => Promise client; // => Promise
Registering new client (via Dynamic Registration)
const opts = keystore initialAccessToken ; // both optionalissuerClient // => opts optional, Promise ;
Generating a signed/encrypted Request Object
client;
WebFinger discovery
Issuer // => Promise ;
Accepts, normalizes, discovers and validates the discovery of User Input using E-Mail, URL, acct, Hostname and Port syntaxes as described in Discovery 1.0.
Uses already discovered (cached) issuers where applicable.
TokenSet
authorizationCallback
and refresh
methods on a Client return TokenSet, when assigned an
expires_in
value a TokenSet calculates and assigns an expires_at
with the corresponding unix
time. It also comes with few helpers.
client;
Usage with passport
Once you have a Client instance, just pass it to the Strategy. Issuer is best discovered, Client passed properties manually or via an uri (see get-started).
Verify function is invoked with a TokenSet, userinfo only when requested, last argument is always the done function which you invoke once you found your user.
const Strategy = Strategy;const params = // ... any authorization params // client_id defaults to client.client_id // redirect_uri defaults to client.redirect_uris[0] // response type defaults to client.response_types[0], then 'code' // scope defaults to 'openid' passport; // start authentication request// options [optional], extra authentication parametersapp; // authentication callbackapp;
Configuration
Allow for system clock skew
It is possible the RP or OP environment has a system clock skew, to set a clock tolerance (in seconds)
clientCLOCK_TOLERANCE = 5; // to allow a 5 second skew
Changing HTTP request defaults
Setting defaultHttpOptions
on Issuer
always merges your passed options with the default.
openid-client uses got for http requests with the following default request options
const DEFAULT_HTTP_OPTIONS = followRedirect: false headers: 'User-Agent': `/ ()` retries: 0 timeout: 1500;
You can add your own headers, change the user-agent used or change the timeout setting
IssuerdefaultHttpOptions = timeout: 2500 headers: 'X-Your-Header': '<whatever>' ;
Confirm your httpOptions by
console;