Skip to content

Commit

Permalink
fix: modify challenge types
Browse files Browse the repository at this point in the history
  • Loading branch information
J0 committed Sep 23, 2024
1 parent 7673fd9 commit d933990
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 54 deletions.
27 changes: 13 additions & 14 deletions src/GoTrueClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ import {
supportsLocalStorage,
parseParametersFromURL,
getCodeChallengeAndMethod,
base64URLStringToBuffer,
} from './lib/helpers'
import { localStorageAdapter, memoryLocalStorageAdapter } from './lib/local-storage'
import { polyfillGlobalThis } from './lib/polyfills'
import { version } from './lib/version'
import { LockAcquireTimeoutError, navigatorLock } from './lib/locks'
import { startRegistration } from '@simplewebauthn/browser'

import type {
AuthChangeEvent,
Expand Down Expand Up @@ -2427,18 +2427,8 @@ export default class GoTrueClient {
return { data: null, error: new Error('Invalid challenge data for WebAuthn') }
}
try {
const publicKeyCredentialCreationOptions =
challengeData.public_key_credential_creation_options as PublicKeyCredentialCreationOptions

// Convert the challenge to an ArrayBuffer if it is in base64 or base64url format
publicKeyCredentialCreationOptions.challenge = base64URLStringToBuffer(
publicKeyCredentialCreationOptions.challenge
)

const publicKey = await navigator.credentials.create(
challengeData.public_key_credential_creation_options
)
console.log('post attempt')
const publicKeyOptions = challengeData
const publicKey = await startRegistration(publicKeyOptions)
if (!publicKey) {
return { data: null, error: new Error('Failed to create credentials') }
}
Expand Down Expand Up @@ -2541,12 +2531,20 @@ export default class GoTrueClient {
return { data: null, error: sessionError }
}

let body: { channel?: 'sms' | 'whatsapp' } | { rp?: { id: string } } | {} = {}

if ('channel' in params) {
body = { channel: params.channel }
} else if ('rp' in params) {
body = { rp: params.rp }
}

return await _request(
this.fetch,
'POST',
`${this.url}/factors/${params.factorId}/challenge`,
{
body: { channel: params.channel },
body,
headers: this.headers,
jwt: sessionData?.session?.access_token,
}
Expand All @@ -2564,6 +2562,7 @@ export default class GoTrueClient {
/**
* {@see GoTrueMFAApi#challengeAndVerify}
*/
// TODO: Undo this change
private async _challengeAndVerify(params: {
factorId: string
code: string
Expand Down
33 changes: 0 additions & 33 deletions src/lib/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -346,36 +346,3 @@ export function parseResponseAPIVersion(response: Response) {
}

// Taken from simplewebauthn
/**
* Convert from a Base64URL-encoded string to an Array Buffer. Best used when converting a
* credential ID from a JSON string to an ArrayBuffer, like in allowCredentials or
* excludeCredentials
*
* Helper method to compliment `bufferToBase64URLString`
*/
export function base64URLStringToBuffer(base64URLString: string): ArrayBuffer {
// Convert from Base64URL to Base64
const base64 = base64URLString.replace(/-/g, '+').replace(/_/g, '/')
/**
* Pad with '=' until it's a multiple of four
* (4 - (85 % 4 = 1) = 3) % 4 = 3 padding
* (4 - (86 % 4 = 2) = 2) % 4 = 2 padding
* (4 - (87 % 4 = 3) = 1) % 4 = 1 padding
* (4 - (88 % 4 = 0) = 4) % 4 = 0 padding
*/
const padLength = (4 - (base64.length % 4)) % 4
const padded = base64.padEnd(base64.length + padLength, '=')

// Convert to a binary string
const binary = atob(padded)

// Convert binary string to buffer
const buffer = new ArrayBuffer(binary.length)
const bytes = new Uint8Array(buffer)

for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i)
}

return buffer
}
27 changes: 20 additions & 7 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -860,22 +860,35 @@ export type MFAVerifyWebAuthnParams =
publicKey: Credential
}

export type MFAChallengeTOTPParams = {
/** ID of the factor to be challenged. Returned in enroll(). */
factorId: string
}

export type MFAChallengePhoneParams = MFAChallengeTOTPParams & { channel?: 'sms' | 'whatsapp' }

export type MFAChallengeWebAuthnParams = {
/** ID of the factor to be challenged. Returned in enroll(). */
factorId: string
rp?: {
id: string
}
}

export type MFAEnrollParams = MFAEnrollTOTPParams | MFAEnrollPhoneParams | MFAEnrollWebAuthnParams

export type MFAChallengeParams =
| MFAChallengeTOTPParams
| MFAChallengePhoneParams
| MFAChallengeWebAuthnParams

export type MFAVerifyParams = MFAVerifyTOTPParams | MFAVerifyPhoneParams | MFAVerifyWebAuthnParams

export type MFAUnenrollParams = {
/** ID of the factor being unenrolled. */
factorId: string
}

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 =
| {
/** ID of the factor being verified. Returned in enroll(). */
Expand Down

0 comments on commit d933990

Please sign in to comment.