M2M Api
This commit is contained in:
63
backend/src/routes/internal/auth.m2m.ts
Normal file
63
backend/src/routes/internal/auth.m2m.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { FastifyInstance } from "fastify"
|
||||
import jwt from "jsonwebtoken"
|
||||
import { and, eq } from "drizzle-orm"
|
||||
import { authTenantUsers } from "../../../db/schema"
|
||||
import { secrets } from "../../utils/secrets"
|
||||
|
||||
export default async function authM2mInternalRoutes(server: FastifyInstance) {
|
||||
server.post("/auth/m2m/token", {
|
||||
schema: {
|
||||
tags: ["Auth"],
|
||||
summary: "Exchange M2M API key for a short-lived JWT",
|
||||
body: {
|
||||
type: "object",
|
||||
properties: {
|
||||
expires_in_seconds: { type: "number" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}, async (req, reply) => {
|
||||
try {
|
||||
if (!req.user?.user_id || !req.user?.tenant_id || !req.user?.email) {
|
||||
return reply.code(401).send({ error: "Unauthorized" })
|
||||
}
|
||||
|
||||
const membership = await server.db
|
||||
.select()
|
||||
.from(authTenantUsers)
|
||||
.where(and(
|
||||
eq(authTenantUsers.user_id, req.user.user_id),
|
||||
eq(authTenantUsers.tenant_id, Number(req.user.tenant_id))
|
||||
))
|
||||
.limit(1)
|
||||
|
||||
if (!membership[0]) {
|
||||
return reply.code(403).send({ error: "User is not assigned to tenant" })
|
||||
}
|
||||
|
||||
const requestedTtl = Number((req.body as any)?.expires_in_seconds ?? 900)
|
||||
const ttlSeconds = Math.min(3600, Math.max(60, requestedTtl))
|
||||
|
||||
const token = jwt.sign(
|
||||
{
|
||||
user_id: req.user.user_id,
|
||||
email: req.user.email,
|
||||
tenant_id: req.user.tenant_id,
|
||||
},
|
||||
secrets.JWT_SECRET!,
|
||||
{ expiresIn: ttlSeconds }
|
||||
)
|
||||
|
||||
return {
|
||||
token_type: "Bearer",
|
||||
access_token: token,
|
||||
expires_in_seconds: ttlSeconds,
|
||||
user_id: req.user.user_id,
|
||||
tenant_id: req.user.tenant_id
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("POST /internal/auth/m2m/token ERROR:", err)
|
||||
return reply.code(500).send({ error: "Internal Server Error" })
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user