| 1 | import { afterEach, describe, expect, it, vi } from 'vitest';
|
| 2 | import { GET as authorizationMetadata } from '../api/oauth-authorization-server.js';
|
| 3 | import { POST as registerClient } from '../api/oauth-register.js';
|
| 4 |
|
| 5 | afterEach(() => {
|
| 6 | vi.restoreAllMocks();
|
| 7 | vi.unstubAllGlobals();
|
| 8 | });
|
| 9 |
|
| 10 | describe('hosted OAuth compatibility proxy', () => {
|
| 11 | it('publishes OpenClasp discovery with Auth0 endpoints and the MCP audience', async () => {
|
| 12 | vi.stubGlobal(
|
| 13 | 'fetch',
|
| 14 | vi.fn().mockResolvedValue(
|
| 15 | Response.json({
|
| 16 | issuer: 'https://tenant.auth0.com/',
|
| 17 | authorization_endpoint: 'https://tenant.auth0.com/authorize',
|
| 18 | token_endpoint: 'https://tenant.auth0.com/oauth/token',
|
| 19 | registration_endpoint: 'https://tenant.auth0.com/oidc/register',
|
| 20 | response_types_supported: ['code'],
|
| 21 | }),
|
| 22 | ),
|
| 23 | );
|
| 24 |
|
| 25 | const response = await authorizationMetadata(
|
| 26 | new Request('https://openclasp.example/.well-known/oauth-authorization-server'),
|
| 27 | );
|
| 28 | const metadata = (await response.json()) as Record<string, unknown>;
|
| 29 | expect(response.status).toBe(200);
|
| 30 | expect(metadata).toMatchObject({
|
| 31 | issuer: 'https://openclasp.example',
|
| 32 | registration_endpoint: 'https://openclasp.example/oauth/register',
|
| 33 | scopes_supported: ['mcp:access'],
|
| 34 | });
|
| 35 | expect(String(metadata.authorization_endpoint)).toContain(
|
| 36 | 'audience=https%3A%2F%2Fopenclasp.vercel.app%2Fmcp',
|
| 37 | );
|
| 38 | });
|
| 39 |
|
| 40 | it('forwards dynamic client registration without exposing credentials', async () => {
|
| 41 | const upstream = vi.fn().mockResolvedValue(
|
| 42 | Response.json(
|
| 43 | {
|
| 44 | client_id: 'tpc_test',
|
| 45 | redirect_uris: ['http://localhost:8787/callback'],
|
| 46 | token_endpoint_auth_method: 'none',
|
| 47 | },
|
| 48 | { status: 201 },
|
| 49 | ),
|
| 50 | );
|
| 51 | vi.stubGlobal('fetch', upstream);
|
| 52 | vi.spyOn(console, 'info').mockImplementation(() => undefined);
|
| 53 | const input = {
|
| 54 | client_name: 'MCP client',
|
| 55 | redirect_uris: ['http://localhost:8787/callback'],
|
| 56 | token_endpoint_auth_method: 'none',
|
| 57 | scope: 'mcp:access',
|
| 58 | };
|
| 59 |
|
| 60 | const response = await registerClient(
|
| 61 | new Request('https://openclasp.example/oauth/register', {
|
| 62 | method: 'POST',
|
| 63 | headers: { 'content-type': 'application/json' },
|
| 64 | body: JSON.stringify(input),
|
| 65 | }),
|
| 66 | );
|
| 67 | expect(response.status).toBe(201);
|
| 68 | expect(upstream).toHaveBeenCalledOnce();
|
| 69 | expect(upstream.mock.calls[0]?.[0]).toBe(
|
| 70 | 'https://icfg-0ua6bab8d4omtfolx72mrhzo.us.auth0.com/oidc/register',
|
| 71 | );
|
| 72 | expect(JSON.parse(String(upstream.mock.calls[0]?.[1]?.body))).toEqual(input);
|
| 73 | });
|
| 74 | });
|