fix: openid redirect auth query

This commit is contained in:
DecDuck
2025-05-15 21:22:24 +10:00
parent 8e3ae01a30
commit ce27f76856
4 changed files with 36 additions and 10 deletions
+5 -1
View File
@@ -1,10 +1,14 @@
<template> <template>
<div class="flex"> <div class="flex">
<a <a
href="/auth/oidc" :href="`/auth/oidc?redirect=${route.query.redirect ?? '/'}`"
class="transition rounded-md grow inline-flex items-center justify-center bg-white/10 px-3.5 py-2.5 text-sm font-semibold text-white shadow-xs hover:bg-white/20" class="transition rounded-md grow inline-flex items-center justify-center bg-white/10 px-3.5 py-2.5 text-sm font-semibold text-white shadow-xs hover:bg-white/20"
> >
Sign in with external provider &rarr; Sign in with external provider &rarr;
</a> </a>
</div> </div>
</template> </template>
<script setup lang="ts">
const route = useRoute();
</script>
+15 -3
View File
@@ -1,5 +1,6 @@
import { randomUUID } from "crypto"; import { randomUUID } from "crypto";
import prisma from "../db/database"; import prisma from "../db/database";
import type { User } from "~/prisma/client";
import { AuthMec } from "~/prisma/client"; import { AuthMec } from "~/prisma/client";
import objectHandler from "../objects"; import objectHandler from "../objects";
import type { Readable } from "stream"; import type { Readable } from "stream";
@@ -12,10 +13,15 @@ interface OIDCWellKnown {
scopes_supported: string[]; scopes_supported: string[];
} }
interface OIDCAuthSessionOptions {
redirect: string | undefined;
}
interface OIDCAuthSession { interface OIDCAuthSession {
redirectUrl: string; redirectUrl: string;
callbackUrl: string; callbackUrl: string;
state: string; state: string;
options: OIDCAuthSessionOptions;
} }
interface OIDCUserInfo { interface OIDCUserInfo {
@@ -132,7 +138,7 @@ export class OIDCManager {
}; };
} }
generateAuthSession(): OIDCAuthSession { generateAuthSession(options?: OIDCAuthSessionOptions): OIDCAuthSession {
const stateKey = randomUUID(); const stateKey = randomUUID();
const normalisedUrl = new URL( const normalisedUrl = new URL(
@@ -148,12 +154,16 @@ export class OIDCManager {
redirectUrl: finalUrl, redirectUrl: finalUrl,
callbackUrl: redirectUrl, callbackUrl: redirectUrl,
state: stateKey, state: stateKey,
options: options ?? { redirect: undefined },
}; };
this.signinStateTable[stateKey] = session; this.signinStateTable[stateKey] = session;
return session; return session;
} }
async authorize(code: string, state: string) { async authorize(
code: string,
state: string,
): Promise<{ user: User; options: OIDCAuthSessionOptions } | string> {
const session = this.signinStateTable[state]; const session = this.signinStateTable[state];
if (!session) return "Invalid state parameter"; if (!session) return "Invalid state parameter";
@@ -191,7 +201,9 @@ export class OIDCManager {
const user = await this.fetchOrCreateUser(userinfo); const user = await this.fetchOrCreateUser(userinfo);
return user; if (typeof user === "string") return user;
return { user, options: session.options };
} catch (e) { } catch (e) {
console.error(e); console.error(e);
return `Request to identity provider failed: ${e}`; return `Request to identity provider failed: ${e}`;
+8 -4
View File
@@ -21,15 +21,19 @@ export default defineEventHandler(async (h3) => {
statusMessage: "No state in query params.", statusMessage: "No state in query params.",
}); });
const user = await manager.authorize(code, state); const result = await manager.authorize(code, state);
if (typeof user === "string") if (typeof result === "string")
throw createError({ throw createError({
statusCode: 403, statusCode: 403,
statusMessage: `Failed to sign in: "${user}". Please try again.`, statusMessage: `Failed to sign in: "${result}". Please try again.`,
}); });
await sessionHandler.signin(h3, user.id, true); await sessionHandler.signin(h3, result.user.id, true);
if (result.options.redirect) {
return sendRedirect(h3, result.options.redirect);
}
return sendRedirect(h3, "/"); return sendRedirect(h3, "/");
}); });
+8 -2
View File
@@ -1,10 +1,16 @@
import { enabledAuthManagers } from "~/server/plugins/04.auth-init"; import { enabledAuthManagers } from "~/server/plugins/04.auth-init";
export default defineEventHandler((h3) => { export default defineEventHandler((h3) => {
if (!enabledAuthManagers.OpenID) return sendRedirect(h3, "/auth/signin"); const redirect = getQuery(h3).redirect?.toString();
if (!enabledAuthManagers.OpenID)
return sendRedirect(
h3,
`/auth/signin${redirect ? `?redirect=${encodeURIComponent(redirect)}` : ""}`,
);
const manager = enabledAuthManagers.OpenID; const manager = enabledAuthManagers.OpenID;
const { redirectUrl } = manager.generateAuthSession(); const { redirectUrl } = manager.generateAuthSession({ redirect });
return sendRedirect(h3, redirectUrl); return sendRedirect(h3, redirectUrl);
}); });