diff --git a/.env.example b/.env.example index 7cf72ede78..2f5103a8a8 100644 --- a/.env.example +++ b/.env.example @@ -7,6 +7,8 @@ SESSION_SECRET=secret // Auth https://discord.com/developers DISCORD_CLIENT_ID= DISCORD_CLIENT_SECRET= +AUTH_GATEWAY_URL= +AUTH_GATEWAY_SECRET= // Patreon integration https://www.patreon.com/portal/registration/register-clients PATREON_ACCESS_TOKEN= diff --git a/app/modules/auth/DiscordStrategy.server.ts b/app/modules/auth/DiscordStrategy.server.ts index d7a64cbc43..c4a8d1d073 100644 --- a/app/modules/auth/DiscordStrategy.server.ts +++ b/app/modules/auth/DiscordStrategy.server.ts @@ -57,24 +57,20 @@ export class DiscordStrategy extends OAuth2Strategy< "Authorization", `Bearer ${accessToken}`, ]; - const discordResponses = await Promise.all([ - fetch("https://discord.com/api/users/@me", { - headers: [authHeader], - }), - fetch("https://discord.com/api/users/@me/connections", { - headers: [authHeader], - }), - ]); - - const [user, connections] = discordUserDetailsSchema.parse( - await Promise.all( - discordResponses.map((res) => { - if (!res.ok) throw new Error("Call to Discord API failed"); - - return res.json(); - }), - ), - ); + + const discordResponses = this.authGatewayEnabled() + ? await this.fetchProfileViaGateway(accessToken) + : await Promise.all([ + fetch("https://discord.com/api/users/@me", { + headers: [authHeader], + }).then(this.jsonIfOk), + fetch("https://discord.com/api/users/@me/connections", { + headers: [authHeader], + }).then(this.jsonIfOk), + ]); + + const [user, connections] = + discordUserDetailsSchema.parse(discordResponses); const userFromDb = db.users.upsert({ discordAvatar: user.avatar ?? null, @@ -92,6 +88,33 @@ export class DiscordStrategy extends OAuth2Strategy< this.scope = "identify connections"; } + private authGatewayEnabled() { + return Boolean( + process.env["AUTH_GATEWAY_URL"] && process.env["AUTH_GATEWAY_SECRET"], + ); + } + + private async fetchProfileViaGateway(token: string) { + const url = `${process.env["AUTH_GATEWAY_URL"]}?token=${token}`; + + const options: RequestInit = { + method: "GET", + headers: { "X-Require-Whisk-Auth": process.env["AUTH_GATEWAY_SECRET"]! }, + }; + + return fetch(url, options).then(this.jsonIfOk); + } + + private jsonIfOk(res: Response) { + if (!res.ok) { + throw new Error( + `Auth related call failed with status code ${res.status}`, + ); + } + + return res.json(); + } + private parseConnections( connections: z.infer, ) {