-
Notifications
You must be signed in to change notification settings - Fork 47
/
client.ts
106 lines (93 loc) · 3.29 KB
/
client.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import type {
LiteralUnion,
SignInOptions,
SignInAuthorizationParams,
SignOutParams,
} from 'next-auth/react'
import type { BuiltInProviderType, RedirectableProviderType } from '@auth/core/providers'
interface AstroSignInOptions extends SignInOptions {
/** The base path for authentication (default: /api/auth) */
prefix?: string
}
interface AstroSignOutParams extends SignOutParams {
/** The base path for authentication (default: /api/auth) */
prefix?: string
}
/**
* Client-side method to initiate a 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/utilities/#signin)
*/
export async function signIn<P extends RedirectableProviderType | undefined = undefined>(
providerId?: LiteralUnion<
P extends RedirectableProviderType ? P | BuiltInProviderType : BuiltInProviderType
>,
options?: AstroSignInOptions,
authorizationParams?: SignInAuthorizationParams
) {
const { callbackUrl = window.location.href, redirect = true } = options ?? {}
const { prefix = '/api/auth', ...opts } = options ?? {}
// TODO: Support custom providers
const isCredentials = providerId === 'credentials'
const isEmail = providerId === 'email'
const isSupportingReturn = isCredentials || isEmail
// TODO: Handle custom base path
const signInUrl = `${prefix}/${isCredentials ? 'callback' : 'signin'}/${providerId}`
const _signInUrl = `${signInUrl}?${new URLSearchParams(authorizationParams)}`
// TODO: Handle custom base path
const csrfTokenResponse = await fetch(`${prefix}/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-expect-error -- ignore
body: new URLSearchParams({
...opts,
csrfToken,
callbackUrl,
}),
})
const data = await res.clone().json()
const error = new URL(data.url).searchParams.get('error')
if (redirect || !isSupportingReturn || !error) {
// 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
}
/**
* Signs the user out, by removing the session cookie.
* Automatically adds the CSRF token to the request.
*
* [Documentation](https://authjs.dev/reference/utilities/#signout)
*/
export async function signOut(options?: AstroSignOutParams) {
const { callbackUrl = window.location.href, prefix = '/api/auth' } = options ?? {}
// TODO: Custom base path
const csrfTokenResponse = await fetch(`${prefix}/csrf`)
const { csrfToken } = await csrfTokenResponse.json()
const res = await fetch(`${prefix}/signout`, {
method: 'post',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-Auth-Return-Redirect': '1',
},
body: new URLSearchParams({
csrfToken,
callbackUrl,
}),
})
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()
}