Anvil Connect is a modern authorization server built to authenticate your users and protect your APIs. It's based on OAuth 2.0 and OpenID Connect.
This library is a low level OpenID Connect and Anvil Connect API client. Previous versions included Express-specific functions and middleware. These higher-level functions are being split out into a [separate library][connect-express].
$ npm install camfou-connect-nodejs --save
Before performing any other operations (such as verifying or refreshing OIDC tokens, or accessing the AnvilConnect-specific API (such as creating users), an OIDC client needs to be configured and registered with the server (OIDC Provider, OP for short).
var ConnectClient = require('camfou-connect-nodejs');
// If the client has been pre-registered, pass the credentials to constructor
var client = new ConnectClient({
issuer: 'https://connect.example.com',
client_id: 'CLIENT_ID',
client_secret: 'CLIENT_SECRET',
redirect_uri: 'REDIRECT_URI',
scope: 'realm'
})
client.initProvider()
.then(function () {
// Ready to verify() tokens, refresh(), etc
})
// If the client has not been registered, use OIDC dynamic registration
var client = new ConnectClient({ issuer: 'https://connect.example.com' })
client.initProvider()
.then(function () {
// Provider config loaded (.discover() and .getJWKs() called)
// Ready to register()
return client.register({
// ... see below for registration options
})
})
.then(function () {
// Client is now registered. Ready to verify() tokens, refresh(), etc
})
.catch(function (err) {
// as always, don't forget error handling
})
options
issuer
– REQUIRED uri of your OpenID Connect providerclient_id
– OPTIONAL client identifier issued by OIDC provider during registrationclient_secret
– OPTIONAL confidential value issued by OIDC provider during registrationredirect_uri
– OPTIONAL uri users will be redirected back to after authenticating with the issuerscope
– OPTIONAL array of strings, or space delimited string value containing scopes to be included in authorization requests. Defaults toopenid profile
Returns a promise providing OpenID Metadata retrieved from the
.well-known/openid-configuration
endpoint for the configured issuer. Sets the
response data as client.configuration
.
example
client.discover()
.then(function (openidMetadata) {
// client.configuration === openidMetadata
})
.catch(function (error) {
// ...
})
Returns a promise providing the JWK set published by the configured issuer.
Depends on a prior call to client.discover()
.
example
client.getJWKs()
.then(function (jwks) {
// client.jwks === jwks
})
.catch(function (error) {
// ...
})
Dynamically registers a new client with the configured issuer and returns a
promise for the new client registration. You can learn more about dynamic
registration for Anvil Connect in the docs. Depends on a
prior call to client.discover()
.
example
var options = {
client_name: 'Antisocial Network',
client_uri: 'https://app.example.com',
logo_uri: 'https://app.example.com/assets/logo.png',
response_types: ['code'],
grant_types: ['authorization_code', 'refresh_token'],
default_max_age: 86400, // one day in seconds
redirect_uris: ['https://app.example.com/callback.html', 'https://app.example.com/other.html'],
post_logout_redirect_uris: ['https://app.example.com']
}
client.register(options)
.then(function (data) {
// After the register request resolves
// client.client_id and .client_secret are initialized
// and the rest of the returned data is set to client.registration
})
Accepts a string specifying a non-default endpoint or an options object and
returns an authorization URI. Depends on a prior call to client.discover()
and
client_id
being configured.
options
- All options accepted by
client.authorizationParams()
. endpoint
– This value is used for the path in the returned URI. Defaults toauthorize
.
example
client.authorizationUri()
// 'https://connect.example.com/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=openid%20profile%20more'
client.authorizationUri('signin')
// 'https://connect.example.com/signin?response_type=code&client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=openid%20profile%20more'
client.authorizationUri({
endpoint: 'connect/google',
response_type: 'code id_token token',
redirect_uri: 'OTHER_REDIRECT_URI',
scope: 'openid profile extra'
})
// 'https://connect.example.com/connect/google?response_type=code%20id_token%20token&client_id=CLIENT_ID&redirect_uri=OTHER_REDIRECT_URI&scope=openid%20profile%20extra'
Accepts an options object and returns an object containing authorization params
including default values. Depends on client_id
being configured.
Note: This is a low-level function used by authorizationUri()
,
documented to list its parameters (which are passed through to
authorizationParams()
). It's unlikely that your code will be invoking it
directly.
options
response_type
– defaults tocode
redirect_uri
– defaults to theredirect_uri
configured for this clientscope
– defaults to the scope configured for this clientstate
response_mode
nonce
display
prompt
max_age
ui_locales
id_token_hint
login_hint
acr_values
email
password
provider
Given an authorization code is provided as the code
option, this method will
exchange the auth code for a set of token credentials, then verify the
signatures and decode the payloads. Depends on client_id
and client_secret
being configured, and prior calls to client.discover()
and client.getJWKs()
.
options
code
– value obtained from a successful authorization request withcode
in theresponse_types
request param
example
client.token({ code: 'AUTHORIZATION_CODE' })
Given an refresh_token is provided as the refresh_token
option, this method
will exchange the refresh_token for a set of token credentials, then verify the
signatures. Depends on client_id
and client_secret
being configured, and
prior calls to client.discover()
and client.getJWKs()
.
options
refresh_token
– value obtained from a successful authorization request withtoken
in theresponse_types
request param
example
client.refresh({ refresh_token: 'REFRESH_TOKEN' })
Get user info from the issuer.
options
token
– access token
example
client.userInfo({ token: 'ACCESS_TOKEN' })
Anvil Connect provides a backend admin-only API (outside of the OIDC specs), for managing clients, users and so on.
Note: All of these operations require an access token passed in options.token
.
You can get this token either via an admin user (with an authority
role
assigned to them) login, OR via a Client Credentials Grant request
(see client.getClientAccessToken()
docs in ../index.js
).
Example Usage:
client.getClientAccessToken()
.then(function (accessToken) {
var options = { token: accessToken }
// Once you have the access token you can
// call client.users.update(), create(), delete(), etc
return client.users.create(userData, options)
})
var AnvilConnectClient = require('anvil-connect-nodejs');
// Assumes a preregistered client (if not, call register() after initProvider())
var client = new AnvilConnectClient({
issuer: 'https://connect.example.com',
client_id: 'CLIENT_ID',
client_secret: 'CLIENT_SECRET',
redirect_uri: 'REDIRECT_URI'
})
// Initialize the provider config (endpoints and public keys)
client.initProvider()
.then(function () {
// At this point, provider config and public keys are loaded and cached
console.log(client.configuration)
console.log(jwks)
// Now, build an authorization url
return client.authorizationUri()
})
.then(function (url) {
console.log(url)
// handle an authorization response
// this verifies the signatures on tokens received from the authorization server
return client.token({ code: 'AUTHORIZATION_CODE' })
})
.then(function (tokens) {
// a successful call to tokens() gives us id_token, access_token,
// refresh_token, expiration, and the decoded payloads of the JWTs
console.log(tokens)
// get userinfo
return client.userInfo({ token: tokens.access_token })
})
.then(function (userInfo) {
console.log(userInfo)
// verify an access token received by an API service
return client.verify(JWT, { scope: 'research' })
})