Documentation
Helper

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
}