Skip to content

Commit f1f55ef

Browse files
authored
chore(fastify): Add machine auth integration test (#8230)
1 parent aa63796 commit f1f55ef

2 files changed

Lines changed: 176 additions & 0 deletions

File tree

integration/templates/fastify-vite/src/client/main.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ document.addEventListener('DOMContentLoaded', async function () {
99
await clerk.load({
1010
ui: { ClerkUI },
1111
});
12+
window.Clerk = clerk;
1213

1314
if (clerk.isSignedIn) {
1415
document.getElementById('app')!.innerHTML = `
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
import { test } from '@playwright/test';
2+
3+
import { appConfigs } from '../../presets';
4+
import type { MachineAuthTestAdapter } from '../../testUtils/machineAuthHelpers';
5+
import {
6+
registerApiKeyAuthTests,
7+
registerM2MAuthTests,
8+
registerOAuthAuthTests,
9+
} from '../../testUtils/machineAuthHelpers';
10+
11+
const createMainFile = () => `
12+
import 'dotenv/config';
13+
14+
import express from 'express';
15+
import Fastify from 'fastify';
16+
import ViteExpress from 'vite-express';
17+
import { machineRoutes } from './routes/machine';
18+
19+
async function start() {
20+
const fastify = Fastify();
21+
22+
await fastify.register(machineRoutes);
23+
24+
await fastify.listen({ port: 0, host: '127.0.0.1' });
25+
const fastifyAddress = fastify.server.address();
26+
const fastifyPort = typeof fastifyAddress === 'object' ? fastifyAddress?.port : 0;
27+
28+
const expressApp = express();
29+
30+
expressApp.use('/api', async (req: any, res: any) => {
31+
const url = \`http://127.0.0.1:\${fastifyPort}\${req.url}\`;
32+
const headers: Record<string, string> = {};
33+
for (const [key, value] of Object.entries(req.headers)) {
34+
if (typeof value === 'string') {
35+
headers[key] = value;
36+
} else if (Array.isArray(value)) {
37+
headers[key] = value.join(', ');
38+
}
39+
}
40+
41+
const response = await fetch(url, {
42+
method: req.method,
43+
headers,
44+
body: ['GET', 'HEAD'].includes(req.method) ? undefined : req,
45+
// @ts-expect-error duplex needed for streaming request bodies
46+
duplex: ['GET', 'HEAD'].includes(req.method) ? undefined : 'half',
47+
redirect: 'manual',
48+
});
49+
50+
res.status(response.status);
51+
response.headers.forEach((value: string, key: string) => {
52+
res.setHeader(key, value);
53+
});
54+
const body = await response.arrayBuffer();
55+
res.send(Buffer.from(body));
56+
});
57+
58+
const port = parseInt(process.env.PORT as string) || 3002;
59+
ViteExpress.listen(expressApp, port, () => console.log(\`Server is listening on port \${port}...\`));
60+
}
61+
62+
start();
63+
`;
64+
65+
const adapter: MachineAuthTestAdapter = {
66+
baseConfig: appConfigs.fastify.vite,
67+
apiKey: {
68+
path: '/api/me',
69+
addRoutes: config =>
70+
config
71+
.addFile(
72+
'src/server/routes/machine.ts',
73+
() => `
74+
import { clerkPlugin, getAuth } from '@clerk/fastify';
75+
import type { FastifyInstance } from 'fastify';
76+
77+
export const machineRoutes = async (fastify: FastifyInstance) => {
78+
await fastify.register(clerkPlugin, {
79+
publishableKey: process.env.VITE_CLERK_PUBLISHABLE_KEY,
80+
});
81+
82+
fastify.get('/me', async (request, reply) => {
83+
const { userId, tokenType } = getAuth(request, { acceptsToken: 'api_key' });
84+
85+
if (!userId) {
86+
return reply.code(401).send('Unauthorized');
87+
}
88+
89+
return reply.send({ userId, tokenType });
90+
});
91+
92+
fastify.post('/me', async (request, reply) => {
93+
const authObject = getAuth(request, { acceptsToken: ['api_key', 'session_token'] });
94+
95+
if (!authObject.isAuthenticated) {
96+
return reply.code(401).send('Unauthorized');
97+
}
98+
99+
return reply.send({ userId: authObject.userId, tokenType: authObject.tokenType });
100+
});
101+
};
102+
`,
103+
)
104+
.addFile('src/server/main.ts', () => createMainFile()),
105+
},
106+
m2m: {
107+
path: '/api/m2m',
108+
addRoutes: config =>
109+
config
110+
.addFile(
111+
'src/server/routes/machine.ts',
112+
() => `
113+
import { clerkPlugin, getAuth } from '@clerk/fastify';
114+
import type { FastifyInstance } from 'fastify';
115+
116+
export const machineRoutes = async (fastify: FastifyInstance) => {
117+
await fastify.register(clerkPlugin, {
118+
publishableKey: process.env.VITE_CLERK_PUBLISHABLE_KEY,
119+
});
120+
121+
fastify.get('/m2m', async (request, reply) => {
122+
const { subject, tokenType, machineId } = getAuth(request, { acceptsToken: 'm2m_token' });
123+
124+
if (!machineId) {
125+
return reply.code(401).send('Unauthorized');
126+
}
127+
128+
return reply.send({ subject, tokenType });
129+
});
130+
};
131+
`,
132+
)
133+
.addFile('src/server/main.ts', () => createMainFile()),
134+
},
135+
oauth: {
136+
verifyPath: '/api/oauth-verify',
137+
callbackPath: '/api/oauth/callback',
138+
addRoutes: config =>
139+
config
140+
.addFile(
141+
'src/server/routes/machine.ts',
142+
() => `
143+
import { clerkPlugin, getAuth } from '@clerk/fastify';
144+
import type { FastifyInstance } from 'fastify';
145+
146+
export const machineRoutes = async (fastify: FastifyInstance) => {
147+
await fastify.register(clerkPlugin, {
148+
publishableKey: process.env.VITE_CLERK_PUBLISHABLE_KEY,
149+
});
150+
151+
fastify.get('/oauth-verify', async (request, reply) => {
152+
const { userId, tokenType } = getAuth(request, { acceptsToken: 'oauth_token' });
153+
154+
if (!userId) {
155+
return reply.code(401).send('Unauthorized');
156+
}
157+
158+
return reply.send({ userId, tokenType });
159+
});
160+
161+
fastify.get('/oauth/callback', async (_request, reply) => {
162+
return reply.send({ message: 'OAuth callback received' });
163+
});
164+
};
165+
`,
166+
)
167+
.addFile('src/server/main.ts', () => createMainFile()),
168+
},
169+
};
170+
171+
test.describe('Fastify machine authentication @machine', () => {
172+
registerApiKeyAuthTests(adapter);
173+
registerM2MAuthTests(adapter);
174+
registerOAuthAuthTests(adapter);
175+
});

0 commit comments

Comments
 (0)