UNPKG

10.1 kBMarkdownView Raw
1# Anvil Connect client for Node.js
2[![NPM Version](https://img.shields.io/npm/v/anvil-connect-nodejs.svg?style=flat)](https://npm.im/anvil-connect-nodejs)
3[![Build Status](https://travis-ci.org/anvilresearch/connect-nodejs.svg?branch=master)](https://travis-ci.org/anvilresearch/connect-nodejs)
4
5[Anvil Connect][connect] is a modern authorization server built to authenticate
6your users and protect your APIs. It's based on [OAuth 2.0][oauth2] and
7[OpenID Connect][oidc].
8
9This library is a low level OpenID Connect and Anvil Connect API client.
10Previous versions included Express-specific functions and
11middleware. These higher-level functions are being split out into a
12[separate library][connect-express].
13
14[oauth2]: http://tools.ietf.org/html/rfc6749
15[oidc]: http://openid.net/connect/
16[connect]: https://github.com/anvilresearch/connect
17[connect-nodejs]: https://github.com/anvilresearch/connect-nodejs
18[connect-express]: https://github.com/anvilresearch/connect-express
19
20### Install
21
22```bash
23$ npm install anvil-connect-nodejs --save
24```
25
26### Configure
27
28Before performing any other operations (such as verifying or refreshing OIDC
29tokens, or accessing the AnvilConnect-specific API (such as creating users),
30an OIDC client needs to be configured and registered with the server (OIDC
31Provider, OP for short).
32
33#### new AnvilConnect(config)
34
35```javascript
36var AnvilConnectClient = require('anvil-connect-nodejs');
37
38// If the client has been pre-registered, pass the credentials to constructor
39var client = new AnvilConnectClient({
40 issuer: 'https://connect.example.com',
41 client_id: 'CLIENT_ID',
42 client_secret: 'CLIENT_SECRET',
43 redirect_uri: 'REDIRECT_URI',
44 scope: 'realm'
45})
46client.initProvider()
47 .then(function () {
48 // Ready to verify() tokens, refresh(), etc
49 })
50
51// If the client has not been registered, use OIDC dynamic registration
52var client = new AnvilConnectClient({ issuer: 'https://connect.example.com' })
53client.initProvider()
54 .then(function () {
55 // Provider config loaded (.discover() and .getJWKs() called)
56
57 // Ready to register()
58 return client.register({
59 // ... see below for registration options
60 })
61 })
62 .then(function () {
63 // Client is now registered. Ready to verify() tokens, refresh(), etc
64 })
65 .catch(function (err) {
66 // as always, don't forget error handling
67 })
68```
69
70**options**
71
72* `issuer` – REQUIRED uri of your OpenID Connect provider
73* `client_id` – OPTIONAL client identifier issued by OIDC provider during
74 registration
75* `client_secret` – OPTIONAL confidential value issued by OIDC provider during
76 registration
77* `redirect_uri` – OPTIONAL uri users will be redirected back to after
78 authenticating with the issuer
79* `scope` – OPTIONAL array of strings, or space delimited string value
80 containing scopes to be included in authorization requests.
81 Defaults to `openid profile`
82
83
84### OpenID Connect
85
86#### client.discover()
87
88Returns a promise providing [OpenID Metadata][oidc-meta] retrieved from the
89`.well-known/openid-configuration` endpoint for the configured issuer. Sets the
90response data as `client.configuration`.
91
92[oidc-meta]: http://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
93
94**example**
95
96```javascript
97client.discover()
98 .then(function (openidMetadata) {
99 // client.configuration === openidMetadata
100 })
101 .catch(function (error) {
102 // ...
103 })
104```
105
106#### client.getJWKs()
107
108Returns a promise providing the JWK set published by the configured issuer.
109Depends on a prior call to `client.discover()`.
110
111**example**
112
113```javascript
114client.getJWKs()
115 .then(function (jwks) {
116 // client.jwks === jwks
117 })
118 .catch(function (error) {
119 // ...
120 })
121```
122
123#### client.register(registration)
124
125Dynamically registers a new client with the configured issuer and returns a
126promise for the new client registration. You can learn more about [dynamic
127registration for Anvil Connect][dynamic-registration] in the docs. Depends on a
128prior call to `client.discover()`.
129
130[dynamic-registration]: https://github.com/anvilresearch/connect-docs/blob/master/clients.md#dynamic-registration
131
132**example**
133
134```javascript
135var options = {
136 client_name: 'Antisocial Network',
137 client_uri: 'https://app.example.com',
138 logo_uri: 'https://app.example.com/assets/logo.png',
139 response_types: ['code'],
140 grant_types: ['authorization_code', 'refresh_token'],
141 default_max_age: 86400, // one day in seconds
142 redirect_uris: ['https://app.example.com/callback.html', 'https://app.example.com/other.html'],
143 post_logout_redirect_uris: ['https://app.example.com']
144}
145client.register(options)
146 .then(function (data) {
147 // After the register request resolves
148 // client.client_id and .client_secret are initialized
149 // and the rest of the returned data is set to client.registration
150 })
151```
152
153#### client.authorizationUri([endpoint|options])
154
155Accepts a string specifying a non-default endpoint or an options object and
156returns an authorization URI. Depends on a prior call to `client.discover()` and
157`client_id` being configured.
158
159**options**
160
161* All options accepted by `client.authorizationParams()`.
162* `endpoint` – This value is used for the path in the returned URI. Defaults to `authorize`.
163
164**example**
165
166```javascript
167client.authorizationUri()
168// 'https://connect.example.com/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=openid%20profile%20more'
169
170client.authorizationUri('signin')
171// 'https://connect.example.com/signin?response_type=code&client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=openid%20profile%20more'
172
173client.authorizationUri({
174 endpoint: 'connect/google',
175 response_type: 'code id_token token',
176 redirect_uri: 'OTHER_REDIRECT_URI',
177 scope: 'openid profile extra'
178})
179// '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'
180```
181
182
183#### client.authorizationParams(options)
184
185Accepts an options object and returns an object containing authorization params
186including default values. Depends on `client_id` being configured.
187
188*Note:* This is a low-level function used by `authorizationUri()`,
189documented to list its parameters (which are passed through to
190`authorizationParams()`). It's unlikely that your code will be invoking it
191directly.
192
193**options**
194
195* `response_type` – defaults to `code`
196* `redirect_uri` – defaults to the `redirect_uri` configured for this client
197* `scope` – defaults to the scope configured for this client
198* `state`
199* `response_mode`
200* `nonce`
201* `display`
202* `prompt`
203* `max_age`
204* `ui_locales`
205* `id_token_hint`
206* `login_hint`
207* `acr_values`
208* `email`
209* `password`
210* `provider`
211
212#### client.token(options)
213
214Given an authorization code is provided as the `code` option, this method will
215exchange the auth code for a set of token credentials, then verify the
216signatures and decode the payloads. Depends on `client_id` and `client_secret`
217being configured, and prior calls to `client.discover()` and `client.getJWKs()`.
218
219**options**
220
221 * `code` – value obtained from a successful authorization request with `code`
222 in the `response_types` request param
223
224**example**
225
226```javascript
227client.token({ code: 'AUTHORIZATION_CODE' })
228```
229
230#### client.refresh(options)
231
232Given an refresh_token is provided as the `refresh_token` option, this method
233will exchange the refresh_token for a set of token credentials, then verify the
234signatures. Depends on `client_id` and `client_secret` being configured, and
235prior calls to `client.discover()` and `client.getJWKs()`.
236
237**options**
238
239* `refresh_token` – value obtained from a successful authorization request with
240 `token` in the `response_types` request param
241
242**example**
243
244```javascript
245client.refresh({ refresh_token: 'REFRESH_TOKEN' })
246```
247
248#### client.userInfo(options)
249
250Get user info from the issuer.
251
252**options**
253
254* `token` – access token
255
256**example**
257
258```javascript
259client.userInfo({ token: 'ACCESS_TOKEN' })
260```
261
262#### client.verify(token, options)
263
264### Anvil Connect API
265
266#### Clients
267
268#### client.clients.list()
269#### client.clients.get(id)
270#### client.clients.create(data)
271#### client.clients.update(id, data)
272#### client.clients.delete(id)
273
274#### Roles
275
276#### client.roles.list()
277#### client.roles.get(id)
278#### client.roles.create(data)
279#### client.roles.update(id, data)
280#### client.roles.delete(id)
281
282#### Scopes
283
284#### client.scopes.list()
285#### client.scopes.get(id)
286#### client.scopes.create(data)
287#### client.scopes.update(id, data)
288#### client.scopes.delete(id)
289
290#### Users
291
292#### client.users.list()
293#### client.users.get(id)
294#### client.users.create(data)
295#### client.users.update(id, data)
296#### client.users.delete(id)
297
298### Example
299
300```javascript
301var AnvilConnectClient = require('anvil-connect-nodejs');
302
303// Assumes a preregistered client (if not, call register() after initProvider())
304var client = new AnvilConnectClient({
305 issuer: 'https://connect.example.com',
306 client_id: 'CLIENT_ID',
307 client_secret: 'CLIENT_SECRET',
308 redirect_uri: 'REDIRECT_URI'
309})
310
311// Initialize the provider config (endpoints and public keys)
312client.initProvider()
313 .then(function () {
314 // At this point, provider config and public keys are loaded and cached
315 console.log(client.configuration)
316 console.log(jwks)
317
318 // Now, build an authorization url
319 return client.authorizationUri()
320 })
321 .then(function (url) {
322 console.log(url)
323
324 // handle an authorization response
325 // this verifies the signatures on tokens received from the authorization server
326 return client.token({ code: 'AUTHORIZATION_CODE' })
327 })
328 .then(function (tokens) {
329 // a successful call to tokens() gives us id_token, access_token,
330 // refresh_token, expiration, and the decoded payloads of the JWTs
331 console.log(tokens)
332
333 // get userinfo
334 return client.userInfo({ token: tokens.access_token })
335 })
336 .then(function (userInfo) {
337 console.log(userInfo)
338
339 // verify an access token received by an API service
340 return client.verify(JWT, { scope: 'research' })
341 })
342```