feat(auth): working plugin
This commit is contained in:
parent
c545499c73
commit
ddde700494
5 changed files with 140 additions and 31 deletions
|
|
@ -9,7 +9,9 @@
|
|||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@fastify/cookie": "^11.0.2",
|
||||
"@fastify/jwt": "^9.1.0",
|
||||
"@sinclair/typebox": "^0.34.40",
|
||||
"@types/bcrypt": "^6.0.0",
|
||||
"bcrypt": "^6.0.0",
|
||||
"better-sqlite3": "^11.10.0",
|
||||
|
|
@ -17,7 +19,6 @@
|
|||
"fastify-plugin": "^5.0.1",
|
||||
"joi": "^18.0.0",
|
||||
"otp": "^1.1.2",
|
||||
"rfc4648": "^1.5.4",
|
||||
"uuidv7": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
//! Anything in this file shouldn't be used...
|
||||
//!
|
||||
//! This file is here because it is easier to share code in here.
|
||||
|
||||
import type { Database } from "@shared/database";
|
||||
import type { UserId } from "../database/mixin/user";
|
||||
import OTP, * as OtpModules from "otp";
|
||||
|
||||
let secret = "JKZSGXRCBP3UHOFVDVLYQ3W43IZH3D76";
|
||||
let otp = new OTP({ secret, name: "test" });
|
||||
|
||||
console.log(`${otp.totpURL}`);
|
||||
console.log(new URL(otp.totpURL));
|
||||
setInterval(() => {
|
||||
console.log(`${otp.totp(Date.now())}`);
|
||||
}, 999);
|
||||
|
|
@ -1,10 +1,26 @@
|
|||
import fastifyJwt from "@fastify/jwt";
|
||||
import { FastifyPluginAsync } from "fastify";
|
||||
import fp from 'fastify-plugin'
|
||||
import { user } from "@shared/database"
|
||||
import OTP from "otp";
|
||||
import fastifyJwt from "@fastify/jwt";
|
||||
import fp from 'fastify-plugin'
|
||||
import { FastifyPluginAsync, FastifyRequest } from "fastify";
|
||||
import { Static, Type } from "@sinclair/typebox"
|
||||
import { useDatabase, user } from "@shared/database"
|
||||
import cookie from "@fastify/cookie";
|
||||
|
||||
|
||||
const kRouteAuthDone = Symbol('shared-route-auth-done');
|
||||
|
||||
declare module 'fastify' {
|
||||
export interface FastifyInstance {
|
||||
signJwt: (kind: "auth" | "otp", who: string) => string;
|
||||
}
|
||||
export interface FastifyRequest {
|
||||
authUser?: user.UserId;
|
||||
}
|
||||
export interface FastifyContextConfig {
|
||||
requireAuth?: boolean,
|
||||
}
|
||||
}
|
||||
|
||||
export const Otp = OTP;
|
||||
export const jwtPlugin = fp<FastifyPluginAsync>(async (fastify, _opts) => {
|
||||
let env = process.env.JWT_SECRET;
|
||||
|
|
@ -14,14 +30,38 @@ export const jwtPlugin = fp<FastifyPluginAsync>(async (fastify, _opts) => {
|
|||
secret: env,
|
||||
decode: { complete: false },
|
||||
});
|
||||
void fastify.decorate("signJwt", (kind, who) => fastify.jwt.sign({ kind, who, createdAt: Date.now() }))
|
||||
});
|
||||
|
||||
export type JwtClaims = {
|
||||
id: user.UserId,
|
||||
};
|
||||
export const JwtType = Type.Object({
|
||||
kind: Type.Union([
|
||||
Type.Const("otp", { description: "the token is only valid for otp call" }),
|
||||
Type.Const("auth", { description: "the token is valid for authentication" })
|
||||
]),
|
||||
who: Type.String({ description: "the login of the user" }),
|
||||
createdAt: Type.Integer({ description: "Unix timestamp of when the token as been created at" })
|
||||
});
|
||||
|
||||
export * as _inner from "./_inner.js";
|
||||
export type JwtType = Static<typeof JwtType>;
|
||||
|
||||
export const otpPlugin = fp<FastifyPluginAsync>(async (fastify, _opts) => {
|
||||
fastify.decorate('otp', {}, ["db"]);
|
||||
|
||||
export const authPlugin = fp<FastifyPluginAsync>(async (fastify, _opts) => {
|
||||
await fastify.register(useDatabase as any, {});
|
||||
await fastify.register(jwtPlugin as any, {});
|
||||
await fastify.register(cookie);
|
||||
fastify.addHook('onRoute', (routeOpts) => {
|
||||
if (routeOpts.config?.requireAuth) {
|
||||
routeOpts.preValidation = [function(req, res) {
|
||||
if (req.cookies.token === undefined)
|
||||
return res.clearCookie("token").send({ kind: "notLoggedIn", msg_key: "" })
|
||||
let tok = this.jwt.verify<JwtType>(req.cookies.token);
|
||||
if (tok.kind != "auth")
|
||||
return res.clearCookie("token").send({ kind: "notLoggedIn", msg_key: "" })
|
||||
let user = this.db.getUserFromName(tok.who);
|
||||
if (user === null)
|
||||
return res.clearCookie("token").send({ kind: "notLoggedIn", msg_key: "" })
|
||||
req.authUser = user.id;
|
||||
}, ...(routeOpts.preValidation as any || []),];
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue