A Hapi plugin implementation of the core and discovery OpenID-Connect provider API
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
lib
sample_app
scripts
test
.editorconfig
.eslintrc.json
.gitignore
.npmignore
LICENSE
README.md
package.json

README.md

hapi-openid-connect

This module is a Hapi plugin implementation of the core and discovery OpenID-Connect / OAuth 2.0 provider API.

Please Note That This Plugin Is An Implementation Of The More Recent (Newer) Version Of OpenID: OpenId Connect, And It Does Not Support The Older OpenID 2.0. All OpenID 2.0-specific features, such as realm, are not supported. Furthermore, there is no plan for this plugin to support migration from the older OpenID 2.0 to the newer OpenID Connect.

Release (>= 3.x.x) of this plugin is upgraded for hapi version >= 17,. It is compliant with the OpenID Connect / OAuth 2.0 documentation, and offers the following endpoint implementation:

1- authorization endpoint:

2- The discovery implementation of OpenID Connect is implemented. The specification implementation is comprised in the following endpoints:

  • JWKS endpoint: for retrieval of public key
  • JWKS_X5C endpoint: for retrieval of public X5C certificate
  • /.well-known/openid-configuration endpoint: for a JSON documentation of the entire discovery API implementation.

3- The token endpoint implementation covers:

  • Authorization Code Grant Type
  • Resource Owner Password Credentials Grant Type

4- The user_info endpoint:

  • The signin (login) function is implemented to fully support redirects as per the OpenID Connect specification for the Authorization Code Request. The implementation requires/depends on the hapi-auth-cookie plugin.
  • The signout function is implemented

Limitations of The Current Release

  • Client dynamic registration IS NOT INCLUDED", it is left to the plugin user to implement
  • Only authorization code flow request is implemented
  • The token endpoint DOES NOT IMPLEMENT the Refresh Token Grant Type

Usage

Sample Application

This release includes a fully functional sample application (sample_app), built on the valde-hapi stack. The sample application:

1- is intended as a guidance implementation, and it is not a full implementation of OP.

2- uses mongoDB for persistence of authorization requests, and tokens.

3- relies on an instance of nginx for termination of the SSL

4- relies on mongoDB indexes ("expireAfter" indexes) for automatic deletion of expired tokens.

5- provides guidance on the implementation of the registrars required for the hapi-openid-connect plugin.

Configuration

The hapi-openid-connect plugin is a standard hapi plugin, and is registered on the hapi stack in a standard way:

  let hapi_openid_connect = require("hapi-openid-connect");

  ...
  server.register(hapi_openid_connect, oidc_options, callback);
  ...

Where oidc_options is a json configuration object as follows:

{
    "oidc_url_path": "/sample_app/oidc",
    "version": 1,
    "configuration": {
        "issuer": "https://localhost:8443/sample_app/oidc",
        "issuer_audience": "123456788",
        "scopes_supported": [
            "profile",
            "address",
            "email",
            "phone"
        ],
        "jwk": {
            "cert_type_rsa": true,
            "priv_key_file_name": "./config/oidc/sampleapp-key.pem",
            "pub_key_file_name": "./config/oidc/sampleapp-cert.pem",
            "cert_chain_file_name": "./config/oidc/sampleapp-cert-chain.pem"
        },
        "authorization_endpoint": {
            "authorization_request_registrar_module": "/lib/authorization_request_registrar_module"
        },
        "token_endpoint": {
            "token_registrar_module": "/lib/token_registrar_module",
            "authorization_code_grant_type": {
                "token_duration_seconds": 600
            },
            "password_grant_type": {
                "token_duration_seconds": 900
            }
        },
        "user_info_endpoint": {
            "user_authentication_url": "https://localhost.sampleapp.com:8443/sample_app/oidc/signin",
            "user_post_login_account_url": "https://localhost.sampleapp.com:8443/sample_app/oidc/account",
            "user_account_registrar_module": "/lib/user_account_registrar_module"
        },
        "client_endpoint": {
            "client_registrar_module": "/lib/client_registrar_module"
        }
    }
}

Configuration Attributes

Most of the attributes in the json configuration object are self-explanatory, and the registrar ones are described as follows:

authorization_endpoint

  • authorization_request_registrar_module: This attribute is a path to a commonjs module which will be "required" by the hapi-openid-connect code. The hapi-openid-connect plugin require this module to export the following functions, which must return promises:

    1- put_authorization_request(authorization_request) which must update the authorization_request object in the persistence store.

    2- get_authorization_request(authorization_request_id) which must retrieve the authorization_request associated with the authorization_request_id argument from the persistence store.

    3- post_authorization_request(authorization_request) which must persist the authorization_request object, and return an id for it.

    4- delete_authorization_request(authorization_request_id) which must delete the authorization request from the persistence store

token_endpoint

  • token_registrar_module: This attribute is a path to a commonjs module which will be "required" by the hapi-openid-connect code. The hapi-openid-connect plugin require this module to export the following functions, which must return promises:

    1- put_token(oidc_token) which must update the oidc_token object in the psersistence store.

    2- get_token(oidc_token_id) which must retrieve the oidc_token associated with the oidc_token_id argument from the persistence store. The oidc_token_id is also used as the access_token.

    3- post_token(oidc_token) which must persist the oidc_token object, and return an id for it.

    4- delete_token(oidc_token_id) which must delete the oidc_token request from the persistence store.

usrer_info_endpoint

  • user_authentication_url: this is the https URL for the end_user authentication page (signin or login page).

  • user_post_login_account_url: this is the https URL for the end_user account page (after signin or login page).

  • user_account_registrar_module: This attribute is a path to a commonjs module which will be "required" by the hapi-openid-connect code. The hapi-openid-connect plugin require this module to export the following functions, which must return promises:

    • get_user_account_id_for_credentials(username, password):

      • verify that the username and password match a user account record
      • if the user account is found, set the hapi-auth-cookie session cookie for the request if not already set.
      • return a Promise that must resolve with the user account id (the id is a unique string for the respective user account)
      • reject the Promise if the user account does not exist, or the credentials provided do not match.

      The returned/resolved user account id must be a string, and it must be less than 255 characters (as per the OpenID specs).

client_endpoint

  • client_registrar_module: This attribute is a path to a commonjs module which will be "required" by the hapi-openid-connect code. The hapi-openid-connect plugin require this module to export the following functions, which must return promises:

    • get_client_registration(clientId): This method must return a Promise which resolves to the client registration entry from a persistent store. The client registration entry must at least have the following attributes:

      • redirect_uri_hostname
      • redirect_uri_port
      • redirect_uri_path, and
      • description, which describes the permissions the client is requesting.
    • get_client_account_id_for_credentials(username, password):

      • verify that the username and password match a client account record
      • return a Promise that must resolve with the client account id (the id is a unique string for the respective client account)
      • reject the Promise if the client account does not exist, or the credentials provided do not match.

      The returned/resolved user account id must be a string, and it must be less than 255 characters (as per the OpenID specs).

    • process_signin_request(request, h):

      • verify that the username and password match a client account record
      • setup the session state to reflect signed in state if an account is found for the credentials in request.payload.username and request.payload.password
      • return a Promise that must resolve with the client account id (the id is a unique string for the respective client account)
      • reject the Promise if the client account does not exist, or the credentials provided in request.payload do not match.

      The returned/resolved user account id must be a string, and it must be less than 255 characters (as per the OpenID specs).