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

View File

@ -1,10 +1,14 @@
<template>
<div class="flex">
<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"
>
Sign in with external provider &rarr;
</a>
</div>
</template>
<script setup lang="ts">
const route = useRoute();
</script>

View File

@ -1,5 +1,6 @@
import { randomUUID } from "crypto";
import prisma from "../db/database";
import type { User } from "~/prisma/client";
import { AuthMec } from "~/prisma/client";
import objectHandler from "../objects";
import type { Readable } from "stream";
@ -12,10 +13,15 @@ interface OIDCWellKnown {
scopes_supported: string[];
}
interface OIDCAuthSessionOptions {
redirect: string | undefined;
}
interface OIDCAuthSession {
redirectUrl: string;
callbackUrl: string;
state: string;
options: OIDCAuthSessionOptions;
}
interface OIDCUserInfo {
@ -132,7 +138,7 @@ export class OIDCManager {
};
}
generateAuthSession(): OIDCAuthSession {
generateAuthSession(options?: OIDCAuthSessionOptions): OIDCAuthSession {
const stateKey = randomUUID();
const normalisedUrl = new URL(
@ -148,12 +154,16 @@ export class OIDCManager {
redirectUrl: finalUrl,
callbackUrl: redirectUrl,
state: stateKey,
options: options ?? { redirect: undefined },
};
this.signinStateTable[stateKey] = 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];
if (!session) return "Invalid state parameter";
@ -191,7 +201,9 @@ export class OIDCManager {
const user = await this.fetchOrCreateUser(userinfo);
return user;
if (typeof user === "string") return user;
return { user, options: session.options };
} catch (e) {
console.error(e);
return `Request to identity provider failed: ${e}`;

View File

@ -21,15 +21,19 @@ export default defineEventHandler(async (h3) => {
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({
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, "/");
});

View File

@ -1,10 +1,16 @@
import { enabledAuthManagers } from "~/server/plugins/04.auth-init";
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 { redirectUrl } = manager.generateAuthSession();
const { redirectUrl } = manager.generateAuthSession({ redirect });
return sendRedirect(h3, redirectUrl);
});