{"version":3,"sources":["../src/AccessToken.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { RoomConfiguration } from '@livekit/protocol';\nimport * as jose from 'jose';\nimport type {\n  ClaimGrants,\n  InferenceGrant,\n  ObservabilityGrant,\n  SIPGrant,\n  VideoGrant,\n} from './grants.js';\nimport { claimsToJwtPayload } from './grants.js';\n\n// 6 hours\nconst defaultTTL = `6h`;\n\nconst defaultClockToleranceSeconds = 10;\n\nexport interface AccessTokenOptions {\n  /**\n   * amount of time before expiration\n   * expressed in seconds or a string describing a time span zeit/ms.\n   * eg: '2 days', '10h', or seconds as numeric value\n   */\n  ttl?: number | string;\n\n  /**\n   * display name for the participant, available as `Participant.name`\n   */\n  name?: string;\n\n  /**\n   * identity of the user, required for room join tokens\n   */\n  identity?: string;\n\n  /**\n   * custom participant metadata\n   */\n  metadata?: string;\n\n  /**\n   * custom participant attributes\n   */\n  attributes?: Record<string, string>;\n}\n\nexport class AccessToken {\n  private apiKey: string;\n\n  private apiSecret: string;\n\n  private grants: ClaimGrants;\n\n  identity?: string;\n\n  ttl: number | string;\n\n  /**\n   * Creates a new AccessToken\n   * @param apiKey - API Key, can be set in env LIVEKIT_API_KEY\n   * @param apiSecret - Secret, can be set in env LIVEKIT_API_SECRET\n   */\n  constructor(apiKey?: string, apiSecret?: string, options?: AccessTokenOptions) {\n    if (!apiKey) {\n      apiKey = process.env.LIVEKIT_API_KEY;\n    }\n    if (!apiSecret) {\n      apiSecret = process.env.LIVEKIT_API_SECRET;\n    }\n    if (!apiKey || !apiSecret) {\n      throw Error('api-key and api-secret must be set');\n    }\n    // @ts-expect-error we're not including dom lib for the server sdk so document is not defined\n    else if (typeof document !== 'undefined') {\n      // check against document rather than window because deno provides window\n      console.error(\n        'You should not include your API secret in your web client bundle.\\n\\n' +\n          'Your web client should request a token from your backend server which should then use ' +\n          'the API secret to generate a token. See https://docs.livekit.io/client/connect/',\n      );\n    }\n    this.apiKey = apiKey;\n    this.apiSecret = apiSecret;\n    this.grants = {};\n    this.identity = options?.identity;\n    this.ttl = options?.ttl || defaultTTL;\n    if (typeof this.ttl === 'number') {\n      this.ttl = `${this.ttl}s`;\n    }\n    if (options?.metadata) {\n      this.metadata = options.metadata;\n    }\n    if (options?.attributes) {\n      this.attributes = options.attributes;\n    }\n    if (options?.name) {\n      this.name = options.name;\n    }\n  }\n\n  /**\n   * Adds a video grant to this token.\n   * @param grant -\n   */\n  addGrant(grant: VideoGrant) {\n    this.grants.video = { ...(this.grants.video ?? {}), ...grant };\n  }\n\n  /**\n   * Adds an inference grant to this token.\n   * @param grant -\n   */\n  addInferenceGrant(grant: InferenceGrant) {\n    this.grants.inference = { ...(this.grants.inference ?? {}), ...grant };\n  }\n\n  /**\n   * Adds a SIP grant to this token.\n   * @param grant -\n   */\n  addSIPGrant(grant: SIPGrant) {\n    this.grants.sip = { ...(this.grants.sip ?? {}), ...grant };\n  }\n\n  /**\n   * Adds an observability grant to this token.\n   * @param grant -\n   */\n  addObservabilityGrant(grant: ObservabilityGrant) {\n    this.grants.observability = { ...(this.grants.observability ?? {}), ...grant };\n  }\n\n  get name(): string | undefined {\n    return this.grants.name;\n  }\n\n  set name(name: string) {\n    this.grants.name = name;\n  }\n\n  get metadata(): string | undefined {\n    return this.grants.metadata;\n  }\n\n  /**\n   * Set metadata to be passed to the Participant, used only when joining the room\n   */\n  set metadata(md: string) {\n    this.grants.metadata = md;\n  }\n\n  get attributes(): Record<string, string> | undefined {\n    return this.grants.attributes;\n  }\n\n  set attributes(attrs: Record<string, string>) {\n    this.grants.attributes = attrs;\n  }\n\n  get kind(): string | undefined {\n    return this.grants.kind;\n  }\n\n  set kind(kind: string) {\n    this.grants.kind = kind;\n  }\n\n  get sha256(): string | undefined {\n    return this.grants.sha256;\n  }\n\n  set sha256(sha: string | undefined) {\n    this.grants.sha256 = sha;\n  }\n\n  get roomPreset(): string | undefined {\n    return this.grants.roomPreset;\n  }\n\n  set roomPreset(preset: string | undefined) {\n    this.grants.roomPreset = preset;\n  }\n\n  get roomConfig(): RoomConfiguration | undefined {\n    return this.grants.roomConfig;\n  }\n\n  set roomConfig(config: RoomConfiguration | undefined) {\n    this.grants.roomConfig = config;\n  }\n\n  /**\n   * @returns JWT encoded token\n   */\n  async toJwt(): Promise<string> {\n    // TODO: check for video grant validity\n\n    const secret = new TextEncoder().encode(this.apiSecret);\n\n    const jwt = new jose.SignJWT(claimsToJwtPayload(this.grants))\n      .setProtectedHeader({ alg: 'HS256' })\n      .setIssuer(this.apiKey)\n      .setExpirationTime(this.ttl)\n      .setNotBefore(new Date());\n    if (this.identity) {\n      jwt.setSubject(this.identity);\n    } else if (this.grants.video?.roomJoin) {\n      throw Error('identity is required for join but not set');\n    }\n    return jwt.sign(secret);\n  }\n}\n\nexport class TokenVerifier {\n  private apiKey: string;\n\n  private apiSecret: string;\n\n  constructor(apiKey: string, apiSecret: string) {\n    this.apiKey = apiKey;\n    this.apiSecret = apiSecret;\n  }\n\n  async verify(\n    token: string,\n    clockTolerance: string | number = defaultClockToleranceSeconds,\n  ): Promise<ClaimGrants> {\n    const secret = new TextEncoder().encode(this.apiSecret);\n    const { payload } = await jose.jwtVerify(token, secret, {\n      issuer: this.apiKey,\n      clockTolerance,\n    });\n    if (!payload) {\n      throw Error('invalid token');\n    }\n\n    return payload as ClaimGrants;\n  }\n}\n"],"mappings":"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","names":[]}