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
import { getCookie, setCookie } from "npm:hono/cookie";
import { Lucia } from "npm:lucia@3.0.1";
import { ValTownAdapter } from "https://esm.town/v/yawnxyz/luciaValtownSqlite";
import { generateState, OAuth2RequestError, generateCodeVerifier, GitHub, Google } from "npm:arctic";
class LuciaAuthMiddleware {
constructor(config = {}) {
this.config = {
userTable: "lucia_users_1",
sessionTable: "lucia_sessions_1",
adapter: ValTownAdapter,
sessionCookie: {
attributes: {
sameSite: "none",
},
},
getUserAttributes: (attributes) => ({
github_id: attributes.github_id,
username: attributes.username,
}),
services: {},
...config
};
this.adapter = new this.config.adapter({
userTable: this.config.userTable,
sessionTable: this.config.sessionTable
});
this.lucia = new Lucia(this.adapter, {
sessionCookie: this.config.sessionCookie,
getUserAttributes: this.config.getUserAttributes,
});
this.initializeOAuthServices();
}
initializeOAuthServices() {
this.oauthServices = {};
for (const [service, config] of Object.entries(this.config.services)) {
switch (service) {
case 'github':
this.oauthServices.github = new GitHub(config.clientId, config.clientSecret);
break;
case 'google':
this.oauthServices.google = new Google(config.clientId, config.clientSecret, config.redirectUri);
break;
// Add more services here as needed
}
}
}
middleware() {
return async (c, next) => {
const sessionId = getCookie(c, this.lucia.sessionCookieName) ?? null;
if (!sessionId) {
c.set("user", null);
c.set("session", null);
return next();
}
const { session, user } = await this.lucia.validateSession(sessionId);
if (session && session.fresh) {
c.header("Set-Cookie", this.lucia.createSessionCookie(session.id).serialize(), {
append: true,
});
}
if (!session) {
c.header("Set-Cookie", this.lucia.createBlankSessionCookie().serialize(), {
append: true,
});
}
c.set("user", user);
c.set("session", session);
return next();
};
}
setupRoutes(app) {
// Signup route
app.get("/auth/signup", (c) => {
return c.html(`
<form method="post" action="/auth/signup">
<input name="username" placeholder="Username" required />
<input name="password" type="password" placeholder="Password" required />
<button type="submit">Sign up</button>
</form>
`);
});
app.post("/auth/signup", async (c) => {
const { username, password } = await c.req.parseBody();
if (typeof username !== "string" || typeof password !== "string") {
return c.text("Invalid input", 400);
}
try {
const userId = await this.adapter.createUser({ username, password });
const session = await this.lucia.createSession(userId, {});
c.header("Set-Cookie", this.lucia.createSessionCookie(session.id).serialize(), { append: true });
return c.redirect("/");
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Comments
Nobody has commented on this val yet: be the first!
September 3, 2024