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
107
108
109
110
111
112
113
|
import type { Session } from "@remix-run/server-runtime";
import { jwtDecode } from "jwt-decode";
import { Authenticator } from "remix-auth";
import { FormStrategy } from "remix-auth-form";
import { apiPostLogin } from "./api/client";
import { components } from "./api/schema";
import { sessionStorage } from "./session";
export const authenticator = new Authenticator<string>(sessionStorage);
async function login(username: string, password: string): Promise<string> {
return (await apiPostLogin(username, password)).token;
}
authenticator.use(
new FormStrategy(async ({ form }) => {
const username = String(form.get("username"));
const password = String(form.get("password"));
return await login(username, password);
}),
"default",
);
export type User = components["schemas"]["User"];
export async function isAuthenticated(
request: Request | Session,
options?: {
successRedirect?: never;
failureRedirect?: never;
headers?: never;
},
): Promise<{ user: User; token: string } | null>;
export async function isAuthenticated(
request: Request | Session,
options: {
successRedirect: string;
failureRedirect?: never;
headers?: HeadersInit;
},
): Promise<null>;
export async function isAuthenticated(
request: Request | Session,
options: {
successRedirect?: never;
failureRedirect: string;
headers?: HeadersInit;
},
): Promise<{ user: User; token: string }>;
export async function isAuthenticated(
request: Request | Session,
options: {
successRedirect: string;
failureRedirect: string;
headers?: HeadersInit;
},
): Promise<null>;
export async function isAuthenticated(
request: Request | Session,
options:
| {
successRedirect?: never;
failureRedirect?: never;
headers?: never;
}
| {
successRedirect: string;
failureRedirect?: never;
headers?: HeadersInit;
}
| {
successRedirect?: never;
failureRedirect: string;
headers?: HeadersInit;
}
| {
successRedirect: string;
failureRedirect: string;
headers?: HeadersInit;
} = {},
): Promise<{ user: User; token: string } | null> {
// This function's signature should be compatible with `authenticator.isAuthenticated` but TypeScript does not infer it correctly.
let jwt;
const { successRedirect, failureRedirect, headers } = options;
if (successRedirect && failureRedirect) {
jwt = await authenticator.isAuthenticated(request, {
successRedirect,
failureRedirect,
headers,
});
} else if (!successRedirect && failureRedirect) {
jwt = await authenticator.isAuthenticated(request, {
failureRedirect,
headers,
});
} else if (successRedirect && !failureRedirect) {
jwt = await authenticator.isAuthenticated(request, {
successRedirect,
headers,
});
} else {
jwt = await authenticator.isAuthenticated(request);
}
if (!jwt) {
return null;
}
const user = jwtDecode<User>(jwt);
return {
user,
token: jwt,
};
}
|