•  


GitHub - panva/node-openid-client: OpenID Certified™ Relying Party (OpenID Connect/OAuth 2.0 Client) implementation for Node.js.
Skip to content

OpenID Certified™ Relying Party (OpenID Connect/OAuth 2.0 Client) implementation for Node.js.

License

Notifications You must be signed in to change notification settings

panva/node-openid-client

Repository files navigation

openid-client

openid-client is a server side OpenID Relying Party (RP, Client) implementation for Node.js runtime, supports passport .

Implemented specs & features

The following client/RP features from OpenID Connect/OAuth2.0 specifications are implemented by openid-client.

Updates to draft specifications are released as MINOR library versions, if you utilize these specification implementations consider using the tilde ~ operator in your package.json since breaking changes may be introduced as part of these version updates.

Certification

OpenID Certification
Filip Skokan has certified that openid-client conforms to the following profiles of the OpenID Connect™ protocol

  • Basic, Implicit, Hybrid, Config, Dynamic, and Form Post RP
  • FAPI 1.0 Advanced RP

Sponsor

auth0-logo If you want to quickly add OpenID Connect authentication to Node.js apps, feel free to check out Auth0's Node.js SDK and free plan. Create an Auth0 account; it's free!

Support

If you or your business use openid-client, please consider becoming a sponsor so I can continue maintaining it and adding new features carefree.

Documentation

The library exposes what are essentially steps necessary to be done by a relying party consuming OpenID Connect Authorization Server responses or wrappers around requests to its endpoints. Aside from a generic OpenID Connect passport strategy it does not expose any framework specific middlewares. Those can however be built using the exposed API, one such example is express-openid-connect

Install

Node.js LTS releases Codename Erbium and newer LTS releases are supported.

npm install openid-client

Note: Other javascript runtimes are not supported. I recommend panva/oauth4webapi , or a derivate thereof, if you're looking for a similarly compliant and certified client software that's not dependent on the Node.js runtime builtins.

Quick start

Discover an Issuer configuration using its published .well-known endpoints

import
 {
 Issuer
 }
 from
 'openid-client'
;


const
 googleIssuer
 =
 await
 Issuer
.
discover
(
'https://accounts.google.com'
)
;

console
.
log
(
'Discovered issuer %s %O'
,
 googleIssuer
.
issuer
,
 googleIssuer
.
metadata
)
;

Authorization Code Flow

Authorization Code flow is for obtaining Access Tokens (and optionally Refresh Tokens) to use with third party APIs securely as well as Refresh Tokens. In this quick start your application also uses PKCE instead of state parameter for CSRF protection.

Create a Client instance for that issuer's authorization server intended for Authorization Code flow.

See the documentation for full API details.

const
 client
 =
 new
 googleIssuer
.
Client
(
{

  client_id
: 
'zELcpfANLqY7Oqas'
,

  client_secret
: 
'TQV5U29k1gHibH5bx1layBo0OSAvAbRT3UYW3EWrSYBB5swxjVfWUa1BS8lqzxG/0v9wruMcrGadany3'
,

  redirect_uris
: 
[
'http://localhost:3000/cb'
]
,

  response_types
: 
[
'code'
]
,

  // id_token_signed_response_alg (default "RS256")

  // token_endpoint_auth_method (default "client_secret_basic")

}
)
;
 // => Client

When you want to have your end-users authorize you need to send them to the issuer's authorization_endpoint . Consult the web framework of your choice on how to redirect but here's how to get the authorization endpoint's URL with parameters already encoded in the query to redirect to.

import
 {
 generators
 }
 from
 'openid-client'
;

const
 code_verifier
 =
 generators
.
codeVerifier
(
)
;

// store the code_verifier in your framework's session mechanism, if it is a cookie based solution

// it should be httpOnly (not readable by javascript) and encrypted.


const
 code_challenge
 =
 generators
.
codeChallenge
(
code_verifier
)
;


client
.
authorizationUrl
(
{

  scope
: 
'openid email profile'
,

  resource
: 
'https://my.api.example.com/resource/32178'
,

  code_challenge
,

  code_challenge_method
: 
'S256'
,

}
)
;

When end-users are redirected back to your redirect_uri your application consumes the callback and passes in the code_verifier to include it in the authorization code grant token exchange.

const
 params
 =
 client
.
callbackParams
(
req
)
;

const
 tokenSet
 =
 await
 client
.
callback
(
'https://client.example.com/callback'
,
 params
,
 {
 code_verifier 
}
)
;

console
.
log
(
'received and validated tokens %j'
,
 tokenSet
)
;

console
.
log
(
'validated ID Token claims %j'
,
 tokenSet
.
claims
(
)
)
;

You can then call the userinfo_endpoint .

const
 userinfo
 =
 await
 client
.
userinfo
(
access_token
)
;

console
.
log
(
'userinfo %j'
,
 userinfo
)
;

And later refresh the tokenSet if it had a refresh_token .

const
 tokenSet
 =
 await
 client
.
refresh
(
refresh_token
)
;

console
.
log
(
'refreshed and validated tokens %j'
,
 tokenSet
)
;

console
.
log
(
'refreshed ID Token claims %j'
,
 tokenSet
.
claims
(
)
)
;

Implicit ID Token Flow

