Skip to content

Commit

Permalink
query secrets from cloud secret manager
Browse files Browse the repository at this point in the history
  • Loading branch information
chase-manning committed Dec 6, 2023
1 parent 64d9f66 commit 2191fa6
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 33 deletions.
23 changes: 8 additions & 15 deletions functions/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,18 @@
import { OauthCredentials, ServiceType } from "./types";

function getEnv(name: string): string {
const value = process.env[name];
if (value === undefined) {
throw new Error(`Missing environment variable ${name}`);
}
return value;
export interface Secrets {
twitterClientID: string;
twitterClientSecret: string;
discordClientID: string;
discordClientSecret: string;
}

export const redirectURI = "https://tlx.fi/referrals";

const prefixes = {
[ServiceType.Twitter]: "TWITTER_",
[ServiceType.Discord]: "DISCORD_",
};

export function getCredentials(service: ServiceType): OauthCredentials {
const prefix = prefixes[service];
export function getCredentials(service: ServiceType, secrets: Secrets): OauthCredentials {
return {
clientID: getEnv(`${prefix}CLIENT_ID`),
clientSecret: getEnv(`${prefix}CLIENT_SECRET`),
clientID: service === ServiceType.Twitter ? secrets.twitterClientID : secrets.discordClientID,
clientSecret: service === ServiceType.Twitter ? secrets.twitterClientSecret : secrets.discordClientSecret,
};
}

Expand Down
18 changes: 17 additions & 1 deletion functions/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,26 @@ import registrationHandler from "./registration";
import wrapHandler, { getUserAddress, validateParams } from "./utils";
import { userExists } from "./db";
import { APIError, SignedParams } from "./types";
import { defineSecret } from "firebase-functions/params";

const twitterClientID = defineSecret("TWITTER_CLIENT_ID");
const twitterClientSecret = defineSecret("TWITTER_CLIENT_SECRET");
const discordClientID = defineSecret("DISCORD_CLIENT_ID");
const discordClientSecret = defineSecret("DISCORD_CLIENT_SECRET");

admin.initializeApp();

export const register = onRequest(wrapHandler(registrationHandler));
export const register = onRequest(
{ secrets: [twitterClientID, twitterClientSecret, discordClientID, discordClientSecret] },
wrapHandler(async (request) => {
registrationHandler(request, {
twitterClientID: twitterClientID.value(),
twitterClientSecret: twitterClientSecret.value(),
discordClientID: discordClientID.value(),
discordClientSecret: discordClientSecret.value(),
});
})
);

export const inviteCodes = onRequest(
wrapHandler(async (request) => {
Expand Down
16 changes: 8 additions & 8 deletions functions/src/registration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,26 @@ import admin from "firebase-admin";

import { DiscordService, TwitterService } from "./services";
import { APIError, RegistrationParams, Guild } from "./types";
import { invitesPerUser, tlxGuidID } from "./constants";
import { Secrets, invitesPerUser, tlxGuidID } from "./constants";
import { generateAndSaveInviteCodes, useCode, userExists, usernameExists } from "./db";
import { getUserAddress, validateParams } from "./utils";

const requiredKeys = ["twitterCode", "discordCode", "signature", "inviteCode"];

async function getTwitterUsername(code: string): Promise<string> {
async function getTwitterUsername(code: string, secrets: Secrets): Promise<string> {
try {
logger.info("Getting Twitter data");
const twitterService = await TwitterService.fromCode(code);
const twitterService = await TwitterService.fromCode(code, secrets);
return twitterService.getUsername();
} catch (error) {
throw new APIError(`Twitter authentication failed: ${error}`);
}
}

async function getDiscordData(code: string): Promise<{ username: string; guilds: Guild[] }> {
async function getDiscordData(code: string, secrets: Secrets): Promise<{ username: string; guilds: Guild[] }> {
try {
logger.info("Getting Discord data");
const discordService = await DiscordService.fromCode(code);
const discordService = await DiscordService.fromCode(code, secrets);
const username = await discordService.getUsername();
const guilds = await discordService.getGuilds();
return { username, guilds };
Expand All @@ -32,7 +32,7 @@ async function getDiscordData(code: string): Promise<{ username: string; guilds:
}
}

export default async function registrationHandler(request: Request) {
export default async function registrationHandler(request: Request, secrets: Secrets) {
const params = validateParams<RegistrationParams>(request.body, ...requiredKeys);
const address = getUserAddress(params.signature);

Expand All @@ -50,13 +50,13 @@ export default async function registrationHandler(request: Request) {
throw new APIError("Code already used");
}

const twitterUsername = await getTwitterUsername(params.twitterCode);
const twitterUsername = await getTwitterUsername(params.twitterCode, secrets);

if (await usernameExists("twitterUsername", twitterUsername)) {
throw new APIError("Twitter already used");
}

const { username: discordUsername, guilds } = await getDiscordData(params.discordCode);
const { username: discordUsername, guilds } = await getDiscordData(params.discordCode, secrets);

if (await usernameExists("discordUsername", discordUsername)) {
throw new APIError("Discord already used");
Expand Down
18 changes: 9 additions & 9 deletions functions/src/services.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import fetch, { Response } from "node-fetch";
import { redirectURI, getCredentials, oauthURLs } from "./constants";
import { redirectURI, getCredentials, oauthURLs, Secrets } from "./constants";
import { Guild, ServiceType, TokenResponse, TwitterUserResponse, User } from "./types";

async function processResponse<T>(response: Response): Promise<T> {
Expand All @@ -9,22 +9,22 @@ async function processResponse<T>(response: Response): Promise<T> {
return (await response.json()) as T;
}

function getAuthorization(service: ServiceType) {
const { clientID, clientSecret } = getCredentials(service);
function getAuthorization(service: ServiceType, secrets: Secrets) {
const { clientID, clientSecret } = getCredentials(service, secrets);
const encodedCredentials = Buffer.from(`${clientID}:${clientSecret}`).toString("base64");
const paddingLength = (4 - (encodedCredentials.length % 4)) % 4;
return encodedCredentials + "=".repeat(paddingLength);
}

async function getAccessToken(service: ServiceType, code: string): Promise<string> {
async function getAccessToken(service: ServiceType, code: string, secrets: Secrets): Promise<string> {
const params = new URLSearchParams({ code, grant_type: "authorization_code", redirect_uri: redirectURI });
if (service === ServiceType.Twitter) {
params.set("code_verifier", "challenge");
}

const headers = {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": `Basic ${getAuthorization(service)}`,
"Authorization": `Basic ${getAuthorization(service, secrets)}`,
};
const response = await fetch(oauthURLs[service], { method: "POST", body: params.toString(), headers });
const data = await processResponse<TokenResponse>(response);
Expand All @@ -44,8 +44,8 @@ class Service {
}

export class TwitterService extends Service {
static async fromCode(code: string): Promise<TwitterService> {
return new TwitterService(await getAccessToken(ServiceType.Twitter, code));
static async fromCode(code: string, secrets: Secrets): Promise<TwitterService> {
return new TwitterService(await getAccessToken(ServiceType.Twitter, code, secrets));
}

async getUsername(): Promise<string> {
Expand All @@ -55,8 +55,8 @@ export class TwitterService extends Service {
}

export class DiscordService extends Service {
static async fromCode(code: string): Promise<DiscordService> {
return new DiscordService(await getAccessToken(ServiceType.Discord, code));
static async fromCode(code: string, secrets: Secrets): Promise<DiscordService> {
return new DiscordService(await getAccessToken(ServiceType.Discord, code, secrets));
}

async getUsername(): Promise<string> {
Expand Down

0 comments on commit 2191fa6

Please sign in to comment.