Skip to content

Commit

Permalink
Update token creation
Browse files Browse the repository at this point in the history
  • Loading branch information
fforres committed Aug 11, 2024
1 parent 7e15348 commit ea55905
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 34 deletions.
63 changes: 39 additions & 24 deletions src/authn/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import {
updateUserProfileInfo,
} from "~/datasources/queries/users";
import { getUsername } from "~/datasources/queries/utils/createUsername";
import { unauthorizedError } from "~/errors";
import { applicationError, ServiceErrors, unauthorizedError } from "~/errors";

const preventUserUpdate = new Set<"retool">(["retool"]);

// Obtener el token de autorización de la solicitud, ya sea del encabezado de
// autorización o de la cookie "community-os-access-token"
Expand All @@ -25,12 +27,12 @@ const getAuthToken = (request: Request) => {
return null;
};

export const createAuthToken = async (user: USER, SECRET: string) => {
export const createMinimalAuthToken = async (user: USER, SECRET: string) => {
const payload = {
audience: "retool-autenticated",
id: user.id,
email: user.email,
user_metadata: user,
audience: "retool",
user_metadata: {
sub: user.id,
},
exp: Date.now() + 60 * 60 * 24 * 1000 /* 24 hours */,
};

Expand Down Expand Up @@ -136,26 +138,39 @@ export const upsertUserFromRequest = async ({
throw unauthorizedError("Token expired", logger);
}

const { avatar_url, name, user_name, email_verified, sub, picture } =
payload.user_metadata;
const profileInfo = insertUsersSchema.safeParse({
email: payload.email.toLowerCase(),
isEmailVerified: email_verified,
imageUrl: avatar_url ? avatar_url : picture ? picture : "",
externalId: sub,
name,
username: user_name ?? getUsername(),
publicMetadata: payload,
});

if (profileInfo.success === false) {
logger.error("Could not parse profile info", profileInfo.error);
throw new Error("Could not parse profile info", profileInfo.error);
}
if (payload.audience && preventUserUpdate.has(payload.audience)) {
const userId = payload.user_metadata.sub;

logger.info(`Preventing update for user ID: ${userId}`);
const user = await findUserByID(DB, userId);

if (!user) {
throw applicationError("User not found", ServiceErrors.FORBIDDEN, logger);
}

logger.info(`Updating profile Info for user ID: ${sub}`);
return user;
} else {
const { avatar_url, name, user_name, email_verified, sub, picture } =
payload.user_metadata;
const profileInfo = insertUsersSchema.safeParse({
email: payload.email.toLowerCase(),
isEmailVerified: email_verified,
imageUrl: avatar_url ? avatar_url : picture ? picture : "",
externalId: sub,
name,
username: user_name ?? getUsername(),
publicMetadata: payload,
});

if (profileInfo.success === false) {
logger.error("Could not parse profile info", profileInfo.error);
throw new Error("Could not parse profile info", profileInfo.error);
}

logger.info(`Updating profile Info for user ID: ${sub}`);

return updateUserProfileInfo(DB, profileInfo.data, logger);
return updateUserProfileInfo(DB, profileInfo.data, logger);
}
};

export const logPossibleUserIdFromJWT = (
Expand Down
1 change: 1 addition & 0 deletions src/authn/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export type TokenPayload = {
sub: string;
email: string;
phone: string;
audience?: string;
app_metadata: { provider: string; providers: string[] };
user_metadata: {
avatar_url: string;
Expand Down
4 changes: 2 additions & 2 deletions src/schema/user/mutations.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { eq } from "drizzle-orm";
import { GraphQLError } from "graphql";

import { createAuthToken } from "~/authn";
import { createMinimalAuthToken } from "~/authn";
import { builder } from "~/builder";
import {
PronounsEnum,
Expand Down Expand Up @@ -199,7 +199,7 @@ builder.mutationField("retoolToken", (t) =>

const selectedUser = selectUsersSchema.parse(user);

const token = await createAuthToken(
const token = await createMinimalAuthToken(
selectedUser,
ctx.SUPABASE_JWT_ENCODER,
);
Expand Down
19 changes: 11 additions & 8 deletions src/schema/user/tests/token.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,19 +56,22 @@ describe("User", () => {
assert.equal(verified, true);

const decodedToken = decode<{
user_metadata: USER;
audience: string;
user_metadata: {
sub: string;
};
}>(token);

const userTokenData = decodedToken?.payload?.user_metadata;

assert.equal(userTokenData?.email, user1.email);
if (!decodedToken.payload) {
throw new Error("User token data not found");
}

assert.equal(userTokenData?.isSuperAdmin, true);
const { user_metadata: userTokenData, audience } = decodedToken.payload;

assert.equal(userTokenData?.isRetoolEnabled, true);
assert.equal(userTokenData?.sub, user1.id);

assert.equal(userTokenData?.isEmailVerified, true);
assert.equal(Object.keys(userTokenData).length, 1);

assert.equal(userTokenData?.id, user1.id);
assert.equal(audience, "retool");
});
});

0 comments on commit ea55905

Please sign in to comment.