Skip to content

Timeout issue when calling verify(token, options) #77

@brucetieu

Description

@brucetieu

Describe the Issue

We have an authorizer lambda that validates Azure AD JWT tokens using Azure’s public keys and extracts user information (name, email, roles, groups, scope) from valid tokens. Here's a snippet of the validator class we've written:

import { setConfig, verify, VerifyOptions } from 'azure-ad-verify-token';
import { JwtPayload } from 'jsonwebtoken';
import logger from '$lib/logger';

// Cache the Microsoft public key for an hour so that we don't fetch it each time we verify a JWT
setConfig({
  cacheLifetime: 60 * 60 * 1000, // 1 hour
});

type AzureConfig = {
  audience: string;
  tenantId: string;
};

type AzureJwtValidatorResult = {
  isAuthorized: boolean;
  user: string;
  roles: string;
  groups: string;
  scope: string;
};

class AzureJwtValidator {
  private readonly audience: string;
  private readonly tenantId: string;

  constructor(config: AzureConfig) {
    this.audience = config.audience;
    this.tenantId = config.tenantId;
  }

  private constructVerifyOptions(): VerifyOptions {
    return {
      jwksUri: `https://login.microsoftonline.com/${this.tenantId}/discovery/v2.0/keys`,
      issuer: `https://sts.windows.net/${this.tenantId}/`,
      audience: this.audience,
    };
  }

  private buildResult(decodedToken: string | JwtPayload): AzureJwtValidatorResult {
    return {
      isAuthorized: true,
      user: JSON.stringify({
        name: decodedToken.name,
        email: decodedToken.unique_name,
      }),
      roles: JSON.stringify(decodedToken.roles),
      groups: JSON.stringify(decodedToken.groups),
      scope: decodedToken.scp,
    };
  }

  async parseToken(authorizationHeaderValue: string): Promise<AzureJwtValidatorResult> {
    const token = authorizationHeaderValue.replace(/^Bearer\s+/, '');
    const options = this.constructVerifyOptions();

    try {
      logger.debug('Calling verify with options', JSON.stringify(options));
      const decodedToken = await verify(token, options);
      return this.buildResult(decodedToken);
    } catch (err) {
      logger.error(`Failed to verify token: ${err}`);
      return this.buildResult('');
    }
  }
}

However, with the help of debug logs, we find that calling verify(token, options) intermittently times out with the following error message:

Task timed out after 30.23 seconds

We've set the lambda time out to be longer than this, so it seems like this is not an issue related to the lambda configuration itself.

Could we rule out a network or JWKs endpoint issue? Could it be due to a token cache misconfiguration?
We are using the setConfig function to cache the Microsoft public key for 1 hour. If there is an issue with the caching mechanism (e.g., cache not being refreshed properly or invalid cache data), the verify function may hang while attempting to retrieve or validate the key.

Any feedback is greatly appreciated.

Expected behavior

Calling verify(token, options) should not intermittently time out

Steps to Reproduce

n/a

Other Information

n/a

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions