From c0b51b1e8c02d7fa6d0b6aed0d0cd4874786b996 Mon Sep 17 00:00:00 2001 From: joel Date: Sun, 21 Jul 2024 20:20:03 +0200 Subject: [PATCH 01/11] feat: initial commit --- src/GoTrueClient.ts | 49 ++++++++++++++++++++++++++++----------------- src/lib/types.ts | 43 +++++++++++++++++++++++++++++++-------- 2 files changed, 66 insertions(+), 26 deletions(-) diff --git a/src/GoTrueClient.ts b/src/GoTrueClient.ts index 00958fd65..de2380462 100644 --- a/src/GoTrueClient.ts +++ b/src/GoTrueClient.ts @@ -2341,25 +2341,38 @@ export default class GoTrueClient { return { data: null, error: sessionError } } - const { data, error } = await _request(this.fetch, 'POST', `${this.url}/factors`, { - body: { - friendly_name: params.friendlyName, - factor_type: params.factorType, - issuer: params.issuer, - }, - headers: this.headers, - jwt: sessionData?.session?.access_token, - }) - - if (error) { - return { data: null, error } - } - - if (data?.totp?.qr_code) { - data.totp.qr_code = `data:image/svg+xml;utf-8,${data.totp.qr_code}` + if (params.factorType === 'sms') { + const { data, error } = await _request(this.fetch, 'POST', `${this.url}/factors`, { + body: { + friendly_name: params.friendlyName, + factor_type: params.factorType, + phone_number: params.phoneNumber, + }, + headers: this.headers, + jwt: sessionData?.session?.access_token, + }) + if (error) { + return { data: null, error } + } + return { data, error: null } + } else { + const { data, error } = await _request(this.fetch, 'POST', `${this.url}/factors`, { + body: { + friendly_name: params.friendlyName, + factor_type: params.factorType, + issuer: params.issuer, + }, + headers: this.headers, + jwt: sessionData?.session?.access_token, + }) + if (error) { + return { data: null, error } + } + if (data?.totp?.qr_code) { + data.totp.qr_code = `data:image/svg+xml;utf-8,${data.totp.qr_code}` + } + return { data, error: null } } - - return { data, error: null } }) } catch (error) { if (isAuthError(error)) { diff --git a/src/lib/types.ts b/src/lib/types.ts index 2129c01b7..6db90008d 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -805,18 +805,29 @@ export type GenerateLinkType = | 'email_change_current' | 'email_change_new' -export type MFAEnrollParams = { - /** The type of factor being enrolled. */ - factorType: 'totp' - /** Domain which the user is enrolled with. */ - issuer?: string - /** Human readable name assigned to the factor. */ - friendlyName?: string -} +export type MFAEnrollParams = + | { + /** The type of factor being enrolled. */ + factorType: 'totp' + /** Domain which the user is enrolled with. */ + issuer?: string + /** Human readable name assigned to the factor. */ + friendlyName?: string + } + | { + /** The type of factor being enrolled. */ + factorType: 'sms' + /** Human readable name assigned to the factor. */ + friendlyName?: string + /** Phone number associated with a factor */ + phoneNumber: string + } export type MFAUnenrollParams = { /** ID of the factor being unenrolled. */ factorId: string + /** Phone number of the SMS Factor being enrolled */ + phoneNumber: string } export type MFAVerifyParams = { @@ -897,6 +908,22 @@ export type AuthMFAEnrollResponse = } error: null } + | { + data: { + /** ID of the factor that was just enrolled (in an unverified state). */ + id: string + + /** Type of MFA factor. Only `totp` supported for now. */ + type: 'sms' + + /** Friendly name of the factor, useful for distinguishing between factors **/ + friendly_name?: string + + /** Phone number of the MFA factor. Used to send SMS-es */ + phone_number: string + } + error: null + } | { data: null error: AuthError From a3ef959b07b76b650276ae2b8723717879410a15 Mon Sep 17 00:00:00 2001 From: joel Date: Tue, 23 Jul 2024 22:02:55 +0200 Subject: [PATCH 02/11] fix: add option of specifying channel --- src/GoTrueClient.ts | 1 + src/lib/types.ts | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/GoTrueClient.ts b/src/GoTrueClient.ts index de2380462..6f7364a92 100644 --- a/src/GoTrueClient.ts +++ b/src/GoTrueClient.ts @@ -2442,6 +2442,7 @@ export default class GoTrueClient { 'POST', `${this.url}/factors/${params.factorId}/challenge`, { + body: { channel: params.channel }, headers: this.headers, jwt: sessionData?.session?.access_token, } diff --git a/src/lib/types.ts b/src/lib/types.ts index 6db90008d..581cb41ee 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -844,6 +844,8 @@ export type MFAVerifyParams = { export type MFAChallengeParams = { /** ID of the factor to be challenged. Returned in enroll(). */ factorId: string + /** Messaging channel to use (e.g. whatsapp or sms). Only relevant for phone factors */ + channel?: 'sms' | 'whatsapp' } export type MFAChallengeAndVerifyParams = { From 90f1a08a9992005d167a127f75ac8def6b147966 Mon Sep 17 00:00:00 2001 From: Joel Lee Date: Thu, 25 Jul 2024 14:38:16 +0200 Subject: [PATCH 03/11] fix: update src/lib/types.ts --- src/lib/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/types.ts b/src/lib/types.ts index 581cb41ee..76260114b 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -921,7 +921,7 @@ export type AuthMFAEnrollResponse = /** Friendly name of the factor, useful for distinguishing between factors **/ friendly_name?: string - /** Phone number of the MFA factor. Used to send SMS-es */ + /** Phone number of the MFA factor. Used to send messages */ phone_number: string } error: null From e3a7702396858665ebc8191fa3efc76a5ee17b07 Mon Sep 17 00:00:00 2001 From: joel Date: Fri, 26 Jul 2024 15:05:23 +0200 Subject: [PATCH 04/11] fix: change factor type to phone --- src/GoTrueClient.ts | 6 +++++- src/lib/types.ts | 6 ++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/GoTrueClient.ts b/src/GoTrueClient.ts index 6f7364a92..550d91dd9 100644 --- a/src/GoTrueClient.ts +++ b/src/GoTrueClient.ts @@ -2341,7 +2341,7 @@ export default class GoTrueClient { return { data: null, error: sessionError } } - if (params.factorType === 'sms') { + if (params.factorType === 'phone') { const { data, error } = await _request(this.fetch, 'POST', `${this.url}/factors`, { body: { friendly_name: params.friendlyName, @@ -2497,11 +2497,15 @@ export default class GoTrueClient { const totp = factors.filter( (factor) => factor.factor_type === 'totp' && factor.status === 'verified' ) + const phone = factors.filter( + (factor) => factor.factor_type === 'phone' && factor.status === 'verified' + ) return { data: { all: factors, totp, + phone, }, error: null, } diff --git a/src/lib/types.ts b/src/lib/types.ts index 76260114b..45818223c 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -816,7 +816,7 @@ export type MFAEnrollParams = } | { /** The type of factor being enrolled. */ - factorType: 'sms' + factorType: 'phone' /** Human readable name assigned to the factor. */ friendlyName?: string /** Phone number associated with a factor */ @@ -916,7 +916,7 @@ export type AuthMFAEnrollResponse = id: string /** Type of MFA factor. Only `totp` supported for now. */ - type: 'sms' + type: 'phone' /** Friendly name of the factor, useful for distinguishing between factors **/ friendly_name?: string @@ -962,6 +962,8 @@ export type AuthMFAListFactorsResponse = /** Only verified TOTP factors. (A subset of `all`.) */ totp: Factor[] + /** Only verified Phone factors. (A subset of `all`.) */ + phone: Factor[] } error: null } From 16336dcfa54649edbbfcf4c373de69704752a453 Mon Sep 17 00:00:00 2001 From: joel Date: Mon, 5 Aug 2024 01:19:48 +0200 Subject: [PATCH 05/11] fix: update types --- src/lib/types.ts | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/lib/types.ts b/src/lib/types.ts index 45818223c..f33a0dcde 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -302,10 +302,9 @@ export interface Factor { friendly_name?: string /** - * Type of factor. Only `totp` supported with this version but may change in - * future versions. + * Type of factor. `totp` and `phone` supported with this version */ - factor_type: 'totp' | string + factor_type: 'totp' | 'phone' | string /** Factor's status. */ status: 'verified' | 'unverified' @@ -471,9 +470,6 @@ export interface Subscription { unsubscribe: () => void } -export interface UpdatableFactorAttributes { - friendlyName: string -} export type SignInAnonymouslyCredentials = { options?: { @@ -826,8 +822,6 @@ export type MFAEnrollParams = export type MFAUnenrollParams = { /** ID of the factor being unenrolled. */ factorId: string - /** Phone number of the SMS Factor being enrolled */ - phoneNumber: string } export type MFAVerifyParams = { @@ -886,7 +880,7 @@ export type AuthMFAEnrollResponse = /** ID of the factor that was just enrolled (in an unverified state). */ id: string - /** Type of MFA factor. Only `totp` supported for now. */ + /** Type of MFA factor.*/ type: 'totp' /** TOTP enrollment information. */ @@ -915,7 +909,7 @@ export type AuthMFAEnrollResponse = /** ID of the factor that was just enrolled (in an unverified state). */ id: string - /** Type of MFA factor. Only `totp` supported for now. */ + /** Type of MFA factor. */ type: 'phone' /** Friendly name of the factor, useful for distinguishing between factors **/ From b77f71a72ef9dbe0c23aa92a6949ab3a679aad9e Mon Sep 17 00:00:00 2001 From: joel Date: Fri, 9 Aug 2024 10:25:42 +0800 Subject: [PATCH 06/11] fix: correct param naming --- src/GoTrueClient.ts | 2 +- src/lib/types.ts | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/GoTrueClient.ts b/src/GoTrueClient.ts index 550d91dd9..a7ccd11df 100644 --- a/src/GoTrueClient.ts +++ b/src/GoTrueClient.ts @@ -2346,7 +2346,7 @@ export default class GoTrueClient { body: { friendly_name: params.friendlyName, factor_type: params.factorType, - phone_number: params.phoneNumber, + phone: params.phone, }, headers: this.headers, jwt: sessionData?.session?.access_token, diff --git a/src/lib/types.ts b/src/lib/types.ts index f33a0dcde..cc62c79d7 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -470,7 +470,6 @@ export interface Subscription { unsubscribe: () => void } - export type SignInAnonymouslyCredentials = { options?: { /** @@ -816,7 +815,7 @@ export type MFAEnrollParams = /** Human readable name assigned to the factor. */ friendlyName?: string /** Phone number associated with a factor */ - phoneNumber: string + phone: string } export type MFAUnenrollParams = { From 3f047b4017a1dcc165e272b231c4fa60af747d90 Mon Sep 17 00:00:00 2001 From: joel Date: Fri, 9 Aug 2024 10:29:07 +0800 Subject: [PATCH 07/11] fix: condense request body --- src/GoTrueClient.ts | 51 ++++++++++++++++++--------------------------- 1 file changed, 20 insertions(+), 31 deletions(-) diff --git a/src/GoTrueClient.ts b/src/GoTrueClient.ts index a7ccd11df..71aeb53b2 100644 --- a/src/GoTrueClient.ts +++ b/src/GoTrueClient.ts @@ -2341,38 +2341,27 @@ export default class GoTrueClient { return { data: null, error: sessionError } } - if (params.factorType === 'phone') { - const { data, error } = await _request(this.fetch, 'POST', `${this.url}/factors`, { - body: { - friendly_name: params.friendlyName, - factor_type: params.factorType, - phone: params.phone, - }, - headers: this.headers, - jwt: sessionData?.session?.access_token, - }) - if (error) { - return { data: null, error } - } - return { data, error: null } - } else { - const { data, error } = await _request(this.fetch, 'POST', `${this.url}/factors`, { - body: { - friendly_name: params.friendlyName, - factor_type: params.factorType, - issuer: params.issuer, - }, - headers: this.headers, - jwt: sessionData?.session?.access_token, - }) - if (error) { - return { data: null, error } - } - if (data?.totp?.qr_code) { - data.totp.qr_code = `data:image/svg+xml;utf-8,${data.totp.qr_code}` - } - return { data, error: null } + const body = { + friendly_name: params.friendlyName, + factor_type: params.factorType, + ...(params.factorType === 'phone' ? { phone: params.phone } : { issuer: params.issuer }), + } + + const { data, error } = await _request(this.fetch, 'POST', `${this.url}/factors`, { + body, + headers: this.headers, + jwt: sessionData?.session?.access_token, + }) + + if (error) { + return { data: null, error } } + + if (params.factorType === 'totp' && data?.totp?.qr_code) { + data.totp.qr_code = `data:image/svg+xml;utf-8,${data.totp.qr_code}` + } + + return { data, error: null } }) } catch (error) { if (isAuthError(error)) { From 3bd620e8d945ec488504d80370b90f1288cdb63c Mon Sep 17 00:00:00 2001 From: joel Date: Fri, 9 Aug 2024 10:48:36 +0800 Subject: [PATCH 08/11] fix: update comment to specify phone number should follow e.164 --- src/lib/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/types.ts b/src/lib/types.ts index cc62c79d7..9b9b75ba6 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -814,7 +814,7 @@ export type MFAEnrollParams = factorType: 'phone' /** Human readable name assigned to the factor. */ friendlyName?: string - /** Phone number associated with a factor */ + /** Phone number associated with a factor. Number should conform to E.164 format */ phone: string } From 722f02ca45f72a72038b23ba816f2e33c4115d77 Mon Sep 17 00:00:00 2001 From: joel Date: Fri, 9 Aug 2024 11:19:01 +0800 Subject: [PATCH 09/11] fix: add factor type --- src/lib/types.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lib/types.ts b/src/lib/types.ts index 9b9b75ba6..5f4970faa 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -940,6 +940,9 @@ export type AuthMFAChallengeResponse = /** ID of the newly created challenge. */ id: string + /** Factor Type which generated the challenge */ + type: 'totp' | 'phone' + /** Timestamp in UNIX seconds when this challenge will no longer be usable. */ expires_at: number } From 2ae300a2e166d5ec597c2113009e3591473528f8 Mon Sep 17 00:00:00 2001 From: joel Date: Fri, 9 Aug 2024 14:31:29 +0800 Subject: [PATCH 10/11] fix: remove totp field for phone responses --- src/GoTrueClient.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/GoTrueClient.ts b/src/GoTrueClient.ts index 71aeb53b2..3d94fe562 100644 --- a/src/GoTrueClient.ts +++ b/src/GoTrueClient.ts @@ -2357,6 +2357,11 @@ export default class GoTrueClient { return { data: null, error } } + // TODO: Remove once: https://github.com/supabase/auth/pull/1717 is deployed + if (params.factorType === 'phone') { + delete data.totp + } + if (params.factorType === 'totp' && data?.totp?.qr_code) { data.totp.qr_code = `data:image/svg+xml;utf-8,${data.totp.qr_code}` } From ece08e7276ae04c99779cdef61e912e0fa758b64 Mon Sep 17 00:00:00 2001 From: Joel Lee Date: Fri, 9 Aug 2024 14:43:00 +0800 Subject: [PATCH 11/11] fix: update types --- src/lib/types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/types.ts b/src/lib/types.ts index 5f4970faa..95b0ab214 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -914,8 +914,8 @@ export type AuthMFAEnrollResponse = /** Friendly name of the factor, useful for distinguishing between factors **/ friendly_name?: string - /** Phone number of the MFA factor. Used to send messages */ - phone_number: string + /** Phone number of the MFA factor in E.164 format. Used to send messages */ + phone: string } error: null }