Skip to content

feat: webauthn support schema changes, update openapi.yaml - #2163

Merged
hf merged 1 commit into
masterfrom
bewinxed/webauthn-support
Sep 24, 2025
Merged

feat: webauthn support schema changes, update openapi.yaml#2163
hf merged 1 commit into
masterfrom
bewinxed/webauthn-support

Conversation

@Bewinxed

@BewinxedBewinxed commented Sep 13, 2025

Copy link
Copy Markdown
Collaborator

What kind of change does this PR introduce?

Feature improvement / API cleanup

What is the current behavior?

  • The API returns credential_creation_options and credential_request_options as separate fields at the root level, requiring clients to check which is null
  • OpenAPI spec doesn't match actual server output (missing publicKey wrapper that go-webauthn library adds)
  • Field naming inconsistent with W3C spec (web_authn vs standard webauthn)

What is the new behavior?

  1. Challenge response structure changed to discriminated union:
  • Before: Check null fields {credential_creation_options?: ..., credential_request_options?: ...}
  • After: Single typed field {type: "create" | "request", credential_options: {publicKey: ...}}
  1. Verify request structure unified:
  • Before: {creation_response?: ..., assertion_response?: ...}
  • After: {type: "create" | "request", credential_response: ...}
  1. RPOrigins changed from comma-separated string to string array (matches go-webauthn v3 expectations)

Additional context

This makes the PR for the auth-js library easier.

hf
hf approved these changes Sep 15, 2025
@hf

hf commented Sep 19, 2025

Copy link
Copy Markdown
Contributor

Tested, works beautifully! Let's merge on Monday.

hf
hf approved these changes Sep 23, 2025
@hf
hfforce-pushed the bewinxed/webauthn-support branch from c0231f2 to 551dcd3CompareSeptember 23, 2025 13:59
@coveralls

Copy link
Copy Markdown

Pull Request Test Coverage Report for Build 17948586214

Details

  • 13 of 36(36.11%) changed or added relevant lines in 1 file are covered.
  • 2 unchanged lines in 1 file lost coverage.
  • Overall coverage increased (+0.008%) to 67.708%

Changes Missing CoverageCovered LinesChanged/Added Lines%
internal/api/mfa.go133636.11%
Files with Coverage ReductionNew Missed Lines%
internal/api/mfa.go257.98%
TotalsCoverage Status
Change from base Build 17947966352:0.008%
Covered Lines:13004
Relevant Lines:19206

💛 - Coveralls

