@artifact-project/webauthn

WebAuthn — A set of tools for building an API and interacts with

Usage no npm install needed!

<script type="module">
  import artifactProjectWebauthn from 'https://cdn.skypack.dev/@artifact-project/webauthn';
</script>

README

@artifact-project/webauthn 🔐

A set of tools for building an API and interacts with WebAuthn.

npm i --save @artifact-project/webauthn

Features

  • Easy and Flexibility API 🧬
  • Supported IFrames (regardless of nesting) 💪🏻
  • Runtime logger & verbose mode ✴️
  • Fully testelably ✅

Using in iframe

In parent window
import { allowFrom } from '@artifact-project/webauthn/allow';
allowFrom(['mail.ru', '{o2,account}.mail.ru']);
Or embed the code in the parent window
<html>
  <head>
    <script>
      /* Replace this comment on the code from this file: ./node_modules/@artifact-project/webauthn/allow.js */
      webauthn.allowFrom(['mail.ru', '{o2,account}.mail.ru']);
    </script>
  </head>
  <body>...</body>
</html>
Inside iframe
import { allowFor } from '@artifact-project/webauthn';
allowFor(['mail.ru', '*.mail.ru']);

Credential Create Request (aka Registration)

import {
    credentials,
    createMultiPhaseRequest,
    fetchJSON,
    parseAsCredentialCreationOptionsAndExtra,
    encodeAttestationResponsePayload,
} from '@artifact-project/webauthn';

const credentialCreateRequest = createMultiPhaseRequest<{login: params}>()
    .phase((params) => fetchJSON('/api/v1/webauthn/credentials/create', params)
        .then(res => res.body)
        .then(parseAsCredentialCreationOptionsAndExtra)
    )
    .phase(({options, extra}) => credentials.create(options).then(credential => ({
        extra,
        options,
        credential,
    })))
    .phase(
        ({extra, credential, options}) => fetchJSON('/api/v1/webauthn/credentials/create/confirm', {
            ...extra,
            attestation: encodeAttestationResponsePayload(credential),
        }).then(res => ({
            extra: res.body,
            options,
            credential,
        }))
    )
;

credentialCreateRequest({
    login: 'ibn@rubaxa.org',
}).then(console.log);
// {
//   extra: {id: "...", login: "ibn@rubaxa.org"},
//   options: {...},
//   credential: {...},
// }

Credential Request (aka Login)

import {
    credentials,
    createMultiPhaseRequest,
    fetchJSON,
    parseAsCredentialRequestOptionsAndExtra,
    encodeAssertionResponsePlayload,
} from '@artifact-project/webauthn';

const credentialRequest = createMultiPhaseRequest<{login: params}>()
    .phase((params) => fetchJSON('/api/v1/webauthn/credentials/get', params)
        .then(res => res.body)
        .then(parseAsCredentialRequestOptionsAndExtra)
    )
    .phase(({options, extra}) => credentials.get(options).then(credential => ({
        extra,
        options,
        credential,
    })))
    .phase(
        ({extra, credential, options}) => fetchJSON('/api/v1/webauthn/credentials/get/confirm', {
            ...extra,
            assertion: encodeAssertionResponsePlayload(credential),
        }).then(res => ({
            extra: res.body,
            options,
            credential,
        }))
    )
;

credentialRequest({
    login: 'ibn@rubaxa.org',
}).then(console.log);
// {
//   extra: {token: "...", url: "...", expires: 123},
//   options: {...},
//   credential: {...},
// }

API

  • isCredentialsSupported(): boolean
  • getLogEntries(): Array<{msg: string; detail: object;}>
  • credentials
    • create(options?: CredentialCreationOptions): Promise<Credential | null>
    • get(options?: CredentialRequestOptions): Promise<Credential | null>
  • createPhaseRequest<P extends object>(): (params: P) => Promise<R>
  • fetchJSON(url: string, params: object): Response
  • Decode
    • decodeBuffer(value: string): ArrayBuffer
    • decodePublicKeyCredentialCreationOptions(value: object): PublicKeyCredentialCreationOptions
    • decodePublicKeyCredentialRequestOptions(value: object): PublicKeyCredentialRequestOptions
    • decodeCredentialCreationOptions(value: object): CredentialCreationOptions
    • decodeCredentialRequestOptions(value: object): CredentialRequestOptions
    • decodeAttestationResponsePayload(credential: object): PublicKeyCredentialWithAttestationResponse
    • decodeAssertionResponsePlayload(credential: object): PublicKeyCredentialWithAssertionResponse
  • Encode
    • encodeBuffer(buffer: ArrayBuffer): string
    • encodeAttestationResponsePayload(credential: PublicKeyCredential): EncodedPublicKeyCredential
    • encodeAssertionResponsePlayload(credential: PublicKeyCredential): EncodedPublicKeyCredential

Development