Skip to content

Commit 016c7e9

Browse files
authored
Prepare keys for environment migration (#2090)
Part of OPS-3849.
1 parent 9b4caf0 commit 016c7e9

5 files changed

Lines changed: 40 additions & 29 deletions

File tree

packages/server/api/src/app/flow-template/cloud-template.controller.ts

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ import {
88
OpenOpsId,
99
PUBLIC_ROUTE_POLICY,
1010
} from '@openops/shared';
11-
import { FastifyRequest } from 'fastify';
12-
import { JwtPayload } from 'jsonwebtoken';
1311
import {
1412
allowAllOriginsHookHandler,
1513
registerOptionsEndpoint,
1614
} from '../helper/allow-all-origins-hook-handler';
17-
import { getVerifiedUser } from '../user-info/cloud-auth';
15+
import {
16+
filterValidKeys,
17+
verifyUserWithPublicKeys,
18+
} from '../user-info/cloud-auth';
1819
import { flowTemplateService } from './flow-template.service';
1920

2021
export const cloudTemplateController: FastifyPluginAsyncTypebox = async (
@@ -32,7 +33,9 @@ export const cloudTemplateController: FastifyPluginAsyncTypebox = async (
3233
return;
3334
}
3435

35-
const publicKeys = [publicKey];
36+
const oldPublicKey = system.get(AppSystemProp.OLD_FRONTEGG_PUBLIC_KEY);
37+
const publicKeys = filterValidKeys([publicKey, oldPublicKey]);
38+
3639
// cloud templates are available on any origin
3740
app.addHook('onRequest', allowAllOriginsHookHandler);
3841

@@ -112,18 +115,3 @@ export const cloudTemplateController: FastifyPluginAsyncTypebox = async (
112115
},
113116
);
114117
};
115-
116-
function verifyUserWithPublicKeys(
117-
request: FastifyRequest,
118-
keysToCheck: string[],
119-
): string | JwtPayload | undefined {
120-
for (const key of keysToCheck) {
121-
const user = getVerifiedUser(request, key);
122-
123-
if (user) {
124-
return user;
125-
}
126-
}
127-
128-
return undefined;
129-
}

packages/server/api/src/app/user-info/cloud-auth.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const getCloudToken = (request: FastifyRequest): string | undefined => {
1919
return headerToken;
2020
};
2121

22-
export function getVerifiedUser(
22+
function getVerifiedUser(
2323
request: FastifyRequest,
2424
publicKey: string,
2525
): string | JwtPayload | undefined {
@@ -34,3 +34,22 @@ export function getVerifiedUser(
3434
return undefined;
3535
}
3636
}
37+
38+
export function verifyUserWithPublicKeys(
39+
request: FastifyRequest,
40+
keysToCheck: string[],
41+
): string | JwtPayload | undefined {
42+
for (const key of keysToCheck) {
43+
const user = getVerifiedUser(request, key);
44+
45+
if (user) {
46+
return user;
47+
}
48+
}
49+
50+
return undefined;
51+
}
52+
53+
export function filterValidKeys(keys: unknown[]): string[] {
54+
return keys.filter((key): key is string => Boolean(key));
55+
}

packages/server/api/src/app/user-info/user-info.module.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
allowAllOriginsHookHandler,
66
registerOptionsEndpoint,
77
} from '../helper/allow-all-origins-hook-handler';
8-
import { getVerifiedUser } from './cloud-auth';
8+
import { filterValidKeys, verifyUserWithPublicKeys } from './cloud-auth';
99