@hf
hfforce-pushed the bewinxed/webauthn-support branch from 551dcd3 to ddc2d19CompareSeptember 24, 2025 13:01
@hf
hf merged commit 68cb8d2 into masterSep 24, 2025
5 checks passed
@hf
hf deleted the bewinxed/webauthn-support branch September 24, 2025 13:17
hf added a commit to supabase/auth-js that referenced this pull request Sep 24, 2025
## What kind of change does this PR introduce?
**Feature** - This PR introduces YubiKey support for Multi-Factor
Authentication (MFA) via WebAuthn, enabling users to authenticate with
hardware security keys.
## What is the current behavior?
Currently, Supabase Auth JS supports two MFA methods:
- TOTP (Time-based One-Time Password) authenticators
- SMS-based verification
## What is the new behavior?
This PR adds full WebAuthn support to the authentication library, the
defaults enable yubikey support at the moment, but it allows the user to
override some parameters client-side to use other types of passkey
methods.
The PR adds the 'webauthn' factor type, to `listFactors`, `enroll()`,
`challenge()`, and `verify()`
(De)serialization of the webauthn reponse/credential object is done
behind the scenes via dedicated objects.
it also adds a new `experimental` namespace `.mfa.webauthn` which has a
`.register()` and `.authenticate()` methods, these methods allows
**single click** yubikey 2FA addition with a single function call.
additionally, we have `webauthn.{enroll|challenge|verify}()`, which
abstract away some of the logic surrounding enrollment, interaction with
the verifier, and have defaults for factortype etc.
### Two ways to use the new api:
#### Single Step
```typescript
const { data, error } = await client.mfa.webauthn.register({
friendlyName: `Security Key ${new Date().toLocaleDateString()}`,
rpId: window.location.hostname,
rpOrigins: [window.location.origin]
}, {
authenticatorSelection: {
authenticatorAttachment: 'platform',
residentKey: 'discouraged',
userVerification: 'discouraged',
requireResidentKey: false
}
});
if (error) throw error;
console.log(data); // <- session
```
#### Multi Step Composition
```typescript
const { enroll, challenge, verify } = new WebAuthnApi(client);
return enroll({
friendlyName: params.friendlyName
})
.then(async ({ data, error }) => {
if (!data) {
throw error;
}
console.log(`enrolled factor, id: ${data.id}`, 'success');
return await challenge({
factorId: data?.id,
webauthn: {
rpId: params.rpId,
rpOrigins: params.rpOrigins
},
signal: undefined
});
})
.then(async ({ data, error }) => {
if (!data) {
throw error;
}
console.log(`challenged factor, id: ${data.factorId}`, 'success');
return await verify({
factorId: data.factorId,
challengeId: data.challengeId,
webauthn: {
rpId: params.rpId,
rpOrigins: params.rpOrigins,
type: data.webauthn.type,
credential_response: data.webauthn.credential_response
}
});
})
.then(({ data, error }) => {
if (!data) {
throw error;
}
console.log(`verified factor, id: ${data.access_token}`, 'success');
return data;
});
```
## Additional context
While this PR focuses on YubiKey support, the architecture is designed
to accommodate additional authenticator types in future releases
(platform authenticators, passkeys, etc.) without requiring significant
refactoring.
I've added `webauthn.dom.ts` and `webauthn.errors.ts` which attempt to
augment the typescript interfaces for webauthn since they are out of
date and there are some new features that its not aware of yet but are
publicly available in all major browsers.
For all such types, and due to the complexity of the API, I've added
comprehensive jsdocs for each parameter with reference to the w3a spec
for reference on their usage.
in all webauthn related methods, I've added the ability to **override**
any of the parameters we pass by default to the
`credentials.{get|create}()` method for convenience.
This PR is dependent on my previous PR for streamlining types
#1116
and this PR for `auth` supabase/auth#2163
---------
Co-authored-by: Stojan Dimitrovski <sdimitrovski@gmail.com>
fadymak pushed a commit that referenced this pull request Sep 30, 2025
## What kind of change does this PR introduce?
Feature improvement / API cleanup
## What is the current behavior?
- The API returns credential_creation_options and
credential_request_options as separate fields at the root level,
requiring clients to check which is null
- OpenAPI spec doesn't match actual server output (missing publicKey
wrapper that go-webauthn library adds)
- Field naming inconsistent with W3C spec (web_authn vs standard
webauthn)
## What is the new behavior?
1. Challenge response structure changed to discriminated union:
- Before: Check null fields {credential_creation_options?: ...,
credential_request_options?: ...}
- After: Single typed field {type: "create" | "request",
credential_options: {publicKey: ...}}
2. Verify request structure unified:
- Before: {creation_response?: ..., assertion_response?: ...}
- After: {type: "create" | "request", credential_response: ...}
3. RPOrigins changed from comma-separated string to string array
(matches go-webauthn v3 expectations)
## Additional context
This makes the PR for the auth-js library easier.
mandarini pushed a commit to supabase/supabase-js that referenced this pull request Oct 2, 2025
## What kind of change does this PR introduce?
**Feature** - This PR introduces YubiKey support for Multi-Factor
Authentication (MFA) via WebAuthn, enabling users to authenticate with
hardware security keys.
## What is the current behavior?
Currently, Supabase Auth JS supports two MFA methods:
- TOTP (Time-based One-Time Password) authenticators
- SMS-based verification
## What is the new behavior?
This PR adds full WebAuthn support to the authentication library, the
defaults enable yubikey support at the moment, but it allows the user to
override some parameters client-side to use other types of passkey
methods.
The PR adds the 'webauthn' factor type, to `listFactors`, `enroll()`,
`challenge()`, and `verify()`
(De)serialization of the webauthn reponse/credential object is done
behind the scenes via dedicated objects.
it also adds a new `experimental` namespace `.mfa.webauthn` which has a
`.register()` and `.authenticate()` methods, these methods allows
**single click** yubikey 2FA addition with a single function call.
additionally, we have `webauthn.{enroll|challenge|verify}()`, which
abstract away some of the logic surrounding enrollment, interaction with
the verifier, and have defaults for factortype etc.
### Two ways to use the new api:
#### Single Step
```typescript
const { data, error } = await client.mfa.webauthn.register({
friendlyName: `Security Key ${new Date().toLocaleDateString()}`,
rpId: window.location.hostname,
rpOrigins: [window.location.origin]
}, {
authenticatorSelection: {
authenticatorAttachment: 'platform',
residentKey: 'discouraged',
userVerification: 'discouraged',
requireResidentKey: false
}
});
if (error) throw error;
console.log(data); // <- session
```
#### Multi Step Composition
```typescript
const { enroll, challenge, verify } = new WebAuthnApi(client);
return enroll({
friendlyName: params.friendlyName
})
.then(async ({ data, error }) => {
if (!data) {
throw error;
}
console.log(`enrolled factor, id: ${data.id}`, 'success');
return await challenge({
factorId: data?.id,
webauthn: {
rpId: params.rpId,
rpOrigins: params.rpOrigins
},
signal: undefined
});
})
.then(async ({ data, error }) => {
if (!data) {
throw error;
}
console.log(`challenged factor, id: ${data.factorId}`, 'success');
return await verify({
factorId: data.factorId,
challengeId: data.challengeId,
webauthn: {
rpId: params.rpId,
rpOrigins: params.rpOrigins,
type: data.webauthn.type,
credential_response: data.webauthn.credential_response
}
});
})
.then(({ data, error }) => {
if (!data) {
throw error;
}
console.log(`verified factor, id: ${data.access_token}`, 'success');
return data;
});
```
## Additional context
While this PR focuses on YubiKey support, the architecture is designed
to accommodate additional authenticator types in future releases
(platform authenticators, passkeys, etc.) without requiring significant
refactoring.
I've added `webauthn.dom.ts` and `webauthn.errors.ts` which attempt to
augment the typescript interfaces for webauthn since they are out of
date and there are some new features that its not aware of yet but are
publicly available in all major browsers.
For all such types, and due to the complexity of the API, I've added
comprehensive jsdocs for each parameter with reference to the w3a spec
for reference on their usage.
in all webauthn related methods, I've added the ability to **override**
any of the parameters we pass by default to the
`credentials.{get|create}()` method for convenience.
This PR is dependent on my previous PR for streamlining types
supabase/auth-js#1116
and this PR for `auth` supabase/auth#2163
---------
Co-authored-by: Stojan Dimitrovski <sdimitrovski@gmail.com>
fadymak pushed a commit that referenced this pull request Nov 4, 2025
🤖 I have created a release *beep* *boop*
---
##
[2.181.0](v2.180.0...v2.181.0)
(2025-10-31)
### Features
* add `.well-known/openid-configuration`
([#2197](#2197))
([9a8d0df](9a8d0df))
* add `auth_migration` annotation for the migrations
([#2234](#2234))
([b276d0b](b276d0b))
* add advisor to notify you when to double the max connection pool
([#2167](#2167))
([a72f5d9](a72f5d9))
* add after-user-created hook
([#2169](#2169))
([bd80df8](bd80df8))
* add support for account changes notifications in email send hook
([#2192](#2192))
([6b382ae](6b382ae))
* email address changed notification
([#2181](#2181))
([047f851](047f851))
* identity linked/unlinked notifications
([#2185](#2185))
([7d46936](7d46936))
* introduce v2 refresh token algorithm
([#2216](#2216))
([dea5b8e](dea5b8e))
* MFA factor enrollment notifications
([#2183](#2183))
([53db712](53db712))
* notify users when their phone number has changed
([#2184](#2184))
([21f3070](21f3070))
* **oauthserver:** add OAuth client admin update endpoint
([#2231](#2231))
([6296a5a](6296a5a))
* properly handle redirect url fragments and unusual hostnames
([#2200](#2200))
([aa0ac5b](aa0ac5b))
* store latest challenge/attestation data
([#2179](#2179))
([01ebce1](01ebce1))
* support percentage based db limits with reload support
([#2177](#2177))
([1731466](1731466))
* webauthn support schema changes, update openapi.yaml
([#2163](#2163))
([68cb8d2](68cb8d2))
### Bug Fixes
* gosec incorrectly warns about accessing signature[64]
([#2222](#2222))
([bca6626](bca6626))
* **openapi:** add missing OAuth client registration fields
([#2227](#2227))
([cf39a8a](cf39a8a))
---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
DevRyuki pushed a commit to sasatech-gk/supabase-auth that referenced this pull request Feb 23, 2026
🤖 I have created a release *beep* *boop*
---
##
[2.181.0](supabase/auth@v2.180.0...v2.181.0)
(2025-10-31)
### Features
* add `.well-known/openid-configuration`
([supabase#2197](supabase#2197))
([9a8d0df](supabase@9a8d0df))
* add `auth_migration` annotation for the migrations
([supabase#2234](supabase#2234))
([b276d0b](supabase@b276d0b))
* add advisor to notify you when to double the max connection pool
([supabase#2167](supabase#2167))
([a72f5d9](supabase@a72f5d9))
* add after-user-created hook
([supabase#2169](supabase#2169))
([bd80df8](supabase@bd80df8))
* add support for account changes notifications in email send hook
([supabase#2192](supabase#2192))
([6b382ae](supabase@6b382ae))
* email address changed notification
([supabase#2181](supabase#2181))
([047f851](supabase@047f851))
* identity linked/unlinked notifications
([supabase#2185](supabase#2185))
([7d46936](supabase@7d46936))
* introduce v2 refresh token algorithm
([supabase#2216](supabase#2216))
([dea5b8e](supabase@dea5b8e))
* MFA factor enrollment notifications
([supabase#2183](supabase#2183))
([53db712](supabase@53db712))
* notify users when their phone number has changed
([supabase#2184](supabase#2184))
([21f3070](supabase@21f3070))
* **oauthserver:** add OAuth client admin update endpoint
([supabase#2231](supabase#2231))
([6296a5a](supabase@6296a5a))
* properly handle redirect url fragments and unusual hostnames
([supabase#2200](supabase#2200))
([aa0ac5b](supabase@aa0ac5b))
* store latest challenge/attestation data
([supabase#2179](supabase#2179))
([01ebce1](supabase@01ebce1))
* support percentage based db limits with reload support
([supabase#2177](supabase#2177))
([1731466](supabase@1731466))
* webauthn support schema changes, update openapi.yaml
([supabase#2163](supabase#2163))
([68cb8d2](supabase@68cb8d2))
### Bug Fixes
* gosec incorrectly warns about accessing signature[64]
([supabase#2222](supabase#2222))
([bca6626](supabase@bca6626))
* **openapi:** add missing OAuth client registration fields
([supabase#2227](supabase#2227))
([cf39a8a](supabase@cf39a8a))
---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Bewinxed@hf@coveralls