# TODO - save *array* of user_credentials, instead of one - also, save algorithm & authenticator attachment - `cose["3"]` (cbor.decode) contains the public key algorithm - fix loading of saved user_credentials # NOTES - `cose["3"]` (cbor.decode) contains the public key algorithm - Firefox-android seems to respect the long-hold-refresh to force reload - `AuthenticatorAttestationResponse` == *create* - `AuthenticatorAssertionResponse` == *get* https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API/Attestation_and_Assertion https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API/Attestation_and_Assertion https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Permissions-Policy/publickey-credentials-create https://w3c.github.io/webauthn/ ## registration *has* a signature, *somewhere* https://developer.mozilla.org/en-US/docs/Web/API/AuthenticatorAttestationResponse https://developer.mozilla.org/en-US/docs/Web/API/CredentialsContainer/create#challenge `challenge` > This value will be signed by the authenticator and the signature will be sent back as part of `AuthenticatorAttestationResponse.attestationObject`. https://developer.mozilla.org/en-US/docs/Web/API/AuthenticatorAttestationResponse/attestationObject `authData` > in `AuthenticatorAttestationResponse`, the `authenticatorData` is a property in a *CBOR* map. ... https://developer.mozilla.org/en-US/docs/Web/API/AuthenticatorAttestationResponse/getAuthenticatorData https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API/Authenticator_data - `PublicKeyCredential.response.authenticatorData` *property* - `navigator.credentials.create()` - `PublicKeyCredential.response.getAuthenticatorData()` *method* - `navigator.credentials.get()` ... where is the *signature* ??? https://developer.mozilla.org/en-US/docs/Web/API/AuthenticatorAttestationResponse https://developer.mozilla.org/en-US/docs/Web/API/CredentialsContainer/create#challenge https://developer.mozilla.org/en-US/docs/Web/API/AuthenticatorAttestationResponse/attestationObject https://developer.mozilla.org/en-US/docs/Web/API/AuthenticatorAttestationResponse/getAuthenticatorData https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API/Authenticator_data https://developer.mozilla.org/en-US/docs/Web/API/AuthenticatorAssertionResponse # overview ```pseudo server = Server; async on_register( username ) { { challenge } = await server.pre_register( username ); credential = await navigator.credentials.create( username, challenge ); username = await server.register( username, [challenge,] credential ); } async on_authenticate( username ) { { challenge, credential_ids } = await server.pre_authenticate( username ); credential = await navigator.credentials.get( username, challenge, credential_ids ); jwt = await server.authenticate( username, [challenge,] credential ); } ``` # adding typescript for jsdoc typechecking ## install - `npm install --save-dev typescript` ## command line args / usage - `npx tsc --help` - `npx tsc -p ./tsconfig.json` - `npx tsc --pretty --watch` ## references - https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html - https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html - https://www.typescriptlang.org/docs/handbook/tsconfig-json.html ### tsconfig https://www.typescriptlang.org/tsconfig `--showConfig` `npx tsc ... --showConfig > tsconfig.json` `npx tsc --lib esnext,dom --allowJs --checkJs --noEmit --strict *.js --showConfig > tsconfig.json` `--lib esnext,dom --allowJs --checkJs --noEmit --strict *.js` `tsconfig.json` `tsconfig.json` ~ `jsconfig.json` `jsconfig.json` is not automatically found by *tsc* so renamed to `tsconfig.json` for convenience. ### useUnknownInCatchVariables `any` vs `unknown` ? ## DefinitelyTyped / @types https://definitelytyped.github.io/ https://github.com/DefinitelyTyped/DefinitelyTyped XXX [ TypeSearch ](https://microsoft.github.io/TypeSearch/) ### AuthenticatorResponse ( how the hell this came from PowerBI, i have no idea, but i'm glad to find it ) https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules_typedoc_node_modules_typescript_lib_lib_dom_d_.authenticatorresponse.html https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules_typedoc_node_modules_typescript_lib_lib_dom_d_.authenticatorassertionresponse.html https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules_typedoc_node_modules_typescript_lib_lib_dom_d_.authenticatorattestationresponse.html - AuthenticatorResponse - AuthenticatorAttestationResponse ( create, register ) - AuthenticatorAssertionResponse ( get, login ) `@types/webappsec-credential-management` - https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/webappsec-credential-management/index.d.ts - https://www.npmjs.com/package/@types/webappsec-credential-management `npm install --save-dev @types/webappsec-credential-management` https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/webappsec-credential-management/index.d.ts - `get(options?: CredentialRequestOptions): Promise;` - `create(options: CredentialCreationOptions): Promise;` .. - `type CredentialType = PasswordCredential | FederatedCredential | PublicKeyCredential;` .. https://www.w3.org/TR/credential-management-1/#credential https://w3c.github.io/webauthn/#publickeycredential https://w3c.github.io/webauthn/#authenticatorresponse https://w3c.github.io/webauthn/#authenticatorattestationresponse https://w3c.github.io/webauthn/#iface-authenticatorassertionresponse ```ts interface Credential { readonly id: string; readonly type: string; } interface PublicKeyCredential extends Credential { readonly type: "public-key"; readonly rawId: ArrayBuffer; readonly response: AuthenticatorResponse; } interface AuthenticatorResponse { readonly clientDataJSON: ArrayBuffer; } interface AuthenticatorAttestationResponse extends AuthenticatorResponse { readonly attestationObject: ArrayBuffer; } interface AuthenticatorAssertionResponse extends AuthenticatorResponse { readonly authenticatorData: ArrayBuffer; readonly signature: ArrayBuffer; readonly userHandle: ArrayBuffer | null; } ```