Skip to content

Commit ea55905

Browse files
committed
Update token creation
1 parent 7e15348 commit ea55905

File tree

4 files changed

+53
-34
lines changed

4 files changed

+53
-34
lines changed

src/authn/index.ts

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ import {
99
updateUserProfileInfo,
1010
} from "~/datasources/queries/users";
1111
import { getUsername } from "~/datasources/queries/utils/createUsername";
12-
import { unauthorizedError } from "~/errors";
12+
import { applicationError, ServiceErrors, unauthorizedError } from "~/errors";
13+
14+
const preventUserUpdate = new Set<"retool">(["retool"]);
1315

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

28-
export const createAuthToken = async (user: USER, SECRET: string) => {
30+
export const createMinimalAuthToken = async (user: USER, SECRET: string) => {
2931
const payload = {
30-
audience: "retool-autenticated",
31-
id: user.id,
32-
email: user.email,
33-
user_metadata: user,
32+
audience: "retool",
33+
user_metadata: {
34+
sub: user.id,
35+
},
3436
exp: Date.now() + 60 * 60 * 24 * 1000 /* 24 hours */,
3537
};
3638

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

139-
const { avatar_url, name, user_name, email_verified, sub, picture } =
140-
payload.user_metadata;
141-
const profileInfo = insertUsersSchema.safeParse({
142-
email: payload.email.toLowerCase(),
143-
isEmailVerified: email_verified,
144-
imageUrl: avatar_url ? avatar_url : picture ? picture : "",
145-
externalId: sub,
146-
name,
147-
username: user_name ?? getUsername(),
148-
publicMetadata: payload,
149-
});
150-
151-
if (profileInfo.success === false) {
152-
logger.error("Could not parse profile info", profileInfo.error);
153-
throw new Error("Could not parse profile info", profileInfo.error);
154-
}
141+
if (payload.audience && preventUserUpdate.has(payload.audience)) {
142+
const userId = payload.user_metadata.sub;
143+
144+
logger.info(`Preventing update for user ID: ${userId}`);
145+
const user = await findUserByID(DB, userId);
146+
147+
if (!user) {
148+
throw applicationError("User not found", ServiceErrors.FORBIDDEN, logger);
149+
}
155150

156-
logger.info(`Updating profile Info for user ID: ${sub}`);
151+
return user;
152+
} else {
153+
const { avatar_url, name, user_name, email_verified, sub, picture } =
154+
payload.user_metadata;
155+
const profileInfo = insertUsersSchema.safeParse({
156+
email: payload.email.toLowerCase(),
157+
isEmailVerified: email_verified,
158+
imageUrl: avatar_url ? avatar_url : picture ? picture : "",
159+
externalId: sub,
160+
name,
161+
username: user_name ?? getUsername(),
162+
publicMetadata: payload,
163+
});
164+
165+
if (profileInfo.success === false) {
166+
logger.error("Could not parse profile info", profileInfo.error);
167+
throw new Error("Could not parse profile info", profileInfo.error);
168+
}
169+
170+
logger.info(`Updating profile Info for user ID: ${sub}`);
157171

158-
return updateUserProfileInfo(DB, profileInfo.data, logger);
172+
return updateUserProfileInfo(DB, profileInfo.data, logger);
173+
}
159174
};
160175

161176
export const logPossibleUserIdFromJWT = (

src/authn/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export type TokenPayload = {
77
sub: string;
88
email: string;
99
phone: string;
10+
audience?: string;
1011
app_metadata: { provider: string; providers: string[] };
1112
user_metadata: {
1213
avatar_url: string;

src/schema/user/mutations.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { eq } from "drizzle-orm";
22
import { GraphQLError } from "graphql";
33

4-
import { createAuthToken } from "~/authn";
4+
import { createMinimalAuthToken } from "~/authn";
55
import { builder } from "~/builder";
66
import {
77
PronounsEnum,
@@ -199,7 +199,7 @@ builder.mutationField("retoolToken", (t) =>
199199

200200
const selectedUser = selectUsersSchema.parse(user);
201201

202-
const token = await createAuthToken(
202+
const token = await createMinimalAuthToken(
203203
selectedUser,
204204
ctx.SUPABASE_JWT_ENCODER,
205205
);

src/schema/user/tests/token.test.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,22 @@ describe("User", () => {
5656
assert.equal(verified, true);
5757

5858
const decodedToken = decode<{
59-
user_metadata: USER;
59+
audience: string;
60+
user_metadata: {
61+
sub: string;
62+
};
6063
}>(token);
6164

62-
const userTokenData = decodedToken?.payload?.user_metadata;
63-
64-
assert.equal(userTokenData?.email, user1.email);
65+
if (!decodedToken.payload) {
66+
throw new Error("User token data not found");
67+
}
6568

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

68-
assert.equal(userTokenData?.isRetoolEnabled, true);
71+
assert.equal(userTokenData?.sub, user1.id);
6972

70-
assert.equal(userTokenData?.isEmailVerified, true);
73+
assert.equal(Object.keys(userTokenData).length, 1);
7174

72-
assert.equal(userTokenData?.id, user1.id);
75+
assert.equal(audience, "retool");
7376
});
7477
});

0 commit comments

Comments
 (0)