-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Covert Azure AD auth to dynamic configuration
- Loading branch information
1 parent
711b93f
commit a1f06d7
Showing
13 changed files
with
311 additions
and
128 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,7 @@ | ||
import { NextApiRequest, NextApiResponse } from 'next'; | ||
import nextAuth from 'next-auth'; | ||
import { nextAuthOptions } from '~backend/nextAuth'; | ||
import { getNextAuthOptions } from '~backend/nextAuth'; | ||
|
||
export default nextAuth(nextAuthOptions); | ||
export default async function auth(req: NextApiRequest, res: NextApiResponse) { | ||
return await nextAuth(req, res, await getNextAuthOptions()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import { Status, endpoint } from "~backend/Endpoint"; | ||
import { configOptions } from "~backend/config"; | ||
import { makeConfigurationEntity } from "~api/entities/ConfigurationEntity"; | ||
import { hasScope } from "~backend/scopes"; | ||
import { $in } from "~utils/typeguards"; | ||
import { prisma } from "@necode-org/database"; | ||
import Joi from "joi"; | ||
|
||
const apiConfigurationOne = endpoint(makeConfigurationEntity, ['key'], { | ||
type: 'entity', | ||
GET: { | ||
loginValidation: true, | ||
handler: async ({ query: { key }, session }, ok, fail) => { | ||
if (!await hasScope(session!.user.id, 'configuration:read', { key })) { | ||
return fail(Status.FORBIDDEN); | ||
} | ||
|
||
if (!$in(key, configOptions)) { | ||
return fail(Status.NOT_FOUND); | ||
} | ||
|
||
const configSettings = configOptions[key]; | ||
|
||
if (configSettings.writeOnly) { | ||
return fail(Status.FORBIDDEN, `${key} is a write-only configuration option`); | ||
} | ||
|
||
const config = await prisma.systemConfiguration.upsert({ | ||
where: { key }, | ||
create: { | ||
key, | ||
value: configSettings.default, | ||
}, | ||
update: {}, | ||
}); | ||
|
||
return ok(makeConfigurationEntity(config)); | ||
} | ||
}, | ||
PUT: { | ||
loginValidation: true, | ||
schema: Joi.object({ | ||
value: Joi.string(), | ||
}), | ||
handler: async ({ query: { key }, session, body }, ok, fail) => { | ||
if (!await hasScope(session!.user.id, 'configuration:write', { key })) { | ||
return fail(Status.FORBIDDEN); | ||
} | ||
|
||
if (!$in(key, configOptions)) { | ||
return fail(Status.NOT_FOUND); | ||
} | ||
|
||
const config = await prisma.systemConfiguration.upsert({ | ||
where: { key }, | ||
create: { | ||
key, | ||
value: body.value, | ||
}, | ||
update: { | ||
value: body.value, | ||
}, | ||
}); | ||
|
||
return ok(makeConfigurationEntity(config)); | ||
} | ||
}, | ||
}); | ||
|
||
export default apiConfigurationOne; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { SystemConfiguration } from "~database"; | ||
import { Entity, EntityType } from "./Entity"; | ||
|
||
export type ConfigurationEntity | ||
= Entity<EntityType.Configuration, { | ||
value: string; | ||
}>; | ||
|
||
export function makeConfigurationEntity(configuration: SystemConfiguration): ConfigurationEntity { | ||
return { | ||
type: EntityType.Configuration, | ||
id: configuration.key, | ||
attributes: { | ||
value: configuration.value, | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { OAuthConfig, OAuthUserConfig } from "next-auth/providers"; | ||
|
||
interface AzureProfile { | ||
businessPhones: string[], | ||
displayName: string, | ||
givenName: string, | ||
jobTitle: string | ||
mail: string, | ||
mobilePhone: null, | ||
officeLocation: null, | ||
preferredLanguage: null, | ||
surname: string, | ||
userPrincipalName: string, | ||
id: string | ||
} | ||
|
||
export function AzureProvider({ authorization, token, tenantId, ...rest }: OAuthUserConfig<AzureProfile> & { tenantId: string, profile: NonNullable<OAuthUserConfig<AzureProfile>['profile']> }): OAuthConfig<AzureProfile> { | ||
return { | ||
id: 'azure', | ||
name: 'Microsoft', | ||
type: 'oauth', | ||
version: '2.0', | ||
authorization: { | ||
url: `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/authorize?response_type=code&response_mode=query`, | ||
params: { | ||
scope: 'https://graph.microsoft.com/user.read', | ||
...typeof authorization === 'string' ? undefined : authorization?.params, | ||
}, | ||
...typeof authorization === 'string' ? { url: authorization } : authorization, | ||
}, | ||
token: { | ||
url: `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`, | ||
params: { | ||
grant_type: 'authorization_code', | ||
...typeof token === 'string' ? {} : token?.params, | ||
}, | ||
...typeof token === 'string' ? { url: token } : token, | ||
}, | ||
userinfo: 'https://graph.microsoft.com/v1.0/me/', | ||
...rest, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { prisma } from "~database/src"; | ||
|
||
interface ConfigurationSettings { | ||
default: string; | ||
writeOnly: boolean; | ||
} | ||
|
||
function config(settings?: Partial<ConfigurationSettings>): ConfigurationSettings { | ||
return Object.assign({ | ||
default: '', | ||
writeOnly: false, | ||
} satisfies ConfigurationSettings, settings); | ||
} | ||
|
||
export const configOptions = { | ||
'auth.azure.loginName': config({ default: 'Microsoft' }), | ||
'auth.azure.tenantId': config(), | ||
'auth.azure.clientId': config(), | ||
'auth.azure.clientSecret': config({ writeOnly: true }), | ||
} as const; | ||
|
||
export async function getConfigValue(key: keyof typeof configOptions) { | ||
const result = await prisma.systemConfiguration.findUnique({ | ||
where: { key }, | ||
select: { value: true }, | ||
}); | ||
return result?.value ?? configOptions[key].default; | ||
} | ||
|
||
export async function getConfigValues<T extends (keyof typeof configOptions)[]>(...options: T): Promise<{ [key in T[number]]: string }> { | ||
const result = await prisma.systemConfiguration.findMany({ | ||
where: { key: { in: options } }, | ||
select: { key: true, value: true }, | ||
}); | ||
return Object.fromEntries(result.map(r => [r.key, r.value])) as any; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.