Got Authorization flow working (Untested)

This commit is contained in:
2026-01-25 16:53:18 -06:00
parent d96f18e6cf
commit 8ee7dc15e5
8 changed files with 174 additions and 21 deletions
+7 -16
View File
@@ -4,12 +4,10 @@ import * as msal from "@azure/msal-node";
import { msalClient } from "../../constants";
import { users } from "../../managers/users";
/* /v1/authRedirect */
/* /v1/auth/redirect */
export default createRoute("get", ["/"], async (c) => {
c.status(200);
console.log("Query", c.req.query());
const tokenRequest: msal.AuthorizationCodeRequest = {
code: c.req.query().code as string,
scopes: ["user.read"],
@@ -20,17 +18,10 @@ export default createRoute("get", ["/"], async (c) => {
await users.authenticate(authResult);
// This closes the window because duh
return c.html(`
<script>
window.close();
</script>
`);
/* return c.json({
status: 200,
message: "Auth Redirect Endpoint",
data: authResult,
successful: true,
}); */
return c.json({
status: 200,
message: "Auth Redirect Endpoint",
data: authResult,
successful: true,
});
});
+26
View File
@@ -0,0 +1,26 @@
import { Hono } from "hono/tiny";
import { createRoute } from "../../modules/api-utils/createRoute";
import { sessions } from "../../managers/sessions";
/* /v1/auth/refresh */
export default createRoute("post", ["/"], async (c) => {
c.status(201);
const refreshToken = c.req.header("x-refresh-token") || "";
const session = await sessions.fetch({
refreshToken: refreshToken,
});
const newAccessToken = await session.refresh(refreshToken);
return c.json({
status: 201,
message: "Token refreshed successfully!",
data: {
accessToken: newAccessToken,
refreshToken,
},
successful: true,
});
});
+80
View File
@@ -0,0 +1,80 @@
import { Context, Env, MiddlewareHandler } from "hono";
import AuthorizationError from "../../Errors/AuthorizationError";
import { sessions } from "../../managers/sessions";
import { Variables } from "../../types/HonoTypes";
import GenericError from "../../Errors/GenericError";
import { events } from "../../modules/globalEvents";
/**
* Authorization Middleware
*
* This middleware will do all of the authorization for all the routes that may need authorization.
* It will check which auth type is being used and pull the correct credentials from said auth type and
* supply them as a variable to the route. If there is an error thrown at any point in this middleware, it
* will hault and will not proceed to the route handler.
*
* Eventually this method will analyze roles and permissions and supply those as objects to the route handler.
*
* ## Auth Types
* - Bearer: Access Token for user authentication
* - Key: API Key
*
* @param ctx - Hono Context Object
* @param next - Move onto the handler
*/
export const authMiddleware = (permParams?: {
permissions?: string[];
scopes?: string[];
forbiddenAuthTypes?: string[];
}): MiddlewareHandler<{
Variables: Variables;
}> => {
return async (ctx, next) => {
const authorization = ctx.req.header()["authorization"];
if (!authorization)
throw new AuthorizationError("Missing 'authorization' header.");
const components = authorization.match(
/^(Bearer|Key)\s([a-zA-Z0-9-_]+\.[a-zA-Z0-9-_]+\.[a-zA-Z0-9-_]+)$/,
);
if (!components)
throw new AuthorizationError(
"Invalid or malformed authorization header...",
);
const authType: string = components[1] ?? "";
const authValue: string = components[2] ?? "";
if (permParams?.forbiddenAuthTypes?.includes(authType))
throw new GenericError({
name: "NonpermittedAuthType",
message:
"The authorization method you are using is not permitted for this API request.",
cause: `Type '${authType}' is not permitted.`,
status: 403,
});
if (authType) {
const session = await sessions.fetch({ accessToken: authValue });
const user = await session.fetchUser();
ctx.set("user", user);
if (
permParams?.permissions &&
permParams?.permissions.length > 0 &&
(
await Promise.all(
permParams?.permissions.map((p) => user.hasPermission(p)),
)
).includes(false)
)
throw new GenericError({
name: "InsufficentPermission",
message: "You do not have sufficent permissions to do this.",
status: 403,
});
}
await next();
};
};
+10
View File
@@ -2,6 +2,8 @@ import { readFileSync } from "fs";
import { PrismaPg } from "@prisma/adapter-pg";
import { Prisma, PrismaClient } from "../generated/prisma/client";
import * as msal from "@azure/msal-node";
import { Server } from "socket.io";
import { Server as Engine } from "@socket.io/bun-engine";
const connectionString = `${process.env.DATABASE_URL}`;
const adapter = new PrismaPg({ connectionString });
@@ -44,3 +46,11 @@ const msalConfig: msal.Configuration = {
// MSAL Client Instance
export const msalClient = new msal.ConfidentialClientApplication(msalConfig);
// Socket.io
const io = new Server();
const engine = new Engine();
io.bind(engine);
export { io, engine };
+12 -4
View File
@@ -1,7 +1,15 @@
import app from "./api/server";
import { PORT } from "./constants";
import { engine, PORT } from "./constants";
Bun.serve({
port: PORT,
fetch: app.fetch
});
port: PORT,
fetch: (req, server) => {
const url = new URL(req.url);
if (url.pathname.startsWith("/socket.io/")) {
return engine.handleRequest(req, server as any);
}
return app.fetch(req, server);
},
});
+3 -1
View File
@@ -1,3 +1,5 @@
import UserController from "../controllers/UserController";
export type Variables = {
foo: "bar"
user: UserController;
};