mirror of
https://github.com/Drop-OSS/drop.git
synced 2026-06-22 04:11:32 +10:00
fix: openid redirect auth query
This commit is contained in:
@@ -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 →
|
Sign in with external provider →
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
const route = useRoute();
|
||||||
|
</script>
|
||||||
|
|||||||
@@ -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}`;
|
||||||
|
|||||||
@@ -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, "/");
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user