1010
export const userInfoModule: FastifyPluginAsyncTypebox = async (app) => {
1111
await app.register(userInfoController, { prefix: '/v1/user-info' });
@@ -24,6 +24,9 @@ export const userInfoController: FastifyPluginAsyncTypebox = async (app) => {
2424
return;
2525
}
2626

27+
const oldPublicKey = system.get(AppSystemProp.OLD_FRONTEGG_PUBLIC_KEY);
28+
const publicKeys = filterValidKeys([publicKey, oldPublicKey]);
29+
2730
// user-info is available on any origin
2831
app.addHook('onRequest', allowAllOriginsHookHandler);
2932
registerOptionsEndpoint(app);
@@ -38,7 +41,7 @@ export const userInfoController: FastifyPluginAsyncTypebox = async (app) => {
3841
},
3942
},
4043
async (request, reply) => {
41-
const user = getVerifiedUser(request, publicKey);
44+
const user = verifyUserWithPublicKeys(request, publicKeys);
4245

4346
if (!user) {
4447
return reply.status(401).send();

packages/server/api/test/integration/cloud/cloud/cloud-auth.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { FastifyRequest } from 'fastify';
22
import jwt from 'jsonwebtoken';
3-
import { getVerifiedUser } from '../../../../src/app/user-info/cloud-auth';
3+
import { verifyUserWithPublicKeys } from '../../../../src/app/user-info/cloud-auth';
44

55
type MockFastifyRequest = FastifyRequest & {
66
cookies: Record<string, string>;
@@ -37,7 +37,7 @@ function createMockRequest(options: {
3737
} as unknown as MockFastifyRequest;
3838
}
3939

40-
describe('getVerifiedUser', () => {
40+
describe('Verify user with public keys', () => {
4141
const publicKey = 'test-public-key';
4242

4343
beforeEach(() => {
@@ -47,7 +47,7 @@ describe('getVerifiedUser', () => {
4747
it('should return undefined when no token is present (no header, no cookie)', () => {
4848
const mockRequest = createMockRequest({ headers: {}, cookies: {} });
4949

50-
const result = getVerifiedUser(mockRequest, publicKey);
50+
const result = verifyUserWithPublicKeys(mockRequest, [publicKey]);
5151

5252
expect(result).toBeUndefined();
5353
expect(jwt.verify).not.toHaveBeenCalled();
@@ -61,7 +61,7 @@ describe('getVerifiedUser', () => {
6161
cookies: {},
6262
});
6363

64-
const result = getVerifiedUser(mockRequest, publicKey);
64+
const result = verifyUserWithPublicKeys(mockRequest, [publicKey]);
6565

6666
expect(jwt.verify).toHaveBeenCalledWith('header-token', publicKey, {
6767
algorithms: ['RS256'],
@@ -77,7 +77,7 @@ describe('getVerifiedUser', () => {
7777
cookies: { 'cloud-token': 'cookie-token' },
7878
});
7979

80-
const result = getVerifiedUser(mockRequest, publicKey);
80+
const result = verifyUserWithPublicKeys(mockRequest, [publicKey]);
8181

8282
expect(jwt.verify).toHaveBeenCalledWith('cookie-token', publicKey, {
8383
algorithms: ['RS256'],
@@ -93,7 +93,7 @@ describe('getVerifiedUser', () => {
9393
cookies: {},
9494
});
9595

96-
const result = getVerifiedUser(mockRequest, publicKey);
96+
const result = verifyUserWithPublicKeys(mockRequest, [publicKey]);
9797

9898
expect(jwt.verify).toHaveBeenCalledWith('cookie-header-token', publicKey, {
9999
algorithms: ['RS256'],
@@ -110,7 +110,7 @@ describe('getVerifiedUser', () => {
110110
cookies: {},
111111
});
112112

113-
const result = getVerifiedUser(mockRequest, publicKey);
113+
const result = verifyUserWithPublicKeys(mockRequest, [publicKey]);
114114

115115
expect(result).toBeUndefined();
116116
expect(jwt.verify).toHaveBeenCalledWith('bad-token', publicKey, {

packages/server/shared/src/lib/system/system-prop.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ export enum AppSystemProp {
8787

8888
FRONTEGG_URL = 'FRONTEGG_URL',
8989
FRONTEGG_PUBLIC_KEY = 'FRONTEGG_PUBLIC_KEY',
90+
OLD_FRONTEGG_PUBLIC_KEY = 'OLD_FRONTEGG_PUBLIC_KEY', // TODO: Can be removed after 13/04/2026
9091

9192
ENGINE_URL = 'ENGINE_URL',
9293
TELEMETRY_MODE = 'TELEMETRY_MODE',

0 commit comments

Comments
 (0)