From 5f4432513366de1415cc5581933c724398e31369 Mon Sep 17 00:00:00 2001 From: Miguel Romero Karam Date: Mon, 1 Jul 2024 19:38:53 +0200 Subject: [PATCH] feat(plugins/auth): add `netzolabs` provider (via `google` oauth) --- lib/plugins/auth/islands/auth-form.tsx | 6 +++++ lib/plugins/auth/plugin.ts | 5 ++++ lib/plugins/auth/utils/providers/mod.ts | 23 +++++++++++++++- lib/plugins/auth/utils/providers/netzolabs.ts | 27 +++++++++++++++++++ 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 lib/plugins/auth/utils/providers/netzolabs.ts diff --git a/lib/plugins/auth/islands/auth-form.tsx b/lib/plugins/auth/islands/auth-form.tsx index f1323349..91294700 100644 --- a/lib/plugins/auth/islands/auth-form.tsx +++ b/lib/plugins/auth/islands/auth-form.tsx @@ -186,6 +186,12 @@ export function AuthForm(props: AuthFormProps) { )} */ } + + {!!providers?.netzolabs && ( + +
+ + )}
); diff --git a/lib/plugins/auth/plugin.ts b/lib/plugins/auth/plugin.ts index 391e25c3..6c615c8a 100644 --- a/lib/plugins/auth/plugin.ts +++ b/lib/plugins/auth/plugin.ts @@ -71,6 +71,10 @@ export type AuthConfig = { clientSecret?: string; oktaDomain?: string; // must set OKTA_DOMAIN environment variable }; + netzolabs?: AuthConfigProvider & { + clientId?: string; + clientSecret?: string; + }; }; /** A function to check if a user is authorized to sign in. The function should * throw an Error with an optional error message if not authorized. @@ -132,6 +136,7 @@ export const auth = (config: AuthConfig): Plugin => { "gitlab", "auth0", "okta", + "netzolabs", ].some((key) => !!config?.providers?.[key as AuthProvider]); if (!authEnabled) return { name: "netzo.auth" }; // skip if auth but no providers are set diff --git a/lib/plugins/auth/utils/providers/mod.ts b/lib/plugins/auth/utils/providers/mod.ts index 6160af53..ba002414 100644 --- a/lib/plugins/auth/utils/providers/mod.ts +++ b/lib/plugins/auth/utils/providers/mod.ts @@ -17,6 +17,7 @@ import { getUserGithub } from "./github.ts"; import { getUserGitlab } from "./gitlab.ts"; import { getUserGoogle } from "./google.ts"; import { getUserNetzo, handleCallbackNetzo, signInNetzo } from "./netzo.ts"; +import { getUserNetzolabs } from "./netzolabs.ts"; import { getUserOkta } from "./okta.ts"; import { getUserSlack } from "./slack.ts"; @@ -36,7 +37,10 @@ export const getAuthConfig = (provider: AuthProvider, ctx: FreshContext) => { case "google": { return createGoogleOAuthConfig({ redirectUri, - scope: "https://www.googleapis.com/auth/userinfo.profile", + scope: [ + "https://www.googleapis.com/auth/userinfo.profile", + "https://www.googleapis.com/auth/userinfo.email", + ], }); } case "github": { @@ -70,6 +74,21 @@ export const getAuthConfig = (provider: AuthProvider, ctx: FreshContext) => { // case "discord": // case "dropbox": // case "facebook": + case "netzolabs": { + return { + clientId: Deno.env.get("NETZOLABS_CLIENT_ID")!, + clientSecret: Deno.env.get("NETZOLABS_CLIENT_SECRET")!, + authorizationEndpointUri: "https://accounts.google.com/o/oauth2/v2/auth", + tokenUri: "https://oauth2.googleapis.com/token", + redirectUri, + defaults: { + scope: [ + "https://www.googleapis.com/auth/userinfo.profile", + "https://www.googleapis.com/auth/userinfo.email", + ], + }, + }; // MUST be set if using Netzo Auth Provider + } default: throw new Error(`Provider ${provider} not supported`); } @@ -107,6 +126,8 @@ export const getUserByProvider = async ( return await getUserAuth0(accessToken); case "okta": return await getUserOkta(accessToken); + case "netzolabs": + return await getUserNetzolabs(accessToken); default: throw new Error(`Provider ${provider} not supported`); } diff --git a/lib/plugins/auth/utils/providers/netzolabs.ts b/lib/plugins/auth/utils/providers/netzolabs.ts new file mode 100644 index 00000000..9f75ee8b --- /dev/null +++ b/lib/plugins/auth/utils/providers/netzolabs.ts @@ -0,0 +1,27 @@ +import type { AuthUserFromProvider } from "../types.ts"; +import { UserGoogle } from "./google.ts"; + +export type UserNetzolabs = UserGoogle; + +export async function getUserNetzolabs( + accessToken: string, +): Promise { + const response = await fetch( + "https://www.googleapis.com/oauth2/v3/userinfo", + { + headers: { authorization: `Bearer ${accessToken}` }, + }, + ); + if (!response.ok) { + const { message } = await response.json(); + throw new Error(`${response.status}: ${message}`); + } + const userNetzolabs: UserNetzolabs = await response.json(); + return { + provider: "netzolabs", + authId: userNetzolabs.sub, + name: userNetzolabs.name, + email: userNetzolabs.email, + avatar: userNetzolabs.picture, + }; +}