@auth/solid-start 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client.d.ts +29 -4
- package/client.js +5 -0
- package/index.d.ts +196 -0
- package/index.js +9 -4
- package/package.json +5 -6
- package/src/client.ts +37 -9
- package/src/index.ts +196 -0
package/client.d.ts
CHANGED
|
@@ -1,20 +1,45 @@
|
|
|
1
|
-
import { LiteralUnion, SignInOptions, SignInAuthorizationParams, SignOutParams } from 'next-auth/react';
|
|
2
1
|
import { RedirectableProviderType, BuiltInProviderType } from '@auth/core/providers';
|
|
3
2
|
|
|
3
|
+
type LiteralUnion<T extends U, U = string> = T | (U & Record<never, never>);
|
|
4
|
+
interface SignInOptions extends Record<string, unknown> {
|
|
5
|
+
/**
|
|
6
|
+
* Specify to which URL the user will be redirected after signing in. Defaults to the page URL the sign-in is initiated from.
|
|
7
|
+
*
|
|
8
|
+
* [Documentation](https://next-auth.js.org/getting-started/client#specifying-a-callbackurl)
|
|
9
|
+
*/
|
|
10
|
+
callbackUrl?: string;
|
|
11
|
+
/** [Documentation](https://next-auth.js.org/getting-started/client#using-the-redirect-false-option) */
|
|
12
|
+
redirect?: boolean;
|
|
13
|
+
}
|
|
14
|
+
interface SignOutParams<R extends boolean = true> {
|
|
15
|
+
/** [Documentation](https://next-auth.js.org/getting-started/client#specifying-a-callbackurl-1) */
|
|
16
|
+
callbackUrl?: string;
|
|
17
|
+
/** [Documentation](https://next-auth.js.org/getting-started/client#using-the-redirect-false-option-1 */
|
|
18
|
+
redirect?: R;
|
|
19
|
+
}
|
|
20
|
+
/** Match `inputType` of `new URLSearchParams(inputType)` */
|
|
21
|
+
type SignInAuthorizationParams = string | string[][] | Record<string, string> | URLSearchParams;
|
|
4
22
|
/**
|
|
5
23
|
* Client-side method to initiate a signin flow
|
|
6
24
|
* or send the user to the signin page listing all possible providers.
|
|
7
25
|
* Automatically adds the CSRF token to the request.
|
|
8
26
|
*
|
|
9
|
-
*
|
|
27
|
+
* ```ts
|
|
28
|
+
* import { signIn } from "@auth/solid-start/client"
|
|
29
|
+
* signIn()
|
|
30
|
+
* signIn("provider") // example: signIn("github")
|
|
31
|
+
* ```
|
|
10
32
|
*/
|
|
11
33
|
declare function signIn<P extends RedirectableProviderType | undefined = undefined>(providerId?: LiteralUnion<P extends RedirectableProviderType ? P | BuiltInProviderType : BuiltInProviderType>, options?: SignInOptions, authorizationParams?: SignInAuthorizationParams): Promise<Response | undefined>;
|
|
12
34
|
/**
|
|
13
35
|
* Signs the user out, by removing the session cookie.
|
|
14
36
|
* Automatically adds the CSRF token to the request.
|
|
15
37
|
*
|
|
16
|
-
*
|
|
38
|
+
* ```ts
|
|
39
|
+
* import { signOut } from "@auth/solid-start/client"
|
|
40
|
+
* signOut()
|
|
41
|
+
* ```
|
|
17
42
|
*/
|
|
18
43
|
declare function signOut(options?: SignOutParams): Promise<void>;
|
|
19
44
|
|
|
20
|
-
export { signIn, signOut };
|
|
45
|
+
export { SignInAuthorizationParams, signIn, signOut };
|
package/client.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__name
|
|
3
|
+
} from "./chunk-HXRSFH6L.js";
|
|
1
4
|
async function signIn(providerId, options, authorizationParams) {
|
|
2
5
|
const { callbackUrl = window.location.href, redirect = true } = options ?? {};
|
|
3
6
|
const isCredentials = providerId === "credentials";
|
|
@@ -29,6 +32,7 @@ async function signIn(providerId, options, authorizationParams) {
|
|
|
29
32
|
}
|
|
30
33
|
return res;
|
|
31
34
|
}
|
|
35
|
+
__name(signIn, "signIn");
|
|
32
36
|
async function signOut(options) {
|
|
33
37
|
const { callbackUrl = window.location.href } = options ?? {};
|
|
34
38
|
const csrfTokenResponse = await fetch("/api/auth/csrf");
|
|
@@ -50,6 +54,7 @@ async function signOut(options) {
|
|
|
50
54
|
if (url.includes("#"))
|
|
51
55
|
window.location.reload();
|
|
52
56
|
}
|
|
57
|
+
__name(signOut, "signOut");
|
|
53
58
|
export {
|
|
54
59
|
signIn,
|
|
55
60
|
signOut
|
package/index.d.ts
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
import { AuthConfig, Session } from '@auth/core/types';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* :::warning
|
|
6
|
+
* `@auth/solid-start` is currently experimental. The API _will_ change in the future.
|
|
7
|
+
* :::
|
|
8
|
+
*
|
|
9
|
+
* SolidStart Auth is the official SolidStart integration for Auth.js.
|
|
10
|
+
* It provides a simple way to add authentication to your SolidStart app in a few lines of code.
|
|
11
|
+
*
|
|
12
|
+
* ## Installation
|
|
13
|
+
*
|
|
14
|
+
* ```bash npm2yarn
|
|
15
|
+
* npm install @auth/core @auth/solid-start
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* We recommended to using [create-jd-app](https://github.com/OrJDev/create-jd-app)
|
|
19
|
+
*
|
|
20
|
+
* @module index
|
|
21
|
+
*/
|
|
22
|
+
|
|
3
23
|
interface SolidAuthConfig extends AuthConfig {
|
|
4
24
|
/**
|
|
5
25
|
* Defines the base path for the auth routes.
|
|
@@ -7,6 +27,182 @@ interface SolidAuthConfig extends AuthConfig {
|
|
|
7
27
|
*/
|
|
8
28
|
prefix?: string;
|
|
9
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* ## Setup
|
|
32
|
+
*
|
|
33
|
+
* [Generate an auth secret](https://generate-secret.vercel.app/32), then set it as an environment variable:
|
|
34
|
+
*
|
|
35
|
+
* ```
|
|
36
|
+
* AUTH_SECRET=your_auth_secret
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* ## Creating the API handler
|
|
40
|
+
*
|
|
41
|
+
* in this example we are using github so make sure to set the following environment variables:
|
|
42
|
+
*
|
|
43
|
+
* ```
|
|
44
|
+
* GITHUB_ID=your_github_oauth_id
|
|
45
|
+
* GITHUB_SECRET=your_github_oauth_secret
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* ```ts
|
|
49
|
+
* // routes/api/auth/[...solidauth].ts
|
|
50
|
+
* import { SolidAuth, type SolidAuthConfig } from "@auth/solid-start"
|
|
51
|
+
* import GitHub from "@auth/core/providers/github"
|
|
52
|
+
*
|
|
53
|
+
* export const authOpts: SolidAuthConfig = {
|
|
54
|
+
* providers: [
|
|
55
|
+
* GitHub({
|
|
56
|
+
* clientId: process.env.GITHUB_ID,
|
|
57
|
+
* clientSecret: process.env.GITHUB_SECRET,
|
|
58
|
+
* }),
|
|
59
|
+
* ],
|
|
60
|
+
* debug: false,
|
|
61
|
+
* }
|
|
62
|
+
*
|
|
63
|
+
* export const { GET, POST } = SolidAuth(authOpts)
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* ## Getting the current session
|
|
67
|
+
*
|
|
68
|
+
* ```ts
|
|
69
|
+
* import { getSession } from "@auth/solid-start"
|
|
70
|
+
* import { createServerData$ } from "solid-start/server"
|
|
71
|
+
* import { authOpts } from "~/routes/api/auth/[...solidauth]"
|
|
72
|
+
*
|
|
73
|
+
* export const useSession = () => {
|
|
74
|
+
* return createServerData$(
|
|
75
|
+
* async (_, { request }) => {
|
|
76
|
+
* return await getSession(request, authOpts)
|
|
77
|
+
* },
|
|
78
|
+
* { key: () => ["auth_user"] }
|
|
79
|
+
* )
|
|
80
|
+
* }
|
|
81
|
+
*
|
|
82
|
+
* // useSession returns a resource:
|
|
83
|
+
* const session = useSession()
|
|
84
|
+
* const loading = session.loading
|
|
85
|
+
* const user = () => session()?.user
|
|
86
|
+
* ```
|
|
87
|
+
* ## Protected Routes
|
|
88
|
+
*
|
|
89
|
+
* ### When Using SSR
|
|
90
|
+
*
|
|
91
|
+
* When using SSR, I recommend creating a `Protected` component that will trigger suspense using the `Show` component. It should look like this:
|
|
92
|
+
*
|
|
93
|
+
*
|
|
94
|
+
* ```tsx
|
|
95
|
+
* // components/Protected.tsx
|
|
96
|
+
* import { type Session } from "@auth/core/types";
|
|
97
|
+
* import { getSession } from "@auth/solid-start";
|
|
98
|
+
* import { Component, Show } from "solid-js";
|
|
99
|
+
* import { useRouteData } from "solid-start";
|
|
100
|
+
* import { createServerData$, redirect } from "solid-start/server";
|
|
101
|
+
* import { authOpts } from "~/routes/api/auth/[...solidauth]";
|
|
102
|
+
*
|
|
103
|
+
* const Protected = (Comp: IProtectedComponent) => {
|
|
104
|
+
* const routeData = () => {
|
|
105
|
+
* return createServerData$(
|
|
106
|
+
* async (_, event) => {
|
|
107
|
+
* const session = await getSession(event.request, authOpts);
|
|
108
|
+
* if (!session || !session.user) {
|
|
109
|
+
* throw redirect("/");
|
|
110
|
+
* }
|
|
111
|
+
* return session;
|
|
112
|
+
* },
|
|
113
|
+
* { key: () => ["auth_user"] }
|
|
114
|
+
* );
|
|
115
|
+
* };
|
|
116
|
+
*
|
|
117
|
+
* return {
|
|
118
|
+
* routeData,
|
|
119
|
+
* Page: () => {
|
|
120
|
+
* const session = useRouteData<typeof routeData>();
|
|
121
|
+
* return (
|
|
122
|
+
* <Show when={session()} keyed>
|
|
123
|
+
* {(sess) => <Comp {...sess} />}
|
|
124
|
+
* </Show>
|
|
125
|
+
* );
|
|
126
|
+
* },
|
|
127
|
+
* };
|
|
128
|
+
* };
|
|
129
|
+
*
|
|
130
|
+
* type IProtectedComponent = Component<Session>;
|
|
131
|
+
*
|
|
132
|
+
* export default Protected;
|
|
133
|
+
* ```
|
|
134
|
+
*
|
|
135
|
+
* It can be used like this:
|
|
136
|
+
*
|
|
137
|
+
*
|
|
138
|
+
* ```tsx
|
|
139
|
+
* // routes/protected.tsx
|
|
140
|
+
* import Protected from "~/components/Protected";
|
|
141
|
+
*
|
|
142
|
+
* export const { routeData, Page } = Protected((session) => {
|
|
143
|
+
* return (
|
|
144
|
+
* <main class="flex flex-col gap-2 items-center">
|
|
145
|
+
* <h1>This is a protected route</h1>
|
|
146
|
+
* </main>
|
|
147
|
+
* );
|
|
148
|
+
* });
|
|
149
|
+
*
|
|
150
|
+
* export default Page;
|
|
151
|
+
* ```
|
|
152
|
+
*
|
|
153
|
+
* ### When Using CSR
|
|
154
|
+
*
|
|
155
|
+
* When using CSR, the `Protected` component will not work as expected and will cause the screen to flash, so I had to come up with a tricky solution, we will use a Solid-Start middleware:
|
|
156
|
+
*
|
|
157
|
+
* ```tsx
|
|
158
|
+
* // entry-server.tsx
|
|
159
|
+
* import { Session } from "@auth/core";
|
|
160
|
+
* import { getSession } from "@auth/solid-start";
|
|
161
|
+
* import { redirect } from "solid-start";
|
|
162
|
+
* import {
|
|
163
|
+
* StartServer,
|
|
164
|
+
* createHandler,
|
|
165
|
+
* renderAsync,
|
|
166
|
+
* } from "solid-start/entry-server";
|
|
167
|
+
* import { authOpts } from "./routes/api/auth/[...solidauth]";
|
|
168
|
+
*
|
|
169
|
+
* const protectedPaths = ["/protected"]; // add any route you wish in here
|
|
170
|
+
*
|
|
171
|
+
* export default createHandler(
|
|
172
|
+
* ({ forward }) => {
|
|
173
|
+
* return async (event) => {
|
|
174
|
+
* if (protectedPaths.includes(new URL(event.request.url).pathname)) {
|
|
175
|
+
* const session = await getSession(event.request, authOpts);
|
|
176
|
+
* if (!session) {
|
|
177
|
+
* return redirect("/");
|
|
178
|
+
* }
|
|
179
|
+
* }
|
|
180
|
+
* return forward(event);
|
|
181
|
+
* };
|
|
182
|
+
* },
|
|
183
|
+
* renderAsync((event) => <StartServer event={event} />)
|
|
184
|
+
* );
|
|
185
|
+
* ```
|
|
186
|
+
*
|
|
187
|
+
* And now you can easily create a protected route:
|
|
188
|
+
*
|
|
189
|
+
*
|
|
190
|
+
* ```tsx
|
|
191
|
+
* // routes/protected.tsx
|
|
192
|
+
* export default () => {
|
|
193
|
+
* return (
|
|
194
|
+
* <main class="flex flex-col gap-2 items-center">
|
|
195
|
+
* <h1>This is a protected route</h1>
|
|
196
|
+
* </main>
|
|
197
|
+
* );
|
|
198
|
+
* };
|
|
199
|
+
* ```
|
|
200
|
+
*
|
|
201
|
+
* :::note
|
|
202
|
+
* The CSR method should also work when using SSR, the SSR method shouldn't work when using CSR
|
|
203
|
+
* :::
|
|
204
|
+
*
|
|
205
|
+
*/
|
|
10
206
|
declare function SolidAuth(config: SolidAuthConfig): {
|
|
11
207
|
GET(event: any): Promise<Response | undefined>;
|
|
12
208
|
POST(event: any): Promise<Response | undefined>;
|
package/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__name
|
|
3
|
+
} from "./chunk-HXRSFH6L.js";
|
|
1
4
|
import { Auth } from "@auth/core";
|
|
2
5
|
const actions = [
|
|
3
6
|
"providers",
|
|
@@ -20,6 +23,7 @@ function SolidAuthHandler(prefix, authOptions) {
|
|
|
20
23
|
return await Auth(request, authOptions);
|
|
21
24
|
};
|
|
22
25
|
}
|
|
26
|
+
__name(SolidAuthHandler, "SolidAuthHandler");
|
|
23
27
|
function SolidAuth(config) {
|
|
24
28
|
const { prefix = "/api/auth", ...authOptions } = config;
|
|
25
29
|
authOptions.secret ??= process.env.AUTH_SECRET;
|
|
@@ -34,14 +38,14 @@ function SolidAuth(config) {
|
|
|
34
38
|
}
|
|
35
39
|
};
|
|
36
40
|
}
|
|
41
|
+
__name(SolidAuth, "SolidAuth");
|
|
37
42
|
async function getSession(req, options) {
|
|
38
43
|
options.secret ??= process.env.AUTH_SECRET;
|
|
39
44
|
options.trustHost ??= true;
|
|
40
45
|
const url = new URL("/api/auth/session", req.url);
|
|
41
|
-
const response = await Auth(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
);
|
|
46
|
+
const response = await Auth(new Request(url, {
|
|
47
|
+
headers: req.headers
|
|
48
|
+
}), options);
|
|
45
49
|
const { status = 200 } = response;
|
|
46
50
|
const data = await response.json();
|
|
47
51
|
if (!data || !Object.keys(data).length)
|
|
@@ -50,6 +54,7 @@ async function getSession(req, options) {
|
|
|
50
54
|
return data;
|
|
51
55
|
throw new Error(data.message);
|
|
52
56
|
}
|
|
57
|
+
__name(getSession, "getSession");
|
|
53
58
|
export {
|
|
54
59
|
SolidAuth,
|
|
55
60
|
getSession
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@auth/solid-start",
|
|
3
3
|
"description": "Authentication for SolidStart.",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.3",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
7
|
"client.*",
|
|
@@ -22,18 +22,17 @@
|
|
|
22
22
|
"publishConfig": {
|
|
23
23
|
"access": "public"
|
|
24
24
|
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@auth/core": "0.18.1"
|
|
27
|
+
},
|
|
25
28
|
"devDependencies": {
|
|
26
29
|
"@solidjs/meta": "^0.28.0",
|
|
27
30
|
"@types/node": "^18.7.14",
|
|
28
31
|
"solid-js": "^1.5.7",
|
|
29
32
|
"solid-start": "^0.2.14",
|
|
30
|
-
"tsup": "^6.5.0"
|
|
31
|
-
"typescript": "^4.8.2",
|
|
32
|
-
"@auth/core": "0.4.0",
|
|
33
|
-
"next-auth": "4.18.6"
|
|
33
|
+
"tsup": "^6.5.0"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
|
-
"@auth/core": "~0.2.2 || ^0.2.2",
|
|
37
36
|
"solid-js": "^1.5.7",
|
|
38
37
|
"solid-start": "^0.2.14"
|
|
39
38
|
},
|
package/src/client.ts
CHANGED
|
@@ -1,20 +1,45 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
LiteralUnion,
|
|
3
|
-
SignInOptions,
|
|
4
|
-
SignInAuthorizationParams,
|
|
5
|
-
SignOutParams,
|
|
6
|
-
} from "next-auth/react"
|
|
7
1
|
import type {
|
|
8
2
|
BuiltInProviderType,
|
|
9
3
|
RedirectableProviderType,
|
|
10
4
|
} from "@auth/core/providers"
|
|
11
5
|
|
|
6
|
+
type LiteralUnion<T extends U, U = string> = T | (U & Record<never, never>)
|
|
7
|
+
|
|
8
|
+
interface SignInOptions extends Record<string, unknown> {
|
|
9
|
+
/**
|
|
10
|
+
* Specify to which URL the user will be redirected after signing in. Defaults to the page URL the sign-in is initiated from.
|
|
11
|
+
*
|
|
12
|
+
* [Documentation](https://next-auth.js.org/getting-started/client#specifying-a-callbackurl)
|
|
13
|
+
*/
|
|
14
|
+
callbackUrl?: string
|
|
15
|
+
/** [Documentation](https://next-auth.js.org/getting-started/client#using-the-redirect-false-option) */
|
|
16
|
+
redirect?: boolean
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface SignOutParams<R extends boolean = true> {
|
|
20
|
+
/** [Documentation](https://next-auth.js.org/getting-started/client#specifying-a-callbackurl-1) */
|
|
21
|
+
callbackUrl?: string
|
|
22
|
+
/** [Documentation](https://next-auth.js.org/getting-started/client#using-the-redirect-false-option-1 */
|
|
23
|
+
redirect?: R
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Match `inputType` of `new URLSearchParams(inputType)` */
|
|
27
|
+
export type SignInAuthorizationParams =
|
|
28
|
+
| string
|
|
29
|
+
| string[][]
|
|
30
|
+
| Record<string, string>
|
|
31
|
+
| URLSearchParams
|
|
32
|
+
|
|
12
33
|
/**
|
|
13
34
|
* Client-side method to initiate a signin flow
|
|
14
35
|
* or send the user to the signin page listing all possible providers.
|
|
15
36
|
* Automatically adds the CSRF token to the request.
|
|
16
37
|
*
|
|
17
|
-
*
|
|
38
|
+
* ```ts
|
|
39
|
+
* import { signIn } from "@auth/solid-start/client"
|
|
40
|
+
* signIn()
|
|
41
|
+
* signIn("provider") // example: signIn("github")
|
|
42
|
+
* ```
|
|
18
43
|
*/
|
|
19
44
|
export async function signIn<
|
|
20
45
|
P extends RedirectableProviderType | undefined = undefined
|
|
@@ -51,7 +76,7 @@ export async function signIn<
|
|
|
51
76
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
52
77
|
"X-Auth-Return-Redirect": "1",
|
|
53
78
|
},
|
|
54
|
-
// @ts-
|
|
79
|
+
// @ts-ignore
|
|
55
80
|
body: new URLSearchParams({
|
|
56
81
|
...options,
|
|
57
82
|
csrfToken,
|
|
@@ -75,7 +100,10 @@ export async function signIn<
|
|
|
75
100
|
* Signs the user out, by removing the session cookie.
|
|
76
101
|
* Automatically adds the CSRF token to the request.
|
|
77
102
|
*
|
|
78
|
-
*
|
|
103
|
+
* ```ts
|
|
104
|
+
* import { signOut } from "@auth/solid-start/client"
|
|
105
|
+
* signOut()
|
|
106
|
+
* ```
|
|
79
107
|
*/
|
|
80
108
|
export async function signOut(options?: SignOutParams) {
|
|
81
109
|
const { callbackUrl = window.location.href } = options ?? {}
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* :::warning
|
|
4
|
+
* `@auth/solid-start` is currently experimental. The API _will_ change in the future.
|
|
5
|
+
* :::
|
|
6
|
+
*
|
|
7
|
+
* SolidStart Auth is the official SolidStart integration for Auth.js.
|
|
8
|
+
* It provides a simple way to add authentication to your SolidStart app in a few lines of code.
|
|
9
|
+
*
|
|
10
|
+
* ## Installation
|
|
11
|
+
*
|
|
12
|
+
* ```bash npm2yarn
|
|
13
|
+
* npm install @auth/core @auth/solid-start
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* We recommended to using [create-jd-app](https://github.com/OrJDev/create-jd-app)
|
|
17
|
+
*
|
|
18
|
+
* @module index
|
|
19
|
+
*/
|
|
20
|
+
|
|
1
21
|
import { Auth } from "@auth/core"
|
|
2
22
|
import type { AuthAction, AuthConfig, Session } from "@auth/core/types"
|
|
3
23
|
|
|
@@ -36,6 +56,182 @@ function SolidAuthHandler(prefix: string, authOptions: SolidAuthConfig) {
|
|
|
36
56
|
}
|
|
37
57
|
}
|
|
38
58
|
|
|
59
|
+
/**
|
|
60
|
+
* ## Setup
|
|
61
|
+
*
|
|
62
|
+
* [Generate an auth secret](https://generate-secret.vercel.app/32), then set it as an environment variable:
|
|
63
|
+
*
|
|
64
|
+
* ```
|
|
65
|
+
* AUTH_SECRET=your_auth_secret
|
|
66
|
+
* ```
|
|
67
|
+
*
|
|
68
|
+
* ## Creating the API handler
|
|
69
|
+
*
|
|
70
|
+
* in this example we are using github so make sure to set the following environment variables:
|
|
71
|
+
*
|
|
72
|
+
* ```
|
|
73
|
+
* GITHUB_ID=your_github_oauth_id
|
|
74
|
+
* GITHUB_SECRET=your_github_oauth_secret
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* ```ts
|
|
78
|
+
* // routes/api/auth/[...solidauth].ts
|
|
79
|
+
* import { SolidAuth, type SolidAuthConfig } from "@auth/solid-start"
|
|
80
|
+
* import GitHub from "@auth/core/providers/github"
|
|
81
|
+
*
|
|
82
|
+
* export const authOpts: SolidAuthConfig = {
|
|
83
|
+
* providers: [
|
|
84
|
+
* GitHub({
|
|
85
|
+
* clientId: process.env.GITHUB_ID,
|
|
86
|
+
* clientSecret: process.env.GITHUB_SECRET,
|
|
87
|
+
* }),
|
|
88
|
+
* ],
|
|
89
|
+
* debug: false,
|
|
90
|
+
* }
|
|
91
|
+
*
|
|
92
|
+
* export const { GET, POST } = SolidAuth(authOpts)
|
|
93
|
+
* ```
|
|
94
|
+
*
|
|
95
|
+
* ## Getting the current session
|
|
96
|
+
*
|
|
97
|
+
* ```ts
|
|
98
|
+
* import { getSession } from "@auth/solid-start"
|
|
99
|
+
* import { createServerData$ } from "solid-start/server"
|
|
100
|
+
* import { authOpts } from "~/routes/api/auth/[...solidauth]"
|
|
101
|
+
*
|
|
102
|
+
* export const useSession = () => {
|
|
103
|
+
* return createServerData$(
|
|
104
|
+
* async (_, { request }) => {
|
|
105
|
+
* return await getSession(request, authOpts)
|
|
106
|
+
* },
|
|
107
|
+
* { key: () => ["auth_user"] }
|
|
108
|
+
* )
|
|
109
|
+
* }
|
|
110
|
+
*
|
|
111
|
+
* // useSession returns a resource:
|
|
112
|
+
* const session = useSession()
|
|
113
|
+
* const loading = session.loading
|
|
114
|
+
* const user = () => session()?.user
|
|
115
|
+
* ```
|
|
116
|
+
* ## Protected Routes
|
|
117
|
+
*
|
|
118
|
+
* ### When Using SSR
|
|
119
|
+
*
|
|
120
|
+
* When using SSR, I recommend creating a `Protected` component that will trigger suspense using the `Show` component. It should look like this:
|
|
121
|
+
*
|
|
122
|
+
*
|
|
123
|
+
* ```tsx
|
|
124
|
+
* // components/Protected.tsx
|
|
125
|
+
* import { type Session } from "@auth/core/types";
|
|
126
|
+
* import { getSession } from "@auth/solid-start";
|
|
127
|
+
* import { Component, Show } from "solid-js";
|
|
128
|
+
* import { useRouteData } from "solid-start";
|
|
129
|
+
* import { createServerData$, redirect } from "solid-start/server";
|
|
130
|
+
* import { authOpts } from "~/routes/api/auth/[...solidauth]";
|
|
131
|
+
*
|
|
132
|
+
* const Protected = (Comp: IProtectedComponent) => {
|
|
133
|
+
* const routeData = () => {
|
|
134
|
+
* return createServerData$(
|
|
135
|
+
* async (_, event) => {
|
|
136
|
+
* const session = await getSession(event.request, authOpts);
|
|
137
|
+
* if (!session || !session.user) {
|
|
138
|
+
* throw redirect("/");
|
|
139
|
+
* }
|
|
140
|
+
* return session;
|
|
141
|
+
* },
|
|
142
|
+
* { key: () => ["auth_user"] }
|
|
143
|
+
* );
|
|
144
|
+
* };
|
|
145
|
+
*
|
|
146
|
+
* return {
|
|
147
|
+
* routeData,
|
|
148
|
+
* Page: () => {
|
|
149
|
+
* const session = useRouteData<typeof routeData>();
|
|
150
|
+
* return (
|
|
151
|
+
* <Show when={session()} keyed>
|
|
152
|
+
* {(sess) => <Comp {...sess} />}
|
|
153
|
+
* </Show>
|
|
154
|
+
* );
|
|
155
|
+
* },
|
|
156
|
+
* };
|
|
157
|
+
* };
|
|
158
|
+
*
|
|
159
|
+
* type IProtectedComponent = Component<Session>;
|
|
160
|
+
*
|
|
161
|
+
* export default Protected;
|
|
162
|
+
* ```
|
|
163
|
+
*
|
|
164
|
+
* It can be used like this:
|
|
165
|
+
*
|
|
166
|
+
*
|
|
167
|
+
* ```tsx
|
|
168
|
+
* // routes/protected.tsx
|
|
169
|
+
* import Protected from "~/components/Protected";
|
|
170
|
+
*
|
|
171
|
+
* export const { routeData, Page } = Protected((session) => {
|
|
172
|
+
* return (
|
|
173
|
+
* <main class="flex flex-col gap-2 items-center">
|
|
174
|
+
* <h1>This is a protected route</h1>
|
|
175
|
+
* </main>
|
|
176
|
+
* );
|
|
177
|
+
* });
|
|
178
|
+
*
|
|
179
|
+
* export default Page;
|
|
180
|
+
* ```
|
|
181
|
+
*
|
|
182
|
+
* ### When Using CSR
|
|
183
|
+
*
|
|
184
|
+
* When using CSR, the `Protected` component will not work as expected and will cause the screen to flash, so I had to come up with a tricky solution, we will use a Solid-Start middleware:
|
|
185
|
+
*
|
|
186
|
+
* ```tsx
|
|
187
|
+
* // entry-server.tsx
|
|
188
|
+
* import { Session } from "@auth/core";
|
|
189
|
+
* import { getSession } from "@auth/solid-start";
|
|
190
|
+
* import { redirect } from "solid-start";
|
|
191
|
+
* import {
|
|
192
|
+
* StartServer,
|
|
193
|
+
* createHandler,
|
|
194
|
+
* renderAsync,
|
|
195
|
+
* } from "solid-start/entry-server";
|
|
196
|
+
* import { authOpts } from "./routes/api/auth/[...solidauth]";
|
|
197
|
+
*
|
|
198
|
+
* const protectedPaths = ["/protected"]; // add any route you wish in here
|
|
199
|
+
*
|
|
200
|
+
* export default createHandler(
|
|
201
|
+
* ({ forward }) => {
|
|
202
|
+
* return async (event) => {
|
|
203
|
+
* if (protectedPaths.includes(new URL(event.request.url).pathname)) {
|
|
204
|
+
* const session = await getSession(event.request, authOpts);
|
|
205
|
+
* if (!session) {
|
|
206
|
+
* return redirect("/");
|
|
207
|
+
* }
|
|
208
|
+
* }
|
|
209
|
+
* return forward(event);
|
|
210
|
+
* };
|
|
211
|
+
* },
|
|
212
|
+
* renderAsync((event) => <StartServer event={event} />)
|
|
213
|
+
* );
|
|
214
|
+
* ```
|
|
215
|
+
*
|
|
216
|
+
* And now you can easily create a protected route:
|
|
217
|
+
*
|
|
218
|
+
*
|
|
219
|
+
* ```tsx
|
|
220
|
+
* // routes/protected.tsx
|
|
221
|
+
* export default () => {
|
|
222
|
+
* return (
|
|
223
|
+
* <main class="flex flex-col gap-2 items-center">
|
|
224
|
+
* <h1>This is a protected route</h1>
|
|
225
|
+
* </main>
|
|
226
|
+
* );
|
|
227
|
+
* };
|
|
228
|
+
* ```
|
|
229
|
+
*
|
|
230
|
+
* :::note
|
|
231
|
+
* The CSR method should also work when using SSR, the SSR method shouldn't work when using CSR
|
|
232
|
+
* :::
|
|
233
|
+
*
|
|
234
|
+
*/
|
|
39
235
|
export function SolidAuth(config: SolidAuthConfig) {
|
|
40
236
|
const { prefix = "/api/auth", ...authOptions } = config
|
|
41
237
|
authOptions.secret ??= process.env.AUTH_SECRET
|