diff --git a/.changeset/harness-oauth-binding.md b/.changeset/harness-oauth-binding.md new file mode 100644 index 0000000..6c733ee --- /dev/null +++ b/.changeset/harness-oauth-binding.md @@ -0,0 +1,5 @@ +--- +"seamless-cli": patch +--- + +`seamless verify` now forwards the `binding` that `POST /oauth/:providerId/start` returns in the body of its OAuth callbacks, so the OAuth specs pass against an auth API that ties the callback to the browser that started the flow. Older API images ignore the extra field. diff --git a/verify/harness/lib/cutoverFlows.ts b/verify/harness/lib/cutoverFlows.ts index 781ab87..117fc39 100644 --- a/verify/harness/lib/cutoverFlows.ts +++ b/verify/harness/lib/cutoverFlows.ts @@ -87,7 +87,8 @@ export async function legacySignIn( }); expect(start.ok(), `oauth start -> ${start.status()} ${await start.text()}`).toBeTruthy(); - const authorizationUrl = new URL((await start.json()).authorizationUrl); + const { authorizationUrl: startUrl, binding } = await start.json(); + const authorizationUrl = new URL(startUrl); authorizationUrl.searchParams.set('mock_sub', profile.sub); authorizationUrl.searchParams.set('mock_oid', profile.oid); authorizationUrl.searchParams.set('mock_email', profile.email); @@ -100,6 +101,7 @@ export async function legacySignIn( data: { code: redirected.searchParams.get('code'), state: redirected.searchParams.get('state'), + binding, }, }); } diff --git a/verify/harness/lib/flows.ts b/verify/harness/lib/flows.ts index 4040f64..78d9e92 100644 --- a/verify/harness/lib/flows.ts +++ b/verify/harness/lib/flows.ts @@ -149,7 +149,7 @@ export async function oauthLogin( ): Promise { const start = await ctx.post(`${pathPrefix}/oauth/${providerId}/start`, { data: {} }); expect(start.ok(), `oauth start -> ${start.status()} ${await start.text()}`).toBeTruthy(); - const { authorizationUrl } = await start.json(); + const { authorizationUrl, binding } = await start.json(); const authorize = await ctx.get(authorizationUrl, { maxRedirects: 0 }); expect(authorize.status(), `authorize redirects with a code (got ${authorize.status()})`).toBe( @@ -161,7 +161,7 @@ export async function oauthLogin( expect(code, 'authorize returns an auth code').toBeTruthy(); const callback = await ctx.post(`${pathPrefix}/oauth/${providerId}/callback`, { - data: { code, state }, + data: { code, state, binding }, }); expect(callback.ok(), `oauth callback -> ${callback.status()} ${await callback.text()}`).toBeTruthy(); const body = await callback.json();