Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
mirai2k committed Nov 19, 2024
1 parent 4218a13 commit f87981a
Show file tree
Hide file tree
Showing 18 changed files with 192 additions and 241 deletions.
27 changes: 0 additions & 27 deletions apps/auth-service/src/handlers/intents/create.ts

This file was deleted.

60 changes: 0 additions & 60 deletions apps/auth-service/src/handlers/intents/get.ts

This file was deleted.

74 changes: 0 additions & 74 deletions apps/auth-service/src/handlers/intents/populate.ts

This file was deleted.

130 changes: 111 additions & 19 deletions apps/auth-service/src/server.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,30 @@
import "dotenv/config";
import type { ZitatelUserInfo } from "@codemod-com/api-types";
import { decodeJwt, jwtVerificationResult } from "@codemod-com/auth";
import { prisma } from "@codemod-com/database";
import { isNeitherNullNorUndefined } from "@codemod-com/utilities";

import cors, { type FastifyCorsOptions } from "@fastify/cors";
import fastifyRateLimit from "@fastify/rate-limit";
import Fastify, { type FastifyPluginCallback } from "fastify";
import Fastify, {
type FastifyRequest,
type FastifyPluginCallback,
} from "fastify";

import { decodeJwt, jwtVerificationResult } from "@codemod-com/auth";
import { isNeitherNullNorUndefined } from "@codemod-com/utilities";
import axios from "axios";
import { environment } from "./util.js";

type ZitadelUserInfo = {
sub: string;
name: string;
given_name: string;
family_name: string;
locale: string;
updated_at: number;
preferred_username: string;
email: string;
email_verified: boolean;
};

export const initApp = async (toRegister: FastifyPluginCallback[]) => {
const { PORT: port } = environment;
if (Number.isNaN(port)) {
Expand Down Expand Up @@ -136,26 +151,27 @@ const routes: FastifyPluginCallback = (instance, _opts, done) => {
}

try {
const { data } = await axios.get<ZitatelUserInfo | object>(
const { data: user } = await axios.get<ZitadelUserInfo>(
`${process.env.ZITADEL_URL}/oidc/v1/userinfo`,
{
headers: { Authorization: `Bearer ${jwtToken}` },
timeout: 5000,
},
);

if (!("name" in data)) {
return null;
if (!user.sub) {
return reply.status(401).send({ message: "User was not found" });
}

return data.preferred_username;
return reply.status(200).send({ id: user.sub });
} catch (err) {
return null;
return reply.status(500).send({ message: "Internal server error" });
}
});

instance.get("/userData", async (request, reply) => {
const authHeader = request.headers.authorization;

const jwtToken =
typeof authHeader === "string"
? authHeader.replace("Bearer ", "")
Expand All @@ -172,11 +188,12 @@ const routes: FastifyPluginCallback = (instance, _opts, done) => {
}

const kid = parsedToken.header.kid;

if (!kid) {
return reply.status(401).send({ message: "No kid in JWT token" });
}

const result = jwtVerificationResult(jwtToken);
const result = await jwtVerificationResult(jwtToken);

if (!result) {
return reply
Expand All @@ -185,22 +202,22 @@ const routes: FastifyPluginCallback = (instance, _opts, done) => {
}

try {
const { data } = await axios.get<ZitatelUserInfo | object>(
const { data: user } = await axios.get<ZitadelUserInfo>(
`${process.env.ZITADEL_URL}/oidc/v1/userinfo`,
{
headers: { Authorization: `Bearer ${jwtToken}` },
timeout: 5000,
},
);

if (!("name" in data)) {
return null;
if (!user.sub) {
return reply.status(401).send({ message: "User was not found" });
}

const organizations = await prisma.organization.findMany({
where: {
users: {
hasSome: [data.preferred_username],
has: user.preferred_username,
},
},
});
Expand All @@ -209,20 +226,95 @@ const routes: FastifyPluginCallback = (instance, _opts, done) => {
...organizations.map(({ slug }) => slug),
].filter(isNeitherNullNorUndefined);

if (data.preferred_username) {
allowedNamespaces.unshift(data.preferred_username);
if (user.preferred_username) {
allowedNamespaces.unshift(user.preferred_username);

if (environment.VERIFIED_PUBLISHERS.includes(data.preferred_username)) {
if (environment.VERIFIED_PUBLISHERS.includes(user.preferred_username)) {
allowedNamespaces.push("codemod-com");
}
}

return data as ZitatelUserInfo;
return reply.status(200).send({
user: {
id: user.sub,
username: user.preferred_username,
firstName: user.given_name,
lastName: user.family_name,
locale: user.locale,
email: user.email,
emailVerified: user.email_verified,
},
organizations,
allowedNamespaces,
});
} catch (err) {
return null;
return reply.status(500).send({ message: "Internal server error" });
}
});

interface RevokeTokenParams {
client_id: string;
}

instance.delete<{ Params: RevokeTokenParams }>(
"/revokeToken",
async (request: FastifyRequest<{ Params: RevokeTokenParams }>, reply) => {
const authHeader = request.headers.authorization;

const jwtToken =
typeof authHeader === "string"
? authHeader.replace("Bearer ", "")
: undefined;

if (!jwtToken) {
return reply.status(401).send({ message: "No JWT token" });
}

const parsedToken = decodeJwt(jwtToken);

if (!parsedToken) {
return reply.status(401).send({ message: "Invalid JWT token" });
}

const kid = parsedToken.header.kid;

if (!kid) {
return reply.status(401).send({ message: "No kid in JWT token" });
}

const result = await jwtVerificationResult(jwtToken);

if (!result) {
return reply
.status(401)
.send({ message: "JWT token verification failed" });
}

const clientId = request.params.client_id;

if (!clientId) {
return reply
.status(401)
.send({ success: false, error: "Invalid client ID" });
}

try {
await axios.get(`${process.env.ZITADEL_URL}/v2/revoke`, {
headers: { Authorization: `Bearer ${jwtToken}` },
params: { client_id: clientId, token: jwtToken },
timeout: 5000,
});
} catch (err) {
console.error("Failed to revoke session:\n", err);
return reply
.status(500)
.send({ success: false, error: "Failed to revoke session" });
}

return reply.status(200).send({ success: true });
},
);

done();
};

Expand Down
5 changes: 2 additions & 3 deletions apps/backend/src/publishHandler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ import { environment } from "./util.js";
const GET_USER_RETURN = {
user: {
username: "username",
primaryEmailAddressId: "123",
emailAddresses: [{ id: "123", emailAddress: "[email protected]" }],
email: "[email protected]",
firstName: "John",
lastName: "Doe",
},
Expand Down Expand Up @@ -210,7 +209,7 @@ describe("/publish route", async () => {
author: {
username: GET_USER_RETURN.user.username,
name: `${GET_USER_RETURN.user.firstName} ${GET_USER_RETURN.user.lastName}`,
email: GET_USER_RETURN.user.emailAddresses[0]?.emailAddress,
email: GET_USER_RETURN.user.email,
},
},
);
Expand Down
Loading

0 comments on commit f87981a

Please sign in to comment.