Skip to Content

Helper

A collection of JS helper functions for browsers and servers integrating Hellō.

  • @hellocoop/helper-browser is a browser optimized package
  • @hellocoop/helper-server is a Node.js npm package

The APIs are the same except where noted.

Installation

Node.js

npm i @hellocoop/helper-server

Browser

npm i @hellocoop/helper-browser

Usage

Node.js

import { createAuthRequest, fetchToken, parseToken } from '@hellocoop/helper-server'

Browser

import { createAuthRequest, fetchToken, parseToken, validateToken, createInviteRequest, generateChallenge, verifyChallenge, pkceChallenge } from '@hellocoop/helper-browser'

createAuthRequest()

const { url, nonce, code_verifier } = await createAuthRequest(config)

A helper function to create the url to load in the browser to make the request to Hellō.

config = { client_id: OAuth "client_id" parameter - REQUIRED redirect_uri: OAuth "redirect_uri" parameter - REQUIRED scope?: array of zero or more scopes to request - default ['openid','name','email','picture'] response_type?: 'id_token'|'code' - default 'code' response_mode?: 'fragment'|'query'|'form_post' - default 'query' nonce?: OpenID Connect "nonce" parameter override. state?: OAuth "state" parameter login_hint?: a hint for which user account to use. domain_hint?: a hint for which domain or type of account (see below) provider_hint?: array of provider hint update values (see below) prompt?: - 'login' | 'consent' (see below) wallet?: alternative mock wallet URL for testing }

Returns

{ url: URL to load in the browser to make the authorization request nonce: nonce to remember for verifying the returned ID Token code_verifier: returned if a "code" flow }

If the request is approved by the user, the redirect_uri will receive the response per the response_mode as 'fragment'|'query'|'form_post' parameters (query is default). The response will be per the response_mode and either an id_token or a code (code is default).

fetchToken()

const token = await fetchToken(config)

A helper function to fetch an ID Token after a code flow.

config = { client_id: OAuth "client_id" parameter used in request - REQUIRED redirect_uri: OAuth "redirect_uri" parameter used in request - REQUIRED code_verifier: OAuth "code_verifier" created with `createAuthRequest()` code: OAuth "code" parameter returned from request wallet?: string; alternative mock wallet host for testing }

returns an ID Token in the JWT compact format (a string). Note that the ID Token does not require validation as it came directly from Hellō and is bound to the provided code_verifier used in the request

validateToken() (Browser Only)

const response = await validateToken(config)

A helper function to validate an ID token via Hellō’s introspection endpoint.

config = { token: string - The ID token to validate - REQUIRED client_id: string - OAuth "client_id" parameter - REQUIRED nonce?: string - The nonce used in the original request wallet?: string - Alternative mock wallet host for testing }

Returns

