mirror of
https://github.com/Drop-OSS/drop.git
synced 2025-11-10 04:22:09 +10:00
feat: add oidc to admin panel
This commit is contained in:
@ -1,14 +1,15 @@
|
||||
import type { AuthMec } from "@prisma/client";
|
||||
import { AuthMec } from "@prisma/client";
|
||||
import aclManager from "~/server/internal/acls";
|
||||
import { applicationSettings } from "~/server/internal/config/application-configuration";
|
||||
import { enabledAuthManagers } from "~/server/plugins/04.auth-init";
|
||||
|
||||
export default defineEventHandler(async (h3) => {
|
||||
const allowed = await aclManager.allowSystemACL(h3, ["auth:read"]);
|
||||
if (!allowed) throw createError({ statusCode: 403 });
|
||||
|
||||
const enabledMechanisms: AuthMec[] = await applicationSettings.get(
|
||||
"enabledAuthencationMechanisms",
|
||||
);
|
||||
const authData = {
|
||||
[AuthMec.Simple]: enabledAuthManagers.Simple,
|
||||
[AuthMec.OpenID]: enabledAuthManagers.OpenID && enabledAuthManagers.OpenID.generateConfiguration(),
|
||||
}
|
||||
|
||||
return enabledMechanisms;
|
||||
return authData;
|
||||
});
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { enabledAuthManagers } from "~/server/plugins/04.auth-init";
|
||||
|
||||
export default defineEventHandler((h3) => {
|
||||
export default defineEventHandler(() => {
|
||||
const authManagers = Object.entries(enabledAuthManagers)
|
||||
.filter((e) => !!e[1])
|
||||
.map((e) => e[0]);
|
||||
|
||||
@ -16,7 +16,7 @@ const signinValidator = type({
|
||||
});
|
||||
|
||||
export default defineEventHandler(async (h3) => {
|
||||
if (!enabledAuthManagers.simple)
|
||||
if (!enabledAuthManagers.Simple)
|
||||
throw createError({
|
||||
statusCode: 403,
|
||||
statusMessage: "Sign in method not enabled",
|
||||
|
||||
@ -80,6 +80,7 @@ export const dbCertificateStore = () => {
|
||||
},
|
||||
});
|
||||
} finally {
|
||||
/* empty */
|
||||
}
|
||||
},
|
||||
async checkBlacklistCertificate(name: string): Promise<boolean> {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import type { ApplicationSettings } from "@prisma/client";
|
||||
import { AuthMec } from "@prisma/client";
|
||||
import prisma from "../db/database";
|
||||
|
||||
class ApplicationConfiguration {
|
||||
@ -38,7 +37,6 @@ class ApplicationConfiguration {
|
||||
async initialiseConfiguration() {
|
||||
const initialState = await prisma.applicationSettings.create({
|
||||
data: {
|
||||
enabledAuthencationMechanisms: [AuthMec.Simple],
|
||||
metadataProviders: [],
|
||||
},
|
||||
});
|
||||
|
||||
@ -57,9 +57,11 @@ class NotificationSystem {
|
||||
}
|
||||
|
||||
async push(userId: string, notificationCreateArgs: NotificationCreateArgs) {
|
||||
if (!notificationCreateArgs.nonce)
|
||||
throw new Error("No nonce in notificationCreateArgs");
|
||||
const notification = await prisma.notification.upsert({
|
||||
where: {
|
||||
nonce: notificationCreateArgs.nonce!!
|
||||
nonce: notificationCreateArgs.nonce,
|
||||
},
|
||||
update: {
|
||||
userId: userId,
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { randomUUID } from "crypto";
|
||||
import prisma from "../db/database";
|
||||
import { AuthMec, Prisma } from "@prisma/client";
|
||||
import { AuthMec } from "@prisma/client";
|
||||
import objectHandler from "../objects";
|
||||
import { Readable } from "stream";
|
||||
import type { Readable } from "stream";
|
||||
import * as jdenticon from "jdenticon";
|
||||
|
||||
interface OIDCWellKnown {
|
||||
@ -39,7 +39,8 @@ export class OIDCManager {
|
||||
|
||||
private adminGroup?: string = process.env.OIDC_ADMIN_GROUP;
|
||||
private usernameClaim: keyof OIDCUserInfo =
|
||||
(process.env.OIDC_USERNAME_CLAIM as any) ?? "preferred_username";
|
||||
(process.env.OIDC_USERNAME_CLAIM as keyof OIDCUserInfo) ??
|
||||
"preferred_username";
|
||||
|
||||
private signinStateTable: { [key: string]: OIDCAuthSession } = {};
|
||||
|
||||
@ -121,6 +122,16 @@ export class OIDCManager {
|
||||
return new OIDCManager(configuration, clientId, clientSecret, externalUrl);
|
||||
}
|
||||
|
||||
generateConfiguration() {
|
||||
return {
|
||||
authorizationUrl: this.oidcConfiguration.authorization_endpoint,
|
||||
scopes: this.oidcConfiguration.scopes_supported.join(", "),
|
||||
adminGroup: this.adminGroup,
|
||||
usernameClaim: this.usernameClaim,
|
||||
externalUrl: this.externalUrl,
|
||||
};
|
||||
}
|
||||
|
||||
generateAuthSession(): OIDCAuthSession {
|
||||
const stateKey = randomUUID();
|
||||
|
||||
@ -226,11 +237,12 @@ export class OIDCManager {
|
||||
const userId = randomUUID();
|
||||
const profilePictureId = randomUUID();
|
||||
|
||||
if (userinfo.picture) {
|
||||
const picture = userinfo.picture;
|
||||
if (picture) {
|
||||
await objectHandler.createFromSource(
|
||||
profilePictureId,
|
||||
async () =>
|
||||
await $fetch<Readable>(userinfo.picture!!, {
|
||||
await $fetch<Readable>(picture, {
|
||||
responseType: "stream",
|
||||
}),
|
||||
{},
|
||||
@ -269,6 +281,7 @@ export class OIDCManager {
|
||||
},
|
||||
},
|
||||
},
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
credentials: creds as any, // Prisma converts this to the Json type for us
|
||||
},
|
||||
include: {
|
||||
|
||||
@ -27,7 +27,6 @@ export default defineNitroPlugin(async (_nitro) => {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add providers based on their position in the application settings
|
||||
const configuredProviderList =
|
||||
await applicationSettings.get("metadataProviders");
|
||||
|
||||
@ -1,24 +1,25 @@
|
||||
import { AuthMec } from "@prisma/client";
|
||||
import { OIDCManager } from "../internal/oidc";
|
||||
|
||||
export const enabledAuthManagers: {
|
||||
simple: boolean;
|
||||
oidc: OIDCManager | undefined;
|
||||
[AuthMec.Simple]: boolean;
|
||||
[AuthMec.OpenID]: OIDCManager | undefined;
|
||||
} = {
|
||||
simple: false,
|
||||
oidc: undefined,
|
||||
[AuthMec.Simple]: false,
|
||||
[AuthMec.OpenID]: undefined,
|
||||
};
|
||||
|
||||
const initFunctions: {
|
||||
[K in keyof typeof enabledAuthManagers]: () => Promise<unknown>;
|
||||
} = {
|
||||
oidc: OIDCManager.prototype.create,
|
||||
simple: async () => {
|
||||
[AuthMec.OpenID]: OIDCManager.prototype.create,
|
||||
[AuthMec.Simple]: async () => {
|
||||
const disabled = process.env.DISABLE_SIMPLE_AUTH as string | undefined;
|
||||
return !disabled;
|
||||
},
|
||||
};
|
||||
|
||||
export default defineNitroPlugin(async (_nitro) => {
|
||||
export default defineNitroPlugin(async () => {
|
||||
for (const [key, init] of Object.entries(initFunctions)) {
|
||||
try {
|
||||
const object = await init();
|
||||
@ -32,7 +33,7 @@ export default defineNitroPlugin(async (_nitro) => {
|
||||
}
|
||||
|
||||
// Add every other auth mechanism here, and fall back to simple if none of them are enabled
|
||||
if (!enabledAuthManagers.oidc) {
|
||||
enabledAuthManagers.simple = true;
|
||||
if (!enabledAuthManagers[AuthMec.OpenID]) {
|
||||
enabledAuthManagers[AuthMec.Simple] = true;
|
||||
}
|
||||
});
|
||||
|
||||
@ -2,9 +2,9 @@ import sessionHandler from "~/server/internal/session";
|
||||
import { enabledAuthManagers } from "~/server/plugins/04.auth-init";
|
||||
|
||||
export default defineEventHandler(async (h3) => {
|
||||
if (!enabledAuthManagers.oidc) return sendRedirect(h3, "/auth/signin");
|
||||
if (!enabledAuthManagers.OpenID) return sendRedirect(h3, "/auth/signin");
|
||||
|
||||
const manager = enabledAuthManagers.oidc;
|
||||
const manager = enabledAuthManagers.OpenID;
|
||||
|
||||
const query = getQuery(h3);
|
||||
const code = query.code?.toString();
|
||||
@ -29,7 +29,6 @@ export default defineEventHandler(async (h3) => {
|
||||
statusMessage: `Failed to sign in: "${user}". Please try again.`,
|
||||
});
|
||||
|
||||
|
||||
await sessionHandler.signin(h3, user.id, true);
|
||||
|
||||
return sendRedirect(h3, "/");
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { enabledAuthManagers } from "~/server/plugins/04.auth-init";
|
||||
|
||||
export default defineEventHandler((h3) => {
|
||||
if (!enabledAuthManagers.oidc) return sendRedirect(h3, "/auth/signin");
|
||||
if (!enabledAuthManagers.OpenID) return sendRedirect(h3, "/auth/signin");
|
||||
|
||||
const manager = enabledAuthManagers.oidc;
|
||||
const manager = enabledAuthManagers.OpenID;
|
||||
const { redirectUrl } = manager.generateAuthSession();
|
||||
|
||||
return sendRedirect(h3, redirectUrl);
|
||||
|
||||
Reference in New Issue
Block a user