From fb910c161728423808d97459cf49ed19662302ed Mon Sep 17 00:00:00 2001 From: Kyle Peacock Date: Thu, 14 Mar 2024 10:36:37 -0700 Subject: [PATCH 1/6] feat!: support for restricting II auth methods --- packages/auth-client/src/index.ts | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/auth-client/src/index.ts b/packages/auth-client/src/index.ts index 72e1d541..b915e145 100644 --- a/packages/auth-client/src/index.ts +++ b/packages/auth-client/src/index.ts @@ -96,6 +96,10 @@ export interface AuthClientLoginOptions { * @default BigInt(8) hours * BigInt(3_600_000_000_000) nanoseconds */ maxTimeToLive?: bigint; + /** + * If present, indicates whether or not the Identity Provider should allow the user to authenticate and/or register using a temporary key/PIN identity. Authenticating dapps may want to prevent users from using Temporary keys/PIN identities because Temporary keys/PIN identities are less secure than Passkeys (webauthn credentials) and because Temporary keys/PIN identities generally only live in a browser database (which may get cleared by the browser/OS). + */ + allowPinAuthentication?: boolean; /** * Origin for Identity Provider to use while generating the delegated identity. For II, the derivation origin must authorize this origin by setting a record at `/.well-known/ii-alternative-origins`. * @see https://github.com/dfinity/internet-identity/blob/main/docs/internet-identity-spec.adoc @@ -120,6 +124,7 @@ interface InternetIdentityAuthRequest { kind: 'authorize-client'; sessionPublicKey: Uint8Array; maxTimeToLive?: bigint; + allowPinAuthentication?: boolean; derivationOrigin?: string; } @@ -134,6 +139,7 @@ interface InternetIdentityAuthResponseSuccess { signature: Uint8Array; }[]; userPublicKey: Uint8Array; + authnMethod: 'passkey' | 'pin' | 'recovery'; } interface AuthReadyMessage { @@ -151,6 +157,7 @@ interface AuthResponseSuccess { signature: Uint8Array; }[]; userPublicKey: Uint8Array; + authnMethod: 'passkey' | 'pin' | 'recovery'; } interface AuthResponseFailure { @@ -355,7 +362,7 @@ export class AuthClient { private async _handleSuccess( message: InternetIdentityAuthResponseSuccess, - onSuccess?: () => void, + onSuccess?: (message?: InternetIdentityAuthResponseSuccess) => void, ) { const delegations = message.delegations.map(signedDelegation => { return { @@ -404,7 +411,7 @@ export class AuthClient { // onSuccess should be the last thing to do to avoid consumers // interfering by navigating or refreshing the page - onSuccess?.(); + onSuccess?.(message); } public getIdentity(): Identity { @@ -421,6 +428,7 @@ export class AuthClient { * @param {AuthClientLoginOptions} options - Options for logging in * @param options.identityProvider Identity provider * @param options.maxTimeToLive Expiration of the authentication in nanoseconds + * @param options.allowPinAuthentication If present, indicates whether or not the Identity Provider should allow the user to authenticate and/or register using a temporary key/PIN identity. Authenticating dapps may want to prevent users from using Temporary keys/PIN identities because Temporary keys/PIN identities are less secure than Passkeys (webauthn credentials) and because Temporary keys/PIN identities generally only live in a browser database (which may get cleared by the browser/OS). * @param options.derivationOrigin Origin for Identity Provider to use while generating the delegated identity * @param options.windowOpenerFeatures Configures the opened authentication window * @param options.onSuccess Callback once login has completed @@ -450,6 +458,10 @@ export class AuthClient { * @default BigInt(8) hours * BigInt(3_600_000_000_000) nanoseconds */ maxTimeToLive?: bigint; + /** + * If present, indicates whether or not the Identity Provider should allow the user to authenticate and/or register using a temporary key/PIN identity. Authenticating dapps may want to prevent users from using Temporary keys/PIN identities because Temporary keys/PIN identities are less secure than Passkeys (webauthn credentials) and because Temporary keys/PIN identities generally only live in a browser database (which may get cleared by the browser/OS). + */ + allowPinAuthentication?: boolean; /** * Auth Window feature config string * @example "toolbar=0,location=0,menubar=0,width=500,height=500,left=100,top=100" @@ -463,7 +475,9 @@ export class AuthClient { /** * Callback once login has completed */ - onSuccess?: (() => void) | (() => Promise); + onSuccess?: + | ((message?: InternetIdentityAuthResponseSuccess) => void) + | ((message?: InternetIdentityAuthResponseSuccess) => Promise); /** * Callback in case authentication fails */ @@ -528,6 +542,7 @@ export class AuthClient { kind: 'authorize-client', sessionPublicKey: new Uint8Array(this._key?.getPublicKey().toDer() as ArrayBuffer), maxTimeToLive: options?.maxTimeToLive, + allowPinAuthentication: options?.allowPinAuthentication, derivationOrigin: options?.derivationOrigin?.toString(), }; this._idpWindow?.postMessage(request, identityProviderUrl.origin); From ea75e57ed75d1e8197c6b8293cf210d052be41ab Mon Sep 17 00:00:00 2001 From: Kyle Peacock Date: Thu, 14 Mar 2024 10:38:22 -0700 Subject: [PATCH 2/6] changelog --- docs/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index ac9e990a..d37fbc6e 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -2,6 +2,13 @@ ## [Unreleased] +### Changed + +* feat!: support for restricting II auth methods + * New login option: `allowPinAuthentication?: boolean;` + * Response from II includes `authnMethod: 'passkey' | 'pin' | 'recovery';` + * OnSuccess now optionally passes the message directly from the IDP provider + ### Added * feat: adds `fromPem` method for `identity-secp256k1` From 67f817339f57834136bfeb54199079b6c93f53df Mon Sep 17 00:00:00 2001 From: Kyle Peacock Date: Thu, 14 Mar 2024 11:08:07 -0700 Subject: [PATCH 3/6] backwards-compatible onsuccess interface --- packages/auth-client/src/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/auth-client/src/index.ts b/packages/auth-client/src/index.ts index b915e145..7844e57c 100644 --- a/packages/auth-client/src/index.ts +++ b/packages/auth-client/src/index.ts @@ -476,7 +476,9 @@ export class AuthClient { * Callback once login has completed */ onSuccess?: + | (() => void) | ((message?: InternetIdentityAuthResponseSuccess) => void) + | (() => Promise) | ((message?: InternetIdentityAuthResponseSuccess) => Promise); /** * Callback in case authentication fails From 55dc427036c2635d5ab2a6112391577e4ae65335 Mon Sep 17 00:00:00 2001 From: Kai Peacock Date: Thu, 14 Mar 2024 16:04:19 -0700 Subject: [PATCH 4/6] Update packages/auth-client/src/index.ts --- packages/auth-client/src/index.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/auth-client/src/index.ts b/packages/auth-client/src/index.ts index 7844e57c..a41440e3 100644 --- a/packages/auth-client/src/index.ts +++ b/packages/auth-client/src/index.ts @@ -476,10 +476,8 @@ export class AuthClient { * Callback once login has completed */ onSuccess?: - | (() => void) - | ((message?: InternetIdentityAuthResponseSuccess) => void) - | (() => Promise) - | ((message?: InternetIdentityAuthResponseSuccess) => Promise); + | (() => void | Promise) + | (message: IIAuthResponse) => void | Promise); /** * Callback in case authentication fails */ From c902d7b2ab734523edcd47888d10078bc151f4d0 Mon Sep 17 00:00:00 2001 From: Kyle Peacock Date: Thu, 14 Mar 2024 16:25:17 -0700 Subject: [PATCH 5/6] de-duplicates login options for simplicity, adds customValues to AuthClientLoginOptions to pass to IDP --- packages/auth-client/src/index.ts | 57 +++++++++---------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/packages/auth-client/src/index.ts b/packages/auth-client/src/index.ts index a41440e3..900d96ac 100644 --- a/packages/auth-client/src/index.ts +++ b/packages/auth-client/src/index.ts @@ -85,6 +85,12 @@ export interface IdleOptions extends IdleManagerOptions { export * from './idleManager'; +export type OnSuccessFunc = + | (() => void | Promise) + | ((message: InternetIdentityAuthResponseSuccess) => void | Promise); + +export type OnErrorFunc = (error?: string) => void | Promise; + export interface AuthClientLoginOptions { /** * Identity provider @@ -113,11 +119,15 @@ export interface AuthClientLoginOptions { /** * Callback once login has completed */ - onSuccess?: (() => void) | (() => Promise); + onSuccess?: OnSuccessFunc; /** * Callback in case authentication fails */ - onError?: ((error?: string) => void) | ((error?: string) => Promise); + onError?: OnErrorFunc; + /** + * Extra values to be passed in the login request during the authorize-ready phase + */ + customValues?: Record; } interface InternetIdentityAuthRequest { @@ -128,7 +138,7 @@ interface InternetIdentityAuthRequest { derivationOrigin?: string; } -interface InternetIdentityAuthResponseSuccess { +export interface InternetIdentityAuthResponseSuccess { kind: 'authorize-client-success'; delegations: { delegation: { @@ -362,7 +372,7 @@ export class AuthClient { private async _handleSuccess( message: InternetIdentityAuthResponseSuccess, - onSuccess?: (message?: InternetIdentityAuthResponseSuccess) => void, + onSuccess?: OnSuccessFunc, ) { const delegations = message.delegations.map(signedDelegation => { return { @@ -447,42 +457,7 @@ export class AuthClient { * } * }); */ - public async login(options?: { - /** - * Identity provider - * @default "https://identity.ic0.app" - */ - identityProvider?: string | URL; - /** - * Expiration of the authentication in nanoseconds - * @default BigInt(8) hours * BigInt(3_600_000_000_000) nanoseconds - */ - maxTimeToLive?: bigint; - /** - * If present, indicates whether or not the Identity Provider should allow the user to authenticate and/or register using a temporary key/PIN identity. Authenticating dapps may want to prevent users from using Temporary keys/PIN identities because Temporary keys/PIN identities are less secure than Passkeys (webauthn credentials) and because Temporary keys/PIN identities generally only live in a browser database (which may get cleared by the browser/OS). - */ - allowPinAuthentication?: boolean; - /** - * Auth Window feature config string - * @example "toolbar=0,location=0,menubar=0,width=500,height=500,left=100,top=100" - */ - /** - * Origin for Identity Provider to use while generating the delegated identity. For II, the derivation origin must authorize this origin by setting a record at `/.well-known/ii-alternative-origins`. - * @see https://github.com/dfinity/internet-identity/blob/main/docs/internet-identity-spec.adoc - */ - derivationOrigin?: string | URL; - windowOpenerFeatures?: string; - /** - * Callback once login has completed - */ - onSuccess?: - | (() => void | Promise) - | (message: IIAuthResponse) => void | Promise); - /** - * Callback in case authentication fails - */ - onError?: ((error?: string) => void) | ((error?: string) => Promise); - }): Promise { + public async login(options?: AuthClientLoginOptions): Promise { // Set default maxTimeToLive to 8 hours const defaultTimeToLive = /* hours */ BigInt(8) * /* nanoseconds */ BigInt(3_600_000_000_000); @@ -544,6 +519,8 @@ export class AuthClient { maxTimeToLive: options?.maxTimeToLive, allowPinAuthentication: options?.allowPinAuthentication, derivationOrigin: options?.derivationOrigin?.toString(), + // Pass any custom values to the IDP. + ...options?.customValues, }; this._idpWindow?.postMessage(request, identityProviderUrl.origin); break; From 6b82168f37dbc0d68378bb86d8ab98ea2f24f2a7 Mon Sep 17 00:00:00 2001 From: Kyle Peacock Date: Thu, 14 Mar 2024 16:41:24 -0700 Subject: [PATCH 6/6] changelog update --- docs/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index d37fbc6e..cfa9a967 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -8,6 +8,7 @@ * New login option: `allowPinAuthentication?: boolean;` * Response from II includes `authnMethod: 'passkey' | 'pin' | 'recovery';` * OnSuccess now optionally passes the message directly from the IDP provider + * Support for arbitrary login values passed to IDP through `customValues` option ### Added