{ active: boolean - Whether the token is active sub: string - User identifier name?: string - User's name email?: string - User's email picture?: string - User's profile picture // ... other claims from the token }

parseToken()

const { header, payload } = parseToken(token)

Parses the header and payload from an ID Token. Does not verify the ID Token.

PKCE Functions

generateChallenge(code_verifier)

const challenge = await generateChallenge(code_verifier)

Generates a PKCE code challenge from a code verifier using SHA256.

code_verifier: string - The code verifier to generate challenge from - REQUIRED

Returns a base64url-encoded SHA256 hash of the code verifier.

verifyChallenge(code_verifier, expectedChallenge)

const isValid = await verifyChallenge(code_verifier, expectedChallenge)

Verifies that a code verifier produces the expected code challenge.

code_verifier: string - The code verifier to verify - REQUIRED expectedChallenge: string - The expected code challenge - REQUIRED

Returns true if the challenges match, false otherwise.

pkce() / pkceChallenge()

const { code_verifier, code_challenge } = await pkce()

Generates a PKCE challenge pair (code verifier and code challenge).

Returns

{ code_verifier: string - The code verifier (43 characters) code_challenge: string - The base64url-encoded SHA256 challenge }

createInviteRequest() (BETA)

const { url } = createInviteRequest(config)

A helper function to create the url to load in the browser to make the invite request to Hellō.

config = { inviter: `sub` provided by Hellō of the inviter - REQUIRED client_id: `client_id` for your application - REQUIRED initiate_login_uri: path where the invitee is sent upon accepting the invitation - REQUIRED return_uri: URI for Hellō to return the inviter when they are done - REQUIRED wallet?: string; alternative mock wallet host for testing app_name?: override the name of the app - defaults to the name registered for the `client_id` prompt?: override the prompt string shown to the invitee (see below) role?: identifier string passed back to the app in the event JWT as the `role` property tenant?: identifier string passed back to the app in the event JWT as the `tenant` property state?: identifier string passed back to the app in the event JWT as the `state` property events_uri?: The webhook where event JWTs are posted (see below) }

Returns

{ url: URL to load in the browser to make the invite request }

Server-Specific Functions

errorPage()

const html = errorPage(config)

Generates an HTML error page for server-side error handling.

config = { title?: string - Page title (default: "Error") message?: string - Error message to display details?: string - Additional error details }

Returns HTML string for the error page.

redirectURIBounce()

const html = redirectURIBounce(config)

Generates an HTML page that redirects to a URI with bounce functionality.

config = { redirect_uri: string - The URI to redirect to - REQUIRED delay?: number - Delay in milliseconds before redirect (default: 1000) message?: string - Message to display during redirect }

Returns HTML string for the redirect page.

wildcardConsole()

const html = wildcardConsole(config)

Generates an HTML console page for wildcard domain handling.

config = { domain: string - The wildcard domain - REQUIRED message?: string - Console message to display }

Returns HTML string for the console page.

sameSite()

const html = sameSite()

Generates an HTML page for SameSite cookie testing.

Returns HTML string for the SameSite test page.

Server Code Sample

Using:

  • response_type=code
  • response_mode=query
// server callback endpoint const { code, error } = res.query if (error) { // process error } // get nonce, code_verifier from server session data try { const token = await fetchToken({ client_id: HELLO_CLIENT_ID, redirect_uri: REDIRECT_URI, // the callback endpoint code_verifier, code }) const { payload } = parseToken(token) if (payload.nonce !== nonce) { // process error } const { sub, name, email, picture } = payload // make use of user data } catch (err) { // deal with error }

Client Code Sample

Using:

  • response_type=id_token
  • response_mode=fragment
const params = new URLSearchParams(window.location.hash.substring(1)) const token = params.get('id_token') if (!token || params.has('error')) { // process error } // get nonce from sessionStorage try { const response = validateToken({ client_id: HELLO_CLIENT_ID, token, nonce }) if (!response.active) { // process error } const { sub, name, email, picture } = response // make use of user data } catch (err) { // deal with error }

PKCE Code Sample

Using PKCE for enhanced security:

// Generate PKCE challenge pair const { code_verifier, code_challenge } = await pkce() // Create auth request with PKCE const { url, nonce } = await createAuthRequest({ client_id: HELLO_CLIENT_ID, redirect_uri: REDIRECT_URI, scope: ['openid', 'name', 'email', 'picture'], response_type: 'code', response_mode: 'query' }) // Store code_verifier and nonce in session sessionStorage.setItem('code_verifier', code_verifier) sessionStorage.setItem('nonce', nonce) // Redirect user to Hellō window.location.href = url // After callback, exchange code for token const { code } = req.query const code_verifier = sessionStorage.getItem('code_verifier') try { const token = await fetchToken({ client_id: HELLO_CLIENT_ID, redirect_uri: REDIRECT_URI, code_verifier, code }) const { payload } = parseToken(token) const { sub, name, email, picture } = payload // Use user data } catch (err) { // Handle error }