mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 13:40:46 +00:00
101 lines
2.5 KiB
TypeScript
101 lines
2.5 KiB
TypeScript
import { jwtVerify } from "jose";
|
|
import { z } from "zod";
|
|
import {
|
|
TokenPayload,
|
|
TokenPayloadSchema,
|
|
UserMeResponse,
|
|
UserMeResponseSchema,
|
|
} from "../core/ApiSchemas";
|
|
import { GameEnv, ServerConfig } from "../core/configuration/Config";
|
|
import { PersistentIdSchema } from "../core/Schemas";
|
|
|
|
type TokenVerificationResult =
|
|
| {
|
|
type: "success";
|
|
persistentId: string;
|
|
claims: TokenPayload | null;
|
|
}
|
|
| { type: "error"; message: string };
|
|
|
|
export async function verifyClientToken(
|
|
token: string,
|
|
config: ServerConfig,
|
|
): Promise<TokenVerificationResult> {
|
|
if (PersistentIdSchema.safeParse(token).success) {
|
|
if (config.env() === GameEnv.Dev) {
|
|
return { type: "success", persistentId: token, claims: null };
|
|
} else {
|
|
return {
|
|
type: "error",
|
|
message: "persistent ID not allowed in production",
|
|
};
|
|
}
|
|
}
|
|
try {
|
|
const issuer = config.jwtIssuer();
|
|
const audience = config.jwtAudience();
|
|
const key = await config.jwkPublicKey();
|
|
const { payload } = await jwtVerify(token, key, {
|
|
algorithms: ["EdDSA"],
|
|
issuer,
|
|
audience,
|
|
});
|
|
const result = TokenPayloadSchema.safeParse(payload);
|
|
if (!result.success) {
|
|
return {
|
|
type: "error",
|
|
message: z.prettifyError(result.error),
|
|
};
|
|
}
|
|
const claims = result.data;
|
|
const persistentId = claims.sub;
|
|
return { type: "success", persistentId, claims };
|
|
} catch (e) {
|
|
const message =
|
|
e instanceof Error
|
|
? e.message
|
|
: typeof e === "string"
|
|
? e
|
|
: "An unknown error occurred";
|
|
|
|
return { type: "error", message };
|
|
}
|
|
}
|
|
|
|
export async function getUserMe(
|
|
token: string,
|
|
config: ServerConfig,
|
|
): Promise<
|
|
| { type: "success"; response: UserMeResponse }
|
|
| { type: "error"; message: string }
|
|
> {
|
|
try {
|
|
// Get the user object
|
|
const response = await fetch(config.jwtIssuer() + "/users/@me", {
|
|
headers: {
|
|
authorization: `Bearer ${token}`,
|
|
},
|
|
});
|
|
if (response.status !== 200) {
|
|
return {
|
|
type: "error",
|
|
message: `Failed to fetch user me: ${response.statusText}`,
|
|
};
|
|
}
|
|
const body = await response.json();
|
|
const result = UserMeResponseSchema.safeParse(body);
|
|
if (!result.success) {
|
|
return {
|
|
type: "error",
|
|
message: `Invalid response: ${z.prettifyError(result.error)}`,
|
|
};
|
|
}
|
|
return { type: "success", response: result.data };
|
|
} catch (e) {
|
|
return {
|
|
type: "error",
|
|
message: `Failed to fetch user me: ${e}`,
|
|
};
|
|
}
|
|
}
|