Implicit response_type=id_token flow is perfect for simply authenticating your end-users, assuming the only job you want done is authenticating the user and then relying on your own session mechanism with no need for accessing any third party APIs with an Access Token from the Authorization Server.

Create a Client instance for that issuer's authorization server intended for ID Token implicit flow.

See the documentation for full API details.

const
 client
 =
 new
 googleIssuer
.
Client
(
{

  client_id
: 
'zELcpfANLqY7Oqas'
,

  redirect_uris
: 
[
'http://localhost:3000/cb'
]
,

  response_types
: 
[
'id_token'
]
,

  // id_token_signed_response_alg (default "RS256")

}
)
;
 // => Client

When you want to have your end-users authorize you need to send them to the issuer's authorization_endpoint . Consult the web framework of your choice on how to redirect but here's how to get the authorization endpoint's URL with parameters already encoded in the query to redirect to.

import
 {
 generators
 }
 from
 'openid-client'
;

const
 nonce
 =
 generators
.
nonce
(
)
;

// store the nonce in your framework's session mechanism, if it is a cookie based solution

// it should be httpOnly (not readable by javascript) and encrypted.


client
.
authorizationUrl
(
{

  scope
: 
'openid email profile'
,

  response_mode
: 
'form_post'
,

  nonce
,

}
)
;

When end-users hit back your redirect_uri with a POST (authorization request included form_post response mode) your application consumes the callback and passes the nonce in to include it in the ID Token verification steps.

// assumes req.body is populated from your web framework's body parser

const
 params
 =
 client
.
callbackParams
(
req
)
;

const
 tokenSet
 =
 await
 client
.
callback
(
'https://client.example.com/callback'
,
 params
,
 {
 nonce 
}
)
;

console
.
log
(
'received and validated tokens %j'
,
 tokenSet
)
;

console
.
log
(
'validated ID Token claims %j'
,
 tokenSet
.
claims
(
)
)
;

Device Authorization Grant (Device Flow)

RFC8628 - OAuth 2.0 Device Authorization Grant (Device Flow) is started by starting a Device Authorization Request.

const
 handle
 =
 await
 client
.
deviceAuthorization
(
)
;

console
.
log
(
'User Code: '
,
 handle
.
user_code
)
;

console
.
log
(
'Verification URI: '
,
 handle
.
verification_uri
)
;

console
.
log
(
'Verification URI (complete): '
,
 handle
.
verification_uri_complete
)
;

The handle represents a Device Authorization Response with the verification_uri , user_code and other defined response properties.

You will display the instructions to the end-user and have him directed at verification_uri or verification_uri_complete , afterwards you can start polling for the Device Access Token Response.

const
 tokenSet
 =
 await
 handle
.
poll
(
)
;

console
.
log
(
'received tokens %j'
,
 tokenSet
)
;

This will poll in the defined interval and only resolve with a TokenSet once one is received. This will handle the defined authorization_pending and slow_down "soft" errors and continue polling but upon any other error it will reject. With tokenSet received you can throw away the handle.

Client Credentials Grant Flow

Client Credentials flow is for obtaining Access Tokens to use with third party APIs on behalf of your application, rather than an end-user which was the case in previous examples.

See the documentation for full API details.

const
 client
 =
 new
 issuer
.
Client
(
{

  client_id
: 
'zELcpfANLqY7Oqas'
,

  client_secret
: 
'TQV5U29k1gHibH5bx1layBo0OSAvAbRT3UYW3EWrSYBB5swxjVfWUa1BS8lqzxG/0v9wruMcrGadany3'
,

}
)
;


const
 tokenSet
 =
 await
 client
.
grant
(
{

  resource
: 
'urn:example:third-party-api'
,

  grant_type
: 
'client_credentials'

}
)
;

FAQ

Semver?

Yes. Everything that's either exported in the TypeScript definitions file or documented is subject to Semantic Versioning 2.0.0 . The rest is to be considered private API and is subject to change between any versions.

How do I use it outside of Node.js

It is only built for Node.js . Other javascript runtimes are not supported. I recommend panva/oauth4webapi , or a derivate thereof, if you're looking for a similarly compliant and certified client software that's not dependent on the Node.js runtime builtins.

How to make the client send client_id and client_secret in the body?

See Client Authentication Methods (docs) .

Can I adjust the HTTP timeout?

See Customizing (docs) .

- "漢字路" 한글한자자동변환 서비스는 교육부 고전문헌국역지원사업의 지원으로 구축되었습니다.
- "漢字路" 한글한자자동변환 서비스는 전통문화연구회 "울산대학교한국어처리연구실 옥철영(IT융합전공)교수팀"에서 개발한 한글한자자동변환기를 바탕하여 지속적으로 공동 연구 개발하고 있는 서비스입니다.
- 현재 고유명사(인명, 지명등)을 비롯한 여러 변환오류가 있으며 이를 해결하고자 많은 연구 개발을 진행하고자 하고 있습니다. 이를 인지하시고 다른 곳에서 인용시 한자 변환 결과를 한번 더 검토하시고 사용해 주시기 바랍니다.
- 변환오류 및 건의,문의사항은 juntong@juntong.or.kr로 메일로 보내주시면 감사하겠습니다. .
Copyright ⓒ 2020 By '전통문화연구회(傳統文化硏究會)' All Rights reserved.
 한국   대만   중국   일본