Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sveltekit): webauthn provider support #9924

Merged
merged 100 commits into from
May 11, 2024
Merged
Show file tree
Hide file tree
Changes from 99 commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
658e4f2
Fixed typos in supabase documentation (#9698)
destructo570 Jan 21, 2024
e875a16
initial passkeys
Maronato Jan 22, 2024
0e5727b
working v1
Maronato Jan 24, 2024
e2d4ef7
Merge branch 'main' into passkeys-re
Maronato Jan 24, 2024
718da79
cleanup
Maronato Jan 24, 2024
48a02ba
remove GetUserInfo restraints
Maronato Jan 24, 2024
f61552b
fix webpack renaming issues
Maronato Jan 26, 2024
745ff4b
Use simplewebauthn server 9.0.1
Maronato Jan 26, 2024
1c60ece
disconnect webauthn userID and internal database userID
Maronato Jan 27, 2024
4be9e24
Merge remote-tracking branch 'origin/main' into passkeys
Maronato Jan 27, 2024
0218442
Merge branch 'main' into passkeys
Maronato Jan 27, 2024
4e58e41
Add webauthn method testing to adapter utils
Maronato Jan 28, 2024
a67a7b6
Merge branch 'main' into passkeys
Maronato Jan 29, 2024
73491eb
Merge branch 'main' into passkeys
ndom91 Jan 29, 2024
e54a909
move simplewebauthn/server to peerdeps
Maronato Jan 29, 2024
877cf87
update pnpm lock
Maronato Jan 29, 2024
c3f7ebf
comment improvements
Maronato Jan 29, 2024
1684076
use User instead of AdapterUser for webauthn methods
Maronato Jan 29, 2024
db33581
remove unnecessary casting
Maronato Jan 29, 2024
ea6c6ec
rename baseURL to authURL in webauthn contexts
Maronato Jan 29, 2024
4825132
use inferWebAuthnOptions instead of decideWebAuthnOptions
Maronato Jan 29, 2024
267ca93
fix inferWebAuthnOptions docstring
Maronato Jan 29, 2024
d9f41ec
remove unecessary default value in inferWebAuthnOptions
Maronato Jan 29, 2024
65761bb
infer relaying party from request url
Maronato Jan 29, 2024
3590b65
simplify getLoggedInUser
Maronato Jan 29, 2024
4a536b3
Merge branch 'main' into passkeys
ndom91 Jan 30, 2024
0cdc67a
validate provider.simpleWebAuthnBrowserVersion in assertConfig
Maronato Jan 31, 2024
1d7d971
add tests to webauthn-utils
Maronato Jan 31, 2024
19e3123
Merge branch 'main' into passkeys
Maronato Feb 1, 2024
8b22ccc
Merge branch 'main' into passkeys
Maronato Feb 2, 2024
9bfbd91
allow multiple relaying parties
Maronato Feb 2, 2024
598a0dd
remove changes to dev app
Maronato Feb 2, 2024
8b8aef9
fix email and db session assertion
Maronato Feb 2, 2024
0326399
move adapter codebase to new PR
Maronato Feb 2, 2024
6649c48
Merge branch 'main' into passkeys
Maronato Feb 3, 2024
5f049fd
Merge branch 'main' into passkeys
Maronato Feb 4, 2024
78d1322
fix adapter builds
balazsorban44 Feb 5, 2024
c04f08a
fix: move @simplewebauthn/browser to peerDep
ndom91 Feb 5, 2024
4f9d992
fix: add note about installing peerDep to passkeys provider docs page
ndom91 Feb 5, 2024
82fec4f
feat: add webauthn provider support to sveltekit
ndom91 Feb 5, 2024
711b480
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Feb 6, 2024
79eff39
Discard changes to packages/core/package.json
ndom91 Feb 6, 2024
3b91d08
Discard changes to packages/core/src/lib/pages/index.ts
ndom91 Feb 6, 2024
b21d79a
Discard changes to packages/core/src/types.ts
ndom91 Feb 6, 2024
1511db3
Discard changes to packages/next-auth/src/react.tsx
ndom91 Feb 6, 2024
046a55f
Discard changes to packages/next-auth/package.json
ndom91 Feb 6, 2024
af99ba1
fix: pnpm-lock
ndom91 Feb 6, 2024
ea857fe
fix: add simplewebuathn/server to peer deps
ndom91 Feb 6, 2024
445980d
fix: swap emial for nodemailer provider in sveltekit dev app
ndom91 Feb 6, 2024
af689a6
Update packages/frameworks-sveltekit/package.json
ndom91 Feb 6, 2024
194fc89
Update packages/frameworks-sveltekit/package.json
ndom91 Feb 6, 2024
fccc619
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Feb 7, 2024
43acf33
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Feb 7, 2024
6f626e5
Merge branch 'ndom91/add-webauthn-to-sveltekit' of ssh://github.com/n…
ndom91 Feb 8, 2024
1aba9ed
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Feb 8, 2024
246a72a
Merge branch 'ndom91/add-webauthn-to-sveltekit' of ssh://github.com/n…
ndom91 Feb 8, 2024
e3cabb3
fix: update pnpm-lock
ndom91 Feb 8, 2024
4a9fa39
fix: export webauthn type from @auth/core/types
ndom91 Feb 8, 2024
5cd3f88
fix: move webauthn signIn fn to /webauthn export like next-auth
ndom91 Feb 8, 2024
666e1c9
fix: bump @simplewebauthn/server@9.0.2
ndom91 Feb 10, 2024
303a95e
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Feb 10, 2024
6017adf
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Feb 10, 2024
023ef68
fix: pnpm-lock
ndom91 Feb 11, 2024
235b93a
Merge branch 'ndom91/add-webauthn-to-sveltekit' of ssh://github.com/n…
ndom91 Feb 11, 2024
99da6bd
fix: update pnpm-lock.ymal
ndom91 Feb 11, 2024
55b784b
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Feb 11, 2024
6e452f4
fix: update pnpm-lock.yaml ..again
ndom91 Feb 11, 2024
bf989ca
fix: sveltekit dev app disable unnecessary providers
ndom91 Feb 12, 2024
6837431
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Feb 12, 2024
be615f3
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Feb 13, 2024
1773c38
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Feb 17, 2024
51fad6d
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Feb 18, 2024
00863a6
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Feb 27, 2024
0504998
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Feb 29, 2024
5f386bf
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Mar 2, 2024
a702db8
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Mar 2, 2024
56b8b9d
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Mar 4, 2024
52c2229
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Mar 8, 2024
c9dc1d3
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Mar 14, 2024
b1f277d
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Mar 16, 2024
78eb671
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Mar 16, 2024
6b081a7
fix: bump simplewebauthn/server@9.0.3
ndom91 Mar 26, 2024
ba9ee09
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Mar 26, 2024
f751251
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Apr 8, 2024
4b1f205
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Apr 9, 2024
2613f94
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Apr 14, 2024
8cf24ce
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Apr 17, 2024
0ffc51d
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Apr 21, 2024
8f0267e
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 Apr 29, 2024
0e9dbab
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 May 10, 2024
4c8e570
fix: pnpm-lock
ndom91 May 10, 2024
426f007
fix: enable webauthn in svelte dev app
ndom91 May 10, 2024
27bd2b7
fix: bump sveltekit dev app deps
ndom91 May 10, 2024
ac0468a
fix: bump svelte dev app and cleanup some routes
ndom91 May 10, 2024
d22ea3d
fix: downgrade svelte dev back to svelte4
ndom91 May 10, 2024
ddad105
fix: merge
ndom91 May 11, 2024
8c601fd
Merge branch 'main' into ndom91/add-webauthn-to-sveltekit
ndom91 May 11, 2024
2f1fb70
fix: pnpm-lock
ndom91 May 11, 2024
bd1c6c4
fix: add unstorage FS driver to make "db" persisent across HMR
ndom91 May 11, 2024
2228250
fix: update passkey doc minimum version
ndom91 May 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/dev/sveltekit/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ node_modules
.output
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
tmp-unstorage
3 changes: 1 addition & 2 deletions apps/dev/sveltekit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@
"dependencies": {
"@auth/sveltekit": "workspace:*",
"@auth/unstorage-adapter": "workspace:*",
"nodemailer": "^6.9.3",
"unstorage": "^1.10.1"
"unstorage": "^1.10.2"
},
"type": "module"
}
15 changes: 11 additions & 4 deletions apps/dev/sveltekit/src/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@ import Credentials from "@auth/sveltekit/providers/credentials"
import Facebook from "@auth/sveltekit/providers/facebook"
import Discord from "@auth/sveltekit/providers/discord"
import Google from "@auth/sveltekit/providers/google"
import Passkey from "@auth/sveltekit/providers/passkey"
import { createStorage } from "unstorage"
import { UnstorageAdapter } from "@auth/unstorage-adapter"
import fsDriver from "unstorage/drivers/fs"
import { dev } from "$app/environment"

