UNPKG

alepha

Version:

Easy-to-use modern TypeScript framework for building many kind of applications.

99 lines (86 loc) 2.63 kB
import { $context, AlephaError, z } from "alepha"; import type { IssuerPrimitive } from "alepha/security"; import type { OAuth2Profile } from "../providers/ServerAuthProvider.ts"; import { $auth, type LinkAccountFn, type OidcOptions, type WithLinkFn, } from "./$auth.ts"; /** * Already configured Facebook authentication primitive. * * Uses OAuth2 to authenticate users via their Facebook accounts. * Upon successful authentication, it links the Facebook account to a user session. * * Environment Variables: * - `FACEBOOK_CLIENT_ID`: The App ID obtained from the Meta Developer Console. * - `FACEBOOK_CLIENT_SECRET`: The App Secret obtained from the Meta Developer Console. */ export const $authFacebook = ( realm: IssuerPrimitive & WithLinkFn, options: Partial<OidcOptions> = {}, ) => { const { alepha } = $context(); const env = alepha.parseEnv( z.object({ FACEBOOK_CLIENT_ID: z .text({ description: "The App ID obtained from the Meta Developer Console.", }) .optional(), FACEBOOK_CLIENT_SECRET: z .text({ description: "The App Secret obtained from the Meta Developer Console.", }) .optional(), }), ); const disabled = !env.FACEBOOK_CLIENT_ID || !env.FACEBOOK_CLIENT_SECRET; const name = "facebook"; const account: LinkAccountFn | undefined = options.account ?? (realm.link ? realm.link(name) : undefined); if (!account) { throw new AlephaError( "Authentication requires a link function in the realm primitive.", ); } return $auth({ issuer: realm, name, oauth: { clientId: env.FACEBOOK_CLIENT_ID!, clientSecret: env.FACEBOOK_CLIENT_SECRET!, authorization: "https://www.facebook.com/v25.0/dialog/oauth", token: "https://graph.facebook.com/v25.0/oauth/access_token", scope: "email", userinfo: async (tokens) => { const res = await fetch( "https://graph.facebook.com/v25.0/me?fields=id,name,email,picture.width(200).height(200)", { headers: { Authorization: `Bearer ${tokens.access_token}`, }, }, ).then((res) => res.json()); const user: OAuth2Profile = { sub: res.id, }; if (res.email) { user.email = res.email; } if (res.name) { user.name = res.name.trim(); } if (res.picture?.data?.url) { user.picture = res.picture.data.url; } return user; }, ...options, account, }, disabled, }); };