{"version":3,"file":"passwordless.min.mjs","sources":["../../src/passwordless.ts"],"sourcesContent":["import {\n  AtLeast,\n  PromiseResult,\n  RegisterBeginResponse,\n  SigninBeginResponse,\n  SigninMethod,\n  StepupRequest,\n  TokenResponse\n} from './types';\n\nexport * from './types';\n\nexport interface Config {\n  apiUrl: string;\n  apiKey: string;\n  origin: string;\n  rpid: string;\n}\n\nexport class Client {\n  private config: Config = {\n    apiUrl: 'https://v4.passwordless.dev',\n    apiKey: '',\n    origin: window.location.origin,\n    rpid: window.location.hostname\n  };\n\n  private _clientVersion: string = 'js-1.1.0';\n\n  private abortController: AbortController = new AbortController();\n\n  constructor(config: AtLeast<Config, 'apiKey'>) {\n    Object.assign(this.config, config);\n  }\n\n  /**\n   * Register a new credential to a user\n   *\n   * @param {string} token Token generated by your backend and the Passwordless API\n   * @param {string} credentialNickname A nickname for the passkey credential being created\n   */\n  public async register(token: string, credentialNickname?: string): PromiseResult<TokenResponse> {\n    try {\n      this.assertBrowserSupported();\n\n      const registration = await this.registerBegin(token);\n      if (registration.error) {\n        console.error(registration.error);\n        return { error: registration.error };\n      }\n\n      registration.data.challenge = base64UrlToArrayBuffer(registration.data.challenge);\n      registration.data.user.id = base64UrlToArrayBuffer(registration.data.user.id);\n      registration.data.excludeCredentials?.forEach((cred) => {\n        cred.id = base64UrlToArrayBuffer(cred.id);\n      });\n\n      const credential = (await navigator.credentials.create({\n        publicKey: registration.data\n      })) as PublicKeyCredential;\n\n      if (!credential) {\n        const error = {\n          from: 'client',\n          errorCode: 'failed_create_credential',\n          title: 'Failed to create credential (navigator.credentials.create returned null)'\n        };\n        console.error(error);\n        return { error };\n      }\n\n      return await this.registerComplete(credential, registration.session, credentialNickname);\n\n      // next steps\n      // return a token from the API\n      // Add a type to the token (method/action)\n    } catch (caughtError: any) {\n      const errorMessage = getErrorMessage(caughtError);\n      const error = {\n        from: 'client',\n        errorCode: 'unknown',\n        title: errorMessage\n      };\n      console.error(caughtError);\n      console.error(error);\n\n      return { error };\n    }\n  }\n\n  /**\n   * Sign in a user using the userid\n   * @param {string} userId\n   * @returns\n   */\n  public async signinWithId(userId: string): PromiseResult<TokenResponse> {\n    return this.signin({ userId });\n  }\n\n  /**\n   * Sign in a user using an alias\n   * @param {string} alias\n   * @returns a verify_token\n   */\n  public async signinWithAlias(alias: string): PromiseResult<TokenResponse> {\n    return this.signin({ alias });\n  }\n\n  /**\n   * Sign in a user using autofill UI (a.k.a conditional) sign in\n   * @returns a verify_token\n   */\n  public async signinWithAutofill(): PromiseResult<TokenResponse> {\n    if (!(await isAutofillSupported())) {\n      throw new Error(\n        'Autofill authentication (conditional meditation) is not supported in this browser'\n      );\n    }\n    return this.signin({ autofill: true });\n  }\n\n  /**\n   * Sign in a user using discoverable credentials\n   * @returns a verify_token\n   */\n  public async signinWithDiscoverable(): PromiseResult<TokenResponse> {\n    return this.signin({ discoverable: true });\n  }\n\n  public abort() {\n    if (this.abortController) {\n      this.abortController.abort();\n    }\n  }\n\n  public isPlatformSupported(): Promise<boolean> {\n    return isPlatformSupported();\n  }\n\n  public isBrowserSupported(): boolean {\n    return isBrowserSupported();\n  }\n\n  public isAutofillSupported(): Promise<boolean> {\n    return isAutofillSupported();\n  }\n\n  private async registerBegin(token: string): PromiseResult<RegisterBeginResponse> {\n    const response = await fetch(`${this.config.apiUrl}/register/begin`, {\n      method: 'POST',\n      headers: this.createHeaders(),\n      body: JSON.stringify({\n        token,\n        RPID: this.config.rpid,\n        Origin: this.config.origin\n      })\n    });\n\n    const res = await response.json();\n    if (response.ok) {\n      return res;\n    }\n\n    return { error: { ...res, from: 'server' } };\n  }\n\n  private async registerComplete(\n    credential: PublicKeyCredential,\n    session: string,\n    credentialNickname?: string\n  ): PromiseResult<TokenResponse> {\n    const attestationResponse = credential.response as AuthenticatorAttestationResponse;\n\n    const response = await fetch(`${this.config.apiUrl}/register/complete`, {\n      method: 'POST',\n      headers: this.createHeaders(),\n      body: JSON.stringify({\n        session: session,\n        response: {\n          id: credential.id,\n          rawId: arrayBufferToBase64Url(credential.rawId),\n          type: credential.type,\n          clientExtensionResults: credential.getClientExtensionResults(),\n          response: {\n            AttestationObject: arrayBufferToBase64Url(attestationResponse.attestationObject),\n            clientDataJson: arrayBufferToBase64Url(attestationResponse.clientDataJSON)\n          }\n        },\n        nickname: credentialNickname,\n        RPID: this.config.rpid,\n        Origin: this.config.origin\n      })\n    });\n\n    const res = await response.json();\n    if (response.ok) {\n      return res;\n    }\n\n    return { error: { ...res, from: 'server' } };\n  }\n\n  /**\n   * Sign in a user\n   *\n   * @param {SigninMethod} Object containing either UserID or Alias\n   * @returns\n   */\n  private async signin(signinMethod: SigninMethod): PromiseResult<TokenResponse> {\n    try {\n      this.assertBrowserSupported();\n      this.handleAbort();\n\n      // if signinMethod is undefined, set it to an empty object\n      // this will cause a login using discoverable credentials\n      if (!signinMethod) {\n        signinMethod = { discoverable: true };\n      }\n\n      const signin = await this.signinBegin(signinMethod);\n      if (signin.error) {\n        return signin;\n      }\n\n      const credential = (await navigator.credentials.get({\n        publicKey: signin.data,\n        mediation:\n          'autofill' in signinMethod\n            ? ('conditional' as CredentialMediationRequirement)\n            : undefined, // Typescript doesn't know about 'conditational' yet\n        signal: this.abortController.signal\n      })) as PublicKeyCredential;\n\n      const response = await this.signinComplete(credential, signin.session);\n      return response;\n    } catch (caughtError: any) {\n      const errorMessage = getErrorMessage(caughtError);\n      const error = {\n        from: 'client',\n        errorCode: 'unknown',\n        title: errorMessage\n      };\n      console.error(caughtError);\n      console.error(error);\n\n      return { error };\n    }\n  }\n\n  /**\n   * Performs a step-up authentication process. This is essentially an overload for the sign-in workflow. It allows for\n   * a user authentication to be given a purpose or context for the sign-in, enabling a \"step-up\" authentication flow.\n   *\n   * @param {StepupRequest} stepup - The step-up request object. This includes the sign-in method and the purpose of the authentication\n   *\n   * @returns {token} - The result of the step-up sign-in process.\n   */\n  public async stepup(stepup: StepupRequest): PromiseResult<TokenResponse> {\n    try {\n      this.assertBrowserSupported();\n      this.handleAbort();\n\n      if (!stepup.signinMethod) {\n        throw new Error('You need to provide the signinMethod');\n      }\n\n      if (!stepup.purpose) {\n        stepup.purpose = 'step-up';\n      }\n\n      const signin = await this.signinBegin(stepup.signinMethod, stepup.purpose);\n\n      if (signin.error) {\n        return signin;\n      }\n\n      const credential = (await navigator.credentials.get({\n        publicKey: signin.data,\n        mediation:\n          'autofill' in stepup.signinMethod\n            ? ('conditional' as CredentialMediationRequirement)\n            : undefined, // Typescript doesn't know about 'conditional' yet\n        signal: this.abortController.signal\n      })) as PublicKeyCredential;\n\n      return await this.signinComplete(credential, signin.session);\n    } catch (caughtError: any) {\n      const errorMessage = getErrorMessage(caughtError);\n      const error = {\n        from: 'client',\n        errorCode: 'unknown',\n        title: errorMessage\n      };\n      console.error(caughtError);\n      console.error(error);\n\n      return { error };\n    }\n  }\n\n  private async signinBegin(\n    signinMethod: SigninMethod,\n    purpose?: string\n  ): PromiseResult<SigninBeginResponse> {\n    const response = await fetch(`${this.config.apiUrl}/signin/begin`, {\n      method: 'POST',\n      headers: this.createHeaders(),\n      body: JSON.stringify({\n        userId: 'userId' in signinMethod ? signinMethod.userId : undefined,\n        alias: 'alias' in signinMethod ? signinMethod.alias : undefined,\n        RPID: this.config.rpid,\n        Origin: this.config.origin,\n        purpose: purpose\n      })\n    });\n\n    const res = await response.json();\n    if (response.ok) {\n      return {\n        ...res,\n        data: {\n          ...res.data,\n          challenge: base64UrlToArrayBuffer(res.data.challenge),\n          allowCredentials: res.data.allowCredentials?.map(\n            (cred: PublicKeyCredentialDescriptor) => {\n              return { ...cred, id: base64UrlToArrayBuffer(cred.id) };\n            }\n          )\n        }\n      };\n    }\n\n    return { error: { ...res, from: 'server' } };\n  }\n\n  private async signinComplete(\n    credential: PublicKeyCredential,\n    session: string\n  ): PromiseResult<TokenResponse> {\n    const assertionResponse = credential.response as AuthenticatorAssertionResponse;\n\n    const response = await fetch(`${this.config.apiUrl}/signin/complete`, {\n      method: 'POST',\n      headers: this.createHeaders(),\n      body: JSON.stringify({\n        session: session,\n        response: {\n          id: credential.id,\n          rawId: arrayBufferToBase64Url(new Uint8Array(credential.rawId)),\n          type: credential.type,\n          clientExtensionResults: credential.getClientExtensionResults(),\n          response: {\n            authenticatorData: arrayBufferToBase64Url(assertionResponse.authenticatorData),\n            clientDataJson: arrayBufferToBase64Url(assertionResponse.clientDataJSON),\n            signature: arrayBufferToBase64Url(assertionResponse.signature)\n          }\n        },\n        RPID: this.config.rpid,\n        Origin: this.config.origin\n      })\n    });\n\n    const res = await response.json();\n    if (response.ok) {\n      return res;\n    }\n\n    return { error: { ...res, from: 'server' } };\n  }\n\n  private handleAbort() {\n    this.abort();\n    this.abortController = new AbortController();\n  }\n\n  private assertBrowserSupported(): void {\n    if (!isBrowserSupported()) {\n      throw new Error('WebAuthn and PublicKeyCredentials are not supported on this browser/device');\n    }\n  }\n\n  private createHeaders(): Record<string, string> {\n    return {\n      'ApiKey': this.config.apiKey,\n      'Content-Type': 'application/json',\n      'Client-Version': this._clientVersion\n    };\n  }\n\n  public get clientVersionRegex(): RegExp {\n    return /^[a-z]+-\\d+\\.\\d+\\.\\d+$/;\n  }\n\n  /**\n   * (Internal use only) Sets the `Client-Version` header for client SDK implementations based off the Javascript Client SDK. By setting the\n   * property, the parameter will be prepended.\n   * @param {string} value The new `Client-Version` header value.\n   * @throws {Error} Throws an error if the `Client-Version` has already been set.\n   * @throws {Error} Throws an error if the `Client-Version` format is invalid. Expected format is 'prefix-x.x.x' where prefix is a lowercase string.\n   * @remarks Do not set this property when integrating the client SDK.\n   */\n  public set clientVersion(value: string) {\n    if (!this.clientVersionRegex.test(this.clientVersion)) {\n      throw new Error('`Client-Version` has already been set.');\n    }\n    if (!this.clientVersionRegex.test(value)) {\n      throw new Error(\n        \"Invalid `Client-Version` format. Expected format is 'prefix-x.x.x' where prefix is a lowercase string.\"\n      );\n    }\n    this._clientVersion = `${value}+${this.clientVersion}`;\n  }\n\n  /**\n   * Gets the `Client-Version` header for client SDK implementations based off the Javascript Client SDK.\n   */\n  public get clientVersion(): string {\n    return this._clientVersion;\n  }\n}\n\nexport async function isPlatformSupported(): Promise<boolean> {\n  if (!isBrowserSupported()) return false;\n  return PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();\n}\n\nexport function isBrowserSupported(): boolean {\n  return (\n    window.PublicKeyCredential !== undefined && typeof window.PublicKeyCredential === 'function'\n  );\n}\n\nexport async function isAutofillSupported(): Promise<boolean> {\n  const PublicKeyCredential = window.PublicKeyCredential as any; // Typescript lacks support for this\n  if (!PublicKeyCredential.isConditionalMediationAvailable) return false;\n  return PublicKeyCredential.isConditionalMediationAvailable() as Promise<boolean>;\n}\n\nfunction base64ToBase64Url(base64: string): string {\n  return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=*$/g, '');\n}\n\nfunction base64UrlToBase64(base64Url: string): string {\n  return base64Url.replace(/-/g, '+').replace(/_/g, '/');\n}\n\nfunction base64UrlToArrayBuffer(base64UrlString: string | BufferSource): Uint8Array<ArrayBuffer> {\n  // improvement: Remove BufferSource-type and add proper types upstream\n  if (typeof base64UrlString !== 'string') {\n    const msg = 'Cannot convert from Base64Url to ArrayBuffer: Input was not of type string';\n    console.error(msg, base64UrlString);\n    throw new TypeError(msg);\n  }\n\n  const base64Unpadded = base64UrlToBase64(base64UrlString);\n  const paddingNeeded = (4 - (base64Unpadded.length % 4)) % 4;\n  const base64Padded = base64Unpadded.padEnd(base64Unpadded.length + paddingNeeded, '=');\n\n  const binary = window.atob(base64Padded);\n  const bytes = new Uint8Array(binary.length);\n  for (let i = 0; i < binary.length; i++) {\n    bytes[i] = binary.charCodeAt(i);\n  }\n\n  return bytes;\n}\n\nfunction arrayBufferToBase64Url(buffer: ArrayBuffer | Uint8Array): string {\n  const uint8Array = (() => {\n    if (Array.isArray(buffer)) return Uint8Array.from(buffer);\n    if (buffer instanceof ArrayBuffer) return new Uint8Array(buffer);\n    if (buffer instanceof Uint8Array) return buffer;\n\n    const msg =\n      'Cannot convert from ArrayBuffer to Base64Url. Input was not of type ArrayBuffer, Uint8Array or Array';\n    console.error(msg, buffer);\n    throw new Error(msg);\n  })();\n\n  let string = '';\n  for (let i = 0; i < uint8Array.byteLength; i++) {\n    string += String.fromCharCode(uint8Array[i]);\n  }\n\n  const base64String = window.btoa(string);\n  return base64ToBase64Url(base64String);\n}\n\ntype ErrorWithMessage = {\n  message: string;\n};\n\nfunction isErrorWithMessage(error: unknown): error is ErrorWithMessage {\n  return (\n    typeof error === 'object' &&\n    error !== null &&\n    'message' in error &&\n    typeof (error as Record<string, unknown>).message === 'string'\n  );\n}\n\nfunction toErrorWithMessage(maybeError: unknown): ErrorWithMessage {\n  if (isErrorWithMessage(maybeError)) return maybeError;\n\n  try {\n    return new Error(JSON.stringify(maybeError));\n  } catch {\n    // fallback in case there's an error stringifying the maybeError\n    // like with circular references for example.\n    return new Error(String(maybeError));\n  }\n}\n\nfunction getErrorMessage(error: unknown) {\n  return toErrorWithMessage(error).message;\n}\n"],"names":["Client","constructor","config","this","apiUrl","apiKey","origin","window","location","rpid","hostname","_clientVersion","abortController","AbortController","Object","assign","register","token","credentialNickname","assertBrowserSupported","registration","registerBegin","error","console","data","challenge","base64UrlToArrayBuffer","user","id","_a","excludeCredentials","forEach","cred","credential","navigator","credentials","create","publicKey","from","errorCode","title","registerComplete","session","caughtError","getErrorMessage","signinWithId","userId","signin","signinWithAlias","alias","signinWithAutofill","isAutofillSupported","Error","autofill","signinWithDiscoverable","discoverable","abort","isPlatformSupported","isBrowserSupported","response","fetch","method","headers","createHeaders","body","JSON","stringify","RPID","Origin","res","json","ok","attestationResponse","rawId","arrayBufferToBase64Url","type","clientExtensionResults","getClientExtensionResults","AttestationObject","attestationObject","clientDataJson","clientDataJSON","nickname","signinMethod","handleAbort","signinBegin","get","mediation","undefined","signal","signinComplete","stepup","purpose","allowCredentials","map","assertionResponse","Uint8Array","authenticatorData","signature","ApiKey","clientVersionRegex","clientVersion","value","test","async","PublicKeyCredential","isUserVerifyingPlatformAuthenticatorAvailable","isConditionalMediationAvailable","base64UrlString","msg","TypeError","base64Unpadded","replace","paddingNeeded","length","base64Padded","padEnd","binary","atob","bytes","i","charCodeAt","buffer","uint8Array","Array","isArray","ArrayBuffer","string","byteLength","String","fromCharCode","base64String","btoa","maybeError","message","toErrorWithMessage"],"mappings":"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"}