CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history
well-known.test.ts
Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.
| 369ad65 | 1 | import { describe, it, expect, beforeAll } from "bun:test"; |
| 2 | import app from "../app"; | |
| 3 | import { SUPPORTED_SCOPES } from "../lib/oauth"; | |
| 4 | ||
| 5 | // These endpoints are what claude.ai / Cursor / Copilot read first to learn | |
| 6 | // how to authenticate. They must be anonymous, JSON, and advertise only | |
| 7 | // endpoints that actually exist. | |
| 8 | ||
| 9 | beforeAll(() => { | |
| 10 | process.env.APP_BASE_URL = "https://gluecron.com"; | |
| 11 | }); | |
| 12 | ||
| 13 | describe("RFC 8414 — authorization server metadata", () => { | |
| 14 | it("serves valid metadata anonymously", async () => { | |
| 15 | const res = await app.request("/.well-known/oauth-authorization-server"); | |
| 16 | expect(res.status).toBe(200); | |
| 17 | expect(res.headers.get("content-type") || "").toContain("application/json"); | |
| 18 | const doc = await res.json(); | |
| 19 | expect(doc.issuer).toBe("https://gluecron.com"); | |
| 20 | expect(doc.authorization_endpoint).toBe("https://gluecron.com/oauth/authorize"); | |
| 21 | expect(doc.token_endpoint).toBe("https://gluecron.com/oauth/token"); | |
| 22 | expect(doc.revocation_endpoint).toBe("https://gluecron.com/oauth/revoke"); | |
| 23 | }); | |
| 24 | ||
| 25 | it("advertises PKCE S256 and the authorization_code + refresh grants", async () => { | |
| 26 | const doc = await ( | |
| 27 | await app.request("/.well-known/oauth-authorization-server") | |
| 28 | ).json(); | |
| 29 | expect(doc.code_challenge_methods_supported).toContain("S256"); | |
| 30 | expect(doc.grant_types_supported).toContain("authorization_code"); | |
| 31 | expect(doc.grant_types_supported).toContain("refresh_token"); | |
| 32 | expect(doc.response_types_supported).toEqual(["code"]); | |
| 33 | }); | |
| 34 | ||
| 35 | it("advertises exactly the supported scopes", async () => { | |
| 36 | const doc = await ( | |
| 37 | await app.request("/.well-known/oauth-authorization-server") | |
| 38 | ).json(); | |
| 39 | expect(doc.scopes_supported).toEqual([...SUPPORTED_SCOPES]); | |
| 40 | }); | |
| 41 | ||
| 42 | it("supports the public-client (none) auth method for PKCE apps", async () => { | |
| 43 | const doc = await ( | |
| 44 | await app.request("/.well-known/oauth-authorization-server") | |
| 45 | ).json(); | |
| 46 | expect(doc.token_endpoint_auth_methods_supported).toContain("none"); | |
| 47 | }); | |
| 48 | ||
| 4c27627 | 49 | it("advertises the registration_endpoint (RFC 7591 DCR is live)", async () => { |
| 369ad65 | 50 | const doc = await ( |
| 51 | await app.request("/.well-known/oauth-authorization-server") | |
| 52 | ).json(); | |
| 4c27627 | 53 | expect(doc.registration_endpoint).toBe("https://gluecron.com/oauth/register"); |
| 54 | }); | |
| 55 | ||
| 56 | it("does NOT advertise introspection until it ships", async () => { | |
| 57 | const doc = await ( | |
| 58 | await app.request("/.well-known/oauth-authorization-server") | |
| 59 | ).json(); | |
| 60 | // Guard: only advertise introspection_endpoint once POST /oauth/introspect | |
| 61 | // actually exists, or clients that probe it will 404. | |
| 369ad65 | 62 | expect(doc.introspection_endpoint).toBeUndefined(); |
| 63 | }); | |
| 64 | }); | |
| 65 | ||
| 66 | describe("RFC 9728 — protected resource metadata", () => { | |
| 67 | it("serves the resource metadata for the MCP endpoint", async () => { | |
| 68 | const res = await app.request("/.well-known/oauth-protected-resource"); | |
| 69 | expect(res.status).toBe(200); | |
| 70 | const doc = await res.json(); | |
| 71 | expect(doc.resource).toBe("https://gluecron.com/mcp"); | |
| 72 | expect(doc.authorization_servers).toEqual(["https://gluecron.com"]); | |
| 73 | expect(doc.bearer_methods_supported).toContain("header"); | |
| 74 | }); | |
| 75 | ||
| 76 | it("also serves the resource-specific /mcp form", async () => { | |
| 77 | const res = await app.request("/.well-known/oauth-protected-resource/mcp"); | |
| 78 | expect(res.status).toBe(200); | |
| 79 | const doc = await res.json(); | |
| 80 | expect(doc.resource).toBe("https://gluecron.com/mcp"); | |
| 81 | }); | |
| 82 | }); |