Skip to content

Commit

Permalink
fix: refactor into branches
Browse files Browse the repository at this point in the history
  • Loading branch information
J0 committed Oct 2, 2024
1 parent 00f6c1d commit f445ba5
Showing 1 changed file with 74 additions and 72 deletions.
146 changes: 74 additions & 72 deletions src/GoTrueClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2455,82 +2455,12 @@ export default class GoTrueClient {
* {@see GoTrueMFAApi#verify}
*/
private async _verify(params: MFAVerifyParams): Promise<AuthMFAVerifyResponse> {
let webAuthnFactor: Factor
if ('factorType' in params && params.factorType === 'webauthn') {
const {
data: { user },
error: userError,
} = await this._getUser()
const factors = user?.factors || []

const webauthn = factors.filter(
(factor) => factor.factor_type === 'webauthn' && factor.status === 'verified'
)

webAuthnFactor = webauthn[0]
if (!webAuthnFactor) {
return { data: null, error: new AuthError('No WebAuthn factor found') }
}
}
const result = await this._useSession(async (result) => {
const { data: sessionData, error: sessionError } = result
if (sessionError) {
return { data: null, error: sessionError }
}
if ('factorType' in params && params.factorType === 'webauthn') {
// Single Step enroll
const webAuthn = this._getWebAuthnRpDetails()

const { data: challengeData, error: challengeError } = await this._challenge({
factorId: webAuthnFactor.id,
webAuthn,
})
if (
!challengeData ||
!(challengeData.type === 'webauthn' && challengeData?.credential_request_options)
) {
return {
data: null,
error: new Error('Invalid challenge data for WebAuthn'),
}
}
const challengeOptions = challengeData?.credential_request_options.publicKey
const finalCredential = await startAuthentication(challengeOptions)
const verifyWebAuthnParams = { ...webAuthn, assertionResponse: finalCredential }

const { data, error } = await _request(
this.fetch,
'POST',
`${this.url}/factors/${webAuthnFactor.id}/verify`,
{
body: {
challenge_id: challengeData.id,
web_authn: {
rp_id: verifyWebAuthnParams.rpId,
rp_origins: verifyWebAuthnParams.rpOrigins,
assertion_response: verifyWebAuthnParams.assertionResponse,
},
},
headers: this.headers,
jwt: sessionData?.session?.access_token,
}
)
if (error) {
return { data: null, error }
}

await this._saveSession({
expires_at: Math.round(Date.now() / 1000) + data.expires_in,
...data,
})
await this._notifyAllSubscribers('MFA_CHALLENGE_VERIFIED', data)
return { data, error }
}
})
return this._acquireLock(-1, async () => {
try {
if ('code' in params && 'challengeId' in params && 'factorId' in params) {
return this._verifyCodeChallenge(params)
} else if ('factorType' in params && params.factorType === 'webauthn') {
return this._verifyWebAuthnSingleStep(params)
} else if ('webAuthn' in params && params.webAuthn) {
return this._verifyWebAuthnCreation(params)
}
Expand All @@ -2544,6 +2474,78 @@ export default class GoTrueClient {
})
}

private async _verifyWebAuthnSingleStep(
params: MFAVerifyWebAuthnParams
): Promise<AuthMFAVerifyResponse> {
const {
data: { user },
error: userError,
} = await this._getUser()
const factors = user?.factors || []

const webauthn = factors.filter(
(factor) => factor.factor_type === 'webauthn' && factor.status === 'verified'
)

const webAuthnFactor = webauthn[0]
if (!webAuthnFactor) {
return { data: null, error: new AuthError('No WebAuthn factor found') }
}
return this._useSession(async (sessionResult) => {
const { data: sessionData, error: sessionError } = sessionResult
if (sessionError) {
return { data: null, error: sessionError }
}
// Single Step enroll
const webAuthn = this._getWebAuthnRpDetails()

const { data: challengeData, error: challengeError } = await this._challenge({
factorId: webAuthnFactor.id,
webAuthn,
})
if (
!challengeData ||
!(challengeData.type === 'webauthn' && challengeData?.credential_request_options)
) {
return {
data: null,
error: new Error('Invalid challenge data for WebAuthn'),
}
}
const challengeOptions = challengeData?.credential_request_options.publicKey
const finalCredential = await startAuthentication(challengeOptions)
const verifyWebAuthnParams = { ...webAuthn, assertionResponse: finalCredential }

const { data, error } = await _request(
this.fetch,
'POST',
`${this.url}/factors/${webAuthnFactor.id}/verify`,
{
body: {
challenge_id: challengeData.id,
web_authn: {
rp_id: verifyWebAuthnParams.rpId,
rp_origins: verifyWebAuthnParams.rpOrigins,
assertion_response: verifyWebAuthnParams.assertionResponse,
},
},
headers: this.headers,
jwt: sessionData?.session?.access_token,
}
)
if (error) {
return { data: null, error }
}

await this._saveSession({
expires_at: Math.round(Date.now() / 1000) + data.expires_in,
...data,
})
await this._notifyAllSubscribers('MFA_CHALLENGE_VERIFIED', data)
return { data, error }
})
}

private async _verifyWebAuthnCreation(
params: MFAVerifySingleStepWebAuthnParams
): Promise<AuthMFAVerifyResponse> {
Expand Down

0 comments on commit f445ba5

Please sign in to comment.