Browse Source

support allowed domains

Bernd Storath 1 month ago
parent
commit
e4286d1cca
  1. 2
      docs/content/advanced/config/external-authentication.md
  2. 21
      src/server/api/auth/[provider]/callback.get.ts
  3. 7
      src/server/api/auth/[provider]/link.get.ts
  4. 18
      src/server/plugins/manager.ts
  5. 9
      src/server/utils/config.ts
  6. 54
      src/server/utils/oauth.ts

2
docs/content/advanced/config/external-authentication.md

@ -45,8 +45,6 @@ Use [Allowed Domains](#allowed-domains) to restrict which users can log in.
///
<!-- TODO support allowed domain -->
### Allowed Domains
To only allow users with an email address from a specific domain to log in, set the env var `OAUTH_ALLOWED_DOMAINS` to the allowed domain.

21
src/server/api/auth/[provider]/callback.get.ts

@ -24,27 +24,6 @@ export default defineEventHandler(async (event) => {
providerConfig
);
if (!userInfo.sub) {
throw createError({
statusCode: 400,
statusMessage: 'No sub set',
});
}
if (!userInfo.email) {
throw createError({
statusCode: 400,
statusMessage: 'No email set',
});
}
if (!userInfo.email_verified) {
throw createError({
statusCode: 401,
statusMessage: 'Email is not verified',
});
}
const result = await Database.users.findOrCreateByProvider(
provider,
userInfo.sub,

7
src/server/api/auth/[provider]/link.get.ts

@ -29,13 +29,6 @@ export default definePermissionEventHandler(
providerConfig
);
if (!userInfo.sub) {
throw createError({
statusCode: 400,
statusMessage: 'No sub set',
});
}
await Database.users.linkOauth(user.id, provider, userInfo.sub);
return sendRedirect(event, '/me');

18
src/server/plugins/manager.ts

@ -1,12 +1,14 @@
export default defineNitroPlugin((nitroApp) => {
console.log(`====================================================`);
console.log(` wg-easy - https://github.com/wg-easy/wg-easy `);
console.log(`====================================================`);
console.log(`| wg-easy: ${RELEASE.padEnd(38)} |`);
console.log(`| Node: ${process.version.padEnd(38)} |`);
console.log(`| Platform: ${process.platform.padEnd(38)} |`);
console.log(`| Arch: ${process.arch.padEnd(38)} |`);
console.log(`====================================================`);
console.log(`
wg-easy - https://github.com/wg-easy/wg-easy ┃
wg-easy: ${RELEASE.padEnd(38)}
Node: ${process.version.padEnd(38)}
Platform: ${process.platform.padEnd(38)}
Arch: ${process.arch.padEnd(38)}
`);
nitroApp.hooks.hook('close', async () => {
console.log('Shutting down');
await WireGuard.Shutdown();

9
src/server/utils/config.ts

@ -42,8 +42,17 @@ export const WG_ENV = {
.map((v) => v.trim())
.filter((v) => isValidOauthProvider(v))
.filter((v) => isConfiguredOauthProvider(OAUTH_PROVIDERS[v])),
OAUTH_ALLOWED_DOMAINS: process.env.OAUTH_ALLOWED_DOMAINS?.split(',').map(
(v) => v.trim()
),
};
if (WG_ENV.OAUTH_PROVIDERS && WG_ENV.OAUTH_PROVIDERS.length > 1) {
SERVER_DEBUG(`
Enabled OAuth providers: ${WG_ENV.OAUTH_PROVIDERS.join(', ')}
Allowed OAuth domains: ${WG_ENV.OAUTH_ALLOWED_DOMAINS?.join(', ') ?? 'All'}`);
}
export const WG_INITIAL_ENV = {
ENABLED: process.env.INIT_ENABLED === 'true',
USERNAME: process.env.INIT_USERNAME,

54
src/server/utils/oauth.ts

@ -208,5 +208,59 @@ export async function getUserInfo(
userInfo = await client.fetchUserInfo(config, tokens.access_token, subject);
}
if (!hasOauthProps(userInfo)) {
throw createError({
statusCode: 400,
statusMessage: 'Invalid user info',
});
}
if (!isAllowedDomain(userInfo.email)) {
throw createError({
statusCode: 401,
statusMessage: 'Email domain not allowed',
});
}
return userInfo;
}
function hasOauthProps<
T extends { sub?: string; email?: string; email_verified?: boolean },
>(
userInfo: T
): userInfo is T & { sub: string; email: string; email_verified: boolean } {
if (!userInfo.sub) {
throw createError({
statusCode: 400,
statusMessage: 'No sub set',
});
}
if (!userInfo.email) {
throw createError({
statusCode: 400,
statusMessage: 'No email set',
});
}
if (!userInfo.email_verified) {
throw createError({
statusCode: 401,
statusMessage: 'Email is not verified',
});
}
return true;
}
function isAllowedDomain(email: string) {
const emailDomain = email.slice(email.lastIndexOf('@') + 1);
if (
WG_ENV.OAUTH_ALLOWED_DOMAINS &&
!WG_ENV.OAUTH_ALLOWED_DOMAINS.includes(emailDomain)
) {
return false;
}
return true;
}

Loading…
Cancel
Save