const storage = createStorage({
driver: fsDriver({ base: "./tmp-unstorage" }),
})

const storage = createStorage()
export const { handle, signIn, signOut } = SvelteKitAuth({
debug: true,
debug: dev ? true : false,
adapter: UnstorageAdapter(storage),
session: {
strategy: "jwt",
experimental: {
enableWebAuthn: true,
},
providers: [
Credentials({
Expand All @@ -31,6 +37,7 @@ export const { handle, signIn, signOut } = SvelteKitAuth({
Google,
Facebook,
Discord,
Passkey,
],
theme: {
logo: "https://authjs.dev/img/logo-sm.png",
Expand Down
2 changes: 1 addition & 1 deletion apps/dev/sveltekit/src/routes/signin/+page.server.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { signIn } from "../../auth"
import { signIn } from "$/auth"
import type { Actions } from "./$types"

export const actions = { default: signIn } satisfies Actions
2 changes: 1 addition & 1 deletion apps/dev/sveltekit/src/routes/signout/+page.server.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { signOut } from "../../auth"
import { signOut } from "$/auth"
import type { Actions } from "./$types"

export const actions = { default: signOut } satisfies Actions
8 changes: 3 additions & 5 deletions apps/dev/sveltekit/vite.config.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { defineConfig } from "vite"
import { sveltekit } from "@sveltejs/kit/vite"

/** @type {import('vite').UserConfig} */
const config = {
export default defineConfig({
server: {
port: 3000,
},
plugins: [sveltekit()],
}

export default config
})
2 changes: 2 additions & 0 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@
WebAuthnProviderType,
} from "./providers/webauthn.js"

export type { WebAuthnOptionsResponseBody } from "./lib/utils/webauthn-utils.js"
export type { AuthConfig } from "./index.js"

Check warning on line 77 in packages/core/src/types.ts

View check run for this annotation

Codecov / codecov/patch

packages/core/src/types.ts#L76-L77

Added lines #L76 - L77 were not covered by tests
export type { LoggerInstance }
export type Awaitable<T> = T | PromiseLike<T>
export type Awaited<T> = T extends Promise<infer U> ? U : T
Expand Down
18 changes: 18 additions & 0 deletions packages/frameworks-sveltekit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,23 @@
"set-cookie-parser": "^2.6.0"
},
"peerDependencies": {
"@simplewebauthn/browser": "^9.0.1",
"@simplewebauthn/server": "^9.0.3",
"@sveltejs/kit": "^1.0.0 || ^2.0.0",
"nodemailer": "^6.6.5",
"svelte": "^3.54.0 || ^4.0.0 || ^5"
},
"peerDependenciesMeta": {
"@simplewebauthn/browser": {
"optional": true
},
"@simplewebauthn/server": {
"optional": true
},
"nodemailer": {
"optional": true
}
},
"type": "module",
"types": "./dist/index.d.ts",
"files": [
Expand All @@ -68,6 +82,10 @@
"types": "./dist/client.d.ts",
"import": "./dist/client.js"
},
"./webauthn": {
"types": "./dist/webauthn.d.ts",
"import": "./dist/webauthn.js"
},
"./components": {
"types": "./dist/components/index.d.ts",
"svelte": "./dist/components/index.js"
Expand Down
10 changes: 6 additions & 4 deletions packages/frameworks-sveltekit/src/lib/client.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { base } from "$app/paths"

Check warning on line 1 in packages/frameworks-sveltekit/src/lib/client.ts

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/client.ts#L1

Added line #L1 was not covered by tests
import type {
BuiltInProviderType,
RedirectableProviderType,
} from "@auth/core/providers"
import { base } from "$app/paths"
import type { LiteralUnion } from "./types.js"

Check warning on line 6 in packages/frameworks-sveltekit/src/lib/client.ts

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/client.ts#L6

Added line #L6 was not covered by tests

type LiteralUnion<T extends U, U = string> = T | (U & Record<never, never>)

interface SignInOptions extends Record<string, unknown> {
/*
* @internal
*/
export interface SignInOptions extends Record<string, unknown> {

Check warning on line 11 in packages/frameworks-sveltekit/src/lib/client.ts

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/client.ts#L8-L11

Added lines #L8 - L11 were not covered by tests
/**
* Specify to which URL the user will be redirected after signing in. Defaults to the page URL the sign-in is initiated from.
*
Expand Down
4 changes: 4 additions & 0 deletions packages/frameworks-sveltekit/src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
import type { BuiltInProviderType } from "@auth/core/providers"
import type { Session } from "@auth/core/types"

export type LiteralUnion<T extends U, U = string> =
| T
| (U & Record<never, never>)

Check warning on line 8 in packages/frameworks-sveltekit/src/lib/types.ts

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/types.ts#L5-L8

Added lines #L5 - L8 were not covered by tests
/** Configure the {@link SvelteKitAuth} method. */
export interface SvelteKitAuthConfig extends Omit<AuthConfig, "raw"> {}

Expand Down
118 changes: 118 additions & 0 deletions packages/frameworks-sveltekit/src/lib/webauthn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { base } from "$app/paths"
import { startAuthentication, startRegistration } from "@simplewebauthn/browser"

import type {
BuiltInProviderType,
RedirectableProviderType,
} from "@auth/core/providers"
import type { WebAuthnOptionsResponseBody } from "@auth/core/types"
import type { SignInOptions, SignInAuthorizationParams } from "./client.js"
import type { LiteralUnion } from "./types.js"

/**
* Fetch webauthn options from server and prompt user for authentication or registration.
* Returns either the completed WebAuthn response or an error request.
*
* @param providerId provider ID
* @param options SignInOptions
* @returns WebAuthn response or error
*/
async function webAuthnOptions(providerId: string, options?: SignInOptions) {
const baseUrl = `${base}/auth/`
ndom91 marked this conversation as resolved.
Show resolved Hide resolved

// @ts-expect-error
const params = new URLSearchParams(options)

const optionsResp = await fetch(
`${baseUrl}/webauthn-options/${providerId}?${params}`
)
if (!optionsResp.ok) {
return { error: optionsResp }
}
const optionsData: WebAuthnOptionsResponseBody = await optionsResp.json()

if (optionsData.action === "authenticate") {
const webAuthnResponse = await startAuthentication(optionsData.options)
return { data: webAuthnResponse, action: "authenticate" }
} else {
const webAuthnResponse = await startRegistration(optionsData.options)
return { data: webAuthnResponse, action: "register" }
}
}

/**
* Client-side method to initiate a webauthn signin flow
* or send the user to the signin page listing all possible providers.
* Automatically adds the CSRF token to the request.
*
* [Documentation](https://authjs.dev/reference/sveltekit/client#signin)
*/
export async function signIn<
ndom91 marked this conversation as resolved.
Show resolved Hide resolved
P extends RedirectableProviderType | undefined = undefined,
>(
providerId?: LiteralUnion<
P extends RedirectableProviderType
? P | BuiltInProviderType
: BuiltInProviderType
>,
options?: SignInOptions,
authorizationParams?: SignInAuthorizationParams
) {
const { callbackUrl = window.location.href, redirect = true } = options ?? {}

// TODO: Support custom providers
const isCredentials = providerId === "credentials"
const isEmail = providerId === "email"
const isWebAuthn = providerId === "webauthn"
const isSupportingReturn = isCredentials || isEmail || isWebAuthn

const basePath = base ?? ""
const signInUrl = `${basePath}/auth/${
isCredentials || isWebAuthn ? "callback" : "signin"
}/${providerId}`

const _signInUrl = `${signInUrl}?${new URLSearchParams(authorizationParams)}`

// Execute WebAuthn client flow if needed
const webAuthnBody: Record<string, unknown> = {}
if (isWebAuthn) {
const { data, error, action } = await webAuthnOptions(providerId, options)
if (error) {
// logger.error(new Error(await error.text()))
return
}
webAuthnBody.data = JSON.stringify(data)
webAuthnBody.action = action
}

// TODO: Remove this since Sveltekit offers the CSRF protection via origin check
const csrfTokenResponse = await fetch(`${basePath}/auth/csrf`)
const { csrfToken } = await csrfTokenResponse.json()

const res = await fetch(_signInUrl, {
method: "post",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"X-Auth-Return-Redirect": "1",
},
// @ts-ignore
body: new URLSearchParams({
...options,
csrfToken,
callbackUrl,
...webAuthnBody,
}),
})

const data = await res.clone().json()

if (redirect || !isSupportingReturn) {
// TODO: Do not redirect for Credentials and Email providers by default in next major
window.location.href = data.url ?? callbackUrl
// If url contains a hash, the browser does not reload the page. We reload manually
if (data.url.includes("#")) window.location.reload()
return
}

return res
}

Check warning on line 118 in packages/frameworks-sveltekit/src/lib/webauthn.ts

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/webauthn.ts#L1-L118

Added lines #L1 - L118 were not covered by tests
2 changes: 1 addition & 1 deletion packages/next-auth/src/webauthn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { getCsrfToken, getProviders, __NEXTAUTH } from "./react.js"

import type { LoggerInstance } from "@auth/core/types"
import type { WebAuthnOptionsResponseBody } from "@auth/core/lib/utils/webauthn-utils"
import type { WebAuthnOptionsResponseBody } from "@auth/core/types"

Check warning on line 6 in packages/next-auth/src/webauthn.ts

View check run for this annotation

Codecov / codecov/patch

packages/next-auth/src/webauthn.ts#L6

Added line #L6 was not covered by tests
import type {
BuiltInProviderType,
RedirectableProviderType,
Expand Down
Loading
Loading