File

projects/lib/src/token-validation/validation-handler.ts

Description

Interface for Handlers that are hooked in to validate tokens.

Index

Methods

Methods

Public Abstract validateAtHash
validateAtHash(validationParams: ValidationParams)

Validates the at_hash in an id_token against the received access_token.

Parameters :
Name Type Optional
validationParams ValidationParams No
Returns : Promise<boolean>
Public Abstract validateSignature
validateSignature(validationParams: ValidationParams)

Validates the signature of an id_token.

Parameters :
Name Type Optional
validationParams ValidationParams No
Returns : Promise<any>
import { base64UrlEncode } from '../base64-helper';

export interface ValidationParams {
  idToken: string;
  accessToken: string;
  idTokenHeader: object;
  idTokenClaims: object;
  jwks: object;
  loadKeys: () => Promise<object>;
}

/**
 * Interface for Handlers that are hooked in to
 * validate tokens.
 */
export abstract class ValidationHandler {
  /**
   * Validates the signature of an id_token.
   */
  public abstract validateSignature(
    validationParams: ValidationParams
  ): Promise<any>;

  /**
   * Validates the at_hash in an id_token against the received access_token.
   */
  public abstract validateAtHash(
    validationParams: ValidationParams
  ): Promise<boolean>;
}

/**
 * This abstract implementation of ValidationHandler already implements
 * the method validateAtHash. However, to make use of it,
 * you have to override the method calcHash.
 */
export abstract class AbstractValidationHandler implements ValidationHandler {
  /**
   * Validates the signature of an id_token.
   */
  abstract validateSignature(validationParams: ValidationParams): Promise<any>;

  /**
   * Validates the at_hash in an id_token against the received access_token.
   */
  async validateAtHash(params: ValidationParams): Promise<boolean> {
    const hashAlg = this.inferHashAlgorithm(params.idTokenHeader);

    const tokenHash = await this.calcHash(params.accessToken, hashAlg); // sha256(accessToken, { asString: true });

    const leftMostHalf = tokenHash.substr(0, tokenHash.length / 2);

    const atHash = base64UrlEncode(leftMostHalf);

    const claimsAtHash = params.idTokenClaims['at_hash'].replace(/=/g, '');

    if (atHash !== claimsAtHash) {
      console.error('exptected at_hash: ' + atHash);
      console.error('actual at_hash: ' + claimsAtHash);
    }

    return atHash === claimsAtHash;
  }

  /**
   * Infers the name of the hash algorithm to use
   * from the alg field of an id_token.
   *
   * @param jwtHeader the id_token's parsed header
   */
  protected inferHashAlgorithm(jwtHeader: object): string {
    const alg: string = jwtHeader['alg'];

    if (!alg.match(/^.S[0-9]{3}$/)) {
      throw new Error('Algorithm not supported: ' + alg);
    }

    return 'sha-' + alg.substr(2);
  }

  /**
   * Calculates the hash for the passed value by using
   * the passed hash algorithm.
   *
   * @param valueToHash
   * @param algorithm
   */
  protected abstract calcHash(
    valueToHash: string,
    algorithm: string
  ): Promise<string>;
}

results matching ""

    No results matching ""