Skip to content

Commit

Permalink
more tweak sveltekit
Browse files Browse the repository at this point in the history
  • Loading branch information
balazsorban44 committed Nov 16, 2024
1 parent e2fc1f1 commit 08162cb
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 74 deletions.
59 changes: 43 additions & 16 deletions packages/frameworks-sveltekit/src/lib/client.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { base } from "$app/paths"
import type { ProviderId } from "@auth/core/providers"

interface SignInOptions<Redirect extends boolean = true>
export interface SignInOptions<Redirect extends boolean = true>
extends Record<string, unknown> {
/** @deprecated Use `redirectTo` instead. */
callbackUrl?: string

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/client.ts#L2-L7

Added lines #L2 - L7 were not covered by tests
Expand All @@ -20,19 +20,25 @@ interface SignInOptions<Redirect extends boolean = true>
redirect?: Redirect
}

interface SignInResponse {
export interface SignInResponse {
error: string | undefined
code: string | undefined
status: number
ok: boolean
url: string | null

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/client.ts#L13-L28

Added lines #L13 - L28 were not covered by tests
}

interface SignOutParams<R extends boolean = true> {
/** [Documentation](https://next-auth.js.org/getting-started/client#specifying-a-callbackurl-1) */
export interface SignOutParams<Redirect extends boolean = true> {
/** @deprecated Use `redirectTo` instead. */

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/client.ts#L31-L32

Added lines #L31 - L32 were not covered by tests
callbackUrl?: string
/**
* If you pass `redirect: false`, the page will not reload.
* The session will be deleted, and `useSession` is notified, so any indication about the user will be shown as logged out automatically.
* It can give a very nice experience for the user.
*/
redirectTo?: string

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/client.ts#L34-L39

Added lines #L34 - L39 were not covered by tests
/** [Documentation](https://next-auth.js.org/getting-started/client#using-the-redirect-false-option-1 */
redirect?: R
redirect?: Redirect

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

View check run for this annotation

Codecov / codecov/patch

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

Added line #L41 was not covered by tests
}

/** Match `inputType` of `new URLSearchParams(inputType)` */
Expand Down Expand Up @@ -121,28 +127,49 @@ export async function signIn<Redirect extends boolean = true>(
}
}

export interface SignOutResponse {
url: string

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/client.ts#L118-L131

Added lines #L118 - L131 were not covered by tests
}

/**
* Signs the user out, by removing the session cookie.
* Initiate a signout, by destroying the current session.
* Handles CSRF protection.

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/client.ts#L135-L136

Added lines #L135 - L136 were not covered by tests
*
* [Documentation](https://authjs.dev/reference/sveltekit/client#signout)
* @note This method can only be used from Client Components ("use client" or Pages Router).
* For Server Actions, use the `signOut` method imported from the `auth` config.

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/client.ts#L138-L139

Added lines #L138 - L139 were not covered by tests
*/
export async function signOut(options?: SignOutParams) {
const { callbackUrl = window.location.href } = options ?? {}
const basePath = base ?? ""
const res = await fetch(`${basePath}/auth/signout`, {
export async function signOut(options?: SignOutParams<true>): Promise<void>
export async function signOut(
options?: SignOutParams<false>
): Promise<SignOutResponse>
export async function signOut<R extends boolean = true>(
options?: SignOutParams<R>
): Promise<SignOutResponse | void> {
const {
redirect = true,
redirectTo = options?.callbackUrl ?? window.location.href,
} = options ?? {}

const baseUrl = base ?? ""
const res = await fetch(`${baseUrl}/signout`, {

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/client.ts#L141-L154

Added lines #L141 - L154 were not covered by tests
method: "post",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"X-Auth-Return-Redirect": "1",
},
body: new URLSearchParams({
callbackUrl,
callbackUrl: redirectTo,

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

View check run for this annotation

Codecov / codecov/patch

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

Added line #L161 was not covered by tests
}),
})
const data = await res.json()

const url = data.url ?? callbackUrl
window.location.href = url
// If url contains a hash, the browser does not reload the page. We reload manually
if (url.includes("#")) window.location.reload()
if (redirect) {
const url = data.url ?? redirectTo
window.location.href = url
// If url contains a hash, the browser does not reload the page. We reload manually
if (url.includes("#")) window.location.reload()
return
}

return data

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/client.ts#L166-L174

Added lines #L166 - L174 were not covered by tests
}
134 changes: 76 additions & 58 deletions packages/frameworks-sveltekit/src/lib/webauthn.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,36 @@
import { base } from "$app/paths"
import { startAuthentication, startRegistration } from "@simplewebauthn/browser"

import type {
BuiltInProviderType,
RedirectableProviderType,
} from "@auth/core/providers"
import type { LoggerInstance } from "@auth/core/types"

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/webauthn.ts#L4

Added line #L4 was not covered by tests
import type { WebAuthnOptionsResponseBody } from "@auth/core/types"
import type { SignInOptions, SignInAuthorizationParams } from "./client.js"
import type { LiteralUnion } from "./types.js"
import type { ProviderId } from "@auth/core/providers"
import type {
SignInAuthorizationParams,
SignInOptions,
SignInResponse,
} from "./client.js"

const logger: LoggerInstance = {
debug: console.debug,
error: console.error,
warn: console.warn,
}

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/webauthn.ts#L6-L17

Added lines #L6 - L17 were not covered by tests

/**
* 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`
async function webAuthnOptions(
providerID: ProviderId,
options?: Omit<SignInOptions, "redirect">
) {
const baseUrl = base ?? ""

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/webauthn.ts#L23-L27

Added lines #L23 - L27 were not covered by tests

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

const optionsResp = await fetch(
`${baseUrl}/webauthn-options/${providerId}?${params}`
`${baseUrl}/webauthn-options/${providerID}?${params}`

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/webauthn.ts#L33

Added line #L33 was not covered by tests
)
if (!optionsResp.ok) {
return { error: optionsResp }
Expand All @@ -41,72 +47,84 @@ async function webAuthnOptions(providerId: string, options?: SignInOptions) {
}

/**
* Client-side method to initiate a webauthn signin flow
* or send the user to the signin page listing all possible providers.
*
* [Documentation](https://authjs.dev/reference/sveltekit/client#signin)
* Initiate a WebAuthn signin flow.
* @see https://authjs.dev/getting-started/authentication/webauthn

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/webauthn.ts#L50-L51

Added lines #L50 - L51 were not covered by tests
*/
export async function signIn<
P extends RedirectableProviderType | undefined = undefined,
>(
providerId?: LiteralUnion<
P extends RedirectableProviderType
? P | BuiltInProviderType
: BuiltInProviderType
>,
options?: SignInOptions,
export async function signIn(
provider?: ProviderId,
options?: SignInOptions<true>,

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/webauthn.ts#L53-L55

Added lines #L53 - L55 were not covered by tests
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
): Promise<void>
export async function signIn(
provider?: ProviderId,
options?: SignInOptions<false>,
authorizationParams?: SignInAuthorizationParams
): Promise<SignInResponse>
export async function signIn<Redirect extends boolean = true>(
provider?: ProviderId,
options?: SignInOptions<Redirect>,
authorizationParams?: SignInAuthorizationParams
): Promise<SignInResponse | void> {
const { callbackUrl, ...rest } = options ?? {}
const {
redirectTo = callbackUrl ?? window.location.href,
redirect = true,
...signInParams
} = rest

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/webauthn.ts#L57-L73

Added lines #L57 - L73 were not covered by tests

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

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/webauthn.ts#L75

Added line #L75 was not covered by tests

const _signInUrl = `${signInUrl}?${new URLSearchParams(authorizationParams)}`
if (!provider || provider !== "webauthn") {
// TODO: Add docs link with explanation
throw new TypeError(
[
`Provider id "${provider}" does not refer to a WebAuthn provider.`,
'Please use `import { signIn } from "@auth/sveltekit/client"` instead.',
].join("\n")
)
}

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/webauthn.ts#L77-L85

Added lines #L77 - L85 were not covered by tests

// 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
const webAuthnResponse = await webAuthnOptions(provider, signInParams)
if (webAuthnResponse.error) {
logger.error(new Error(await webAuthnResponse.error.text()))
return

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/webauthn.ts#L88-L91

Added lines #L88 - L91 were not covered by tests
}
webAuthnBody.data = JSON.stringify(webAuthnResponse.data)
webAuthnBody.action = webAuthnResponse.action

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/webauthn.ts#L93-L94

Added lines #L93 - L94 were not covered by tests

const res = await fetch(_signInUrl, {
const signInUrl = `${baseUrl}/callback/${provider}?${new URLSearchParams(authorizationParams)}`
const res = await fetch(signInUrl, {

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/webauthn.ts#L96-L97

Added lines #L96 - L97 were not covered by tests
method: "post",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"X-Auth-Return-Redirect": "1",
},
// @ts-ignore
body: new URLSearchParams({
...options,
callbackUrl,
...signInParams,

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/webauthn.ts#L104

Added line #L104 was not covered by tests
...webAuthnBody,
callbackUrl: redirectTo,

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/webauthn.ts#L106

Added line #L106 was not covered by tests
}),
})

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

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/webauthn.ts#L110

Added line #L110 was not covered by tests

if (redirect || !isSupportingReturn) {
// TODO: Do not redirect for Credentials and Email providers by default in next major
window.location.href = data.url ?? callbackUrl
if (redirect) {
const url = data.url ?? callbackUrl
window.location.href = url

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/webauthn.ts#L112-L114

Added lines #L112 - L114 were not covered by tests
// If url contains a hash, the browser does not reload the page. We reload manually
if (data.url.includes("#")) window.location.reload()
if (url.includes("#")) window.location.reload()

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/webauthn.ts#L116

Added line #L116 was not covered by tests
return
}

return res
const error = new URL(data.url).searchParams.get("error")
const code = new URL(data.url).searchParams.get("code")

return {
error,
code,
status: res.status,
ok: res.ok,
url: error ? null : data.url,
} as any

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

View check run for this annotation

Codecov / codecov/patch

packages/frameworks-sveltekit/src/lib/webauthn.ts#L120-L129

Added lines #L120 - L129 were not covered by tests
}

0 comments on commit 08162cb

Please sign in to comment.