mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 16:38:19 +01:00
fix(api): 🐛 Fix OIDC
This commit is contained in:
parent
29d7b09677
commit
ff43b19122
|
|
@ -2,7 +2,7 @@ import { randomBytes } from "node:crypto";
|
||||||
import { applyConfig, handleZodError } from "@api";
|
import { applyConfig, handleZodError } from "@api";
|
||||||
import { oauthRedirectUri } from "@constants";
|
import { oauthRedirectUri } from "@constants";
|
||||||
import { zValidator } from "@hono/zod-validator";
|
import { zValidator } from "@hono/zod-validator";
|
||||||
import { response } from "@response";
|
import { errorResponse, response } from "@response";
|
||||||
import type { Hono } from "hono";
|
import type { Hono } from "hono";
|
||||||
import {
|
import {
|
||||||
authorizationCodeGrantRequest,
|
authorizationCodeGrantRequest,
|
||||||
|
|
@ -22,6 +22,7 @@ import { db } from "~drizzle/db";
|
||||||
import { Tokens } from "~drizzle/schema";
|
import { Tokens } from "~drizzle/schema";
|
||||||
import { config } from "~packages/config-manager";
|
import { config } from "~packages/config-manager";
|
||||||
import { User } from "~packages/database-interface/user";
|
import { User } from "~packages/database-interface/user";
|
||||||
|
import { SignJWT } from "jose";
|
||||||
|
|
||||||
export const meta = applyConfig({
|
export const meta = applyConfig({
|
||||||
allowedMethods: ["GET"],
|
allowedMethods: ["GET"],
|
||||||
|
|
@ -122,13 +123,18 @@ export default (app: Hono) =>
|
||||||
|
|
||||||
if (isOAuth2Error(parameters)) {
|
if (isOAuth2Error(parameters)) {
|
||||||
return returnError(
|
return returnError(
|
||||||
context.req.query(),
|
{
|
||||||
|
redirect_uri: flow.application?.redirectUri,
|
||||||
|
client_id: flow.application?.clientId,
|
||||||
|
response_type: "code",
|
||||||
|
scope: flow.application?.scopes,
|
||||||
|
},
|
||||||
parameters.error,
|
parameters.error,
|
||||||
parameters.error_description || "",
|
parameters.error_description || "",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await authorizationCodeGrantRequest(
|
const oidcResponse = await authorizationCodeGrantRequest(
|
||||||
authServer,
|
authServer,
|
||||||
{
|
{
|
||||||
client_id: issuer.client_id,
|
client_id: issuer.client_id,
|
||||||
|
|
@ -145,12 +151,17 @@ export default (app: Hono) =>
|
||||||
client_id: issuer.client_id,
|
client_id: issuer.client_id,
|
||||||
client_secret: issuer.client_secret,
|
client_secret: issuer.client_secret,
|
||||||
},
|
},
|
||||||
response,
|
oidcResponse,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isOAuth2Error(result)) {
|
if (isOAuth2Error(result)) {
|
||||||
return returnError(
|
return returnError(
|
||||||
context.req.query(),
|
{
|
||||||
|
redirect_uri: flow.application?.redirectUri,
|
||||||
|
client_id: flow.application?.clientId,
|
||||||
|
response_type: "code",
|
||||||
|
scope: flow.application?.scopes,
|
||||||
|
},
|
||||||
result.error,
|
result.error,
|
||||||
result.error_description || "",
|
result.error_description || "",
|
||||||
);
|
);
|
||||||
|
|
@ -194,7 +205,12 @@ export default (app: Hono) =>
|
||||||
|
|
||||||
if (!userId) {
|
if (!userId) {
|
||||||
return returnError(
|
return returnError(
|
||||||
context.req.query(),
|
{
|
||||||
|
redirect_uri: flow.application?.redirectUri,
|
||||||
|
client_id: flow.application?.clientId,
|
||||||
|
response_type: "code",
|
||||||
|
scope: flow.application?.scopes,
|
||||||
|
},
|
||||||
"invalid_request",
|
"invalid_request",
|
||||||
"No user found with that account",
|
"No user found with that account",
|
||||||
);
|
);
|
||||||
|
|
@ -204,18 +220,19 @@ export default (app: Hono) =>
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return returnError(
|
return returnError(
|
||||||
context.req.query(),
|
{
|
||||||
|
redirect_uri: flow.application?.redirectUri,
|
||||||
|
client_id: flow.application?.clientId,
|
||||||
|
response_type: "code",
|
||||||
|
scope: flow.application?.scopes,
|
||||||
|
},
|
||||||
"invalid_request",
|
"invalid_request",
|
||||||
"No user found with that account",
|
"No user found with that account",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!flow.application)
|
if (!flow.application)
|
||||||
return returnError(
|
return errorResponse("Application not found", 500);
|
||||||
context.req.query(),
|
|
||||||
"invalid_request",
|
|
||||||
"No application found",
|
|
||||||
);
|
|
||||||
|
|
||||||
const code = randomBytes(32).toString("hex");
|
const code = randomBytes(32).toString("hex");
|
||||||
|
|
||||||
|
|
@ -228,8 +245,30 @@ export default (app: Hono) =>
|
||||||
applicationId: flow.application.id,
|
applicationId: flow.application.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Try and import the key
|
||||||
|
const privateKey = await crypto.subtle.importKey(
|
||||||
|
"pkcs8",
|
||||||
|
Buffer.from(config.oidc.jwt_key.split(";")[0], "base64"),
|
||||||
|
"Ed25519",
|
||||||
|
false,
|
||||||
|
["sign"],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Generate JWT
|
||||||
|
const jwt = await new SignJWT({
|
||||||
|
sub: user.id,
|
||||||
|
iss: new URL(config.http.base_url).origin,
|
||||||
|
aud: flow.application.clientId,
|
||||||
|
exp: Math.floor(Date.now() / 1000) + 60 * 60,
|
||||||
|
iat: Math.floor(Date.now() / 1000),
|
||||||
|
nbf: Math.floor(Date.now() / 1000),
|
||||||
|
})
|
||||||
|
.setProtectedHeader({ alg: "EdDSA" })
|
||||||
|
.sign(privateKey);
|
||||||
|
|
||||||
// Redirect back to application
|
// Redirect back to application
|
||||||
return Response.redirect(
|
return response(null, 302, {
|
||||||
|
Location: new URL(
|
||||||
`/oauth/consent?${new URLSearchParams({
|
`/oauth/consent?${new URLSearchParams({
|
||||||
redirect_uri: flow.application.redirectUri,
|
redirect_uri: flow.application.redirectUri,
|
||||||
code,
|
code,
|
||||||
|
|
@ -237,8 +276,14 @@ export default (app: Hono) =>
|
||||||
application: flow.application.name,
|
application: flow.application.name,
|
||||||
website: flow.application.website ?? "",
|
website: flow.application.website ?? "",
|
||||||
scope: flow.application.scopes,
|
scope: flow.application.scopes,
|
||||||
|
response_type: "code",
|
||||||
}).toString()}`,
|
}).toString()}`,
|
||||||
302,
|
config.http.base_url,
|
||||||
);
|
).toString(),
|
||||||
|
// Set cookie with JWT
|
||||||
|
"Set-Cookie": `jwt=${jwt}; HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age=${
|
||||||
|
60 * 60
|
||||||
|
}`,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue