Skip to content

Commit 0516f98

Browse files
authored
add state param to oauth provider (#529)
1 parent 3d76bbe commit 0516f98

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

src/client/auth.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,31 @@ describe("OAuth Authorization", () => {
366366
expect(authorizationUrl.searchParams.has("scope")).toBe(false);
367367
});
368368

369+
it("includes state parameter when provided", async () => {
370+
const { authorizationUrl } = await startAuthorization(
371+
"https://auth.example.com",
372+
{
373+
clientInformation: validClientInfo,
374+
redirectUrl: "http://localhost:3000/callback",
375+
state: "foobar",
376+
}
377+
);
378+
379+
expect(authorizationUrl.searchParams.get("state")).toBe("foobar");
380+
});
381+
382+
it("excludes state parameter when not provided", async () => {
383+
const { authorizationUrl } = await startAuthorization(
384+
"https://auth.example.com",
385+
{
386+
clientInformation: validClientInfo,
387+
redirectUrl: "http://localhost:3000/callback",
388+
}
389+
);
390+
391+
expect(authorizationUrl.searchParams.has("state")).toBe(false);
392+
});
393+
369394
it("uses metadata authorization_endpoint when provided", async () => {
370395
const { authorizationUrl } = await startAuthorization(
371396
"https://auth.example.com",

src/client/auth.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ export interface OAuthClientProvider {
2121
*/
2222
get clientMetadata(): OAuthClientMetadata;
2323

24+
/**
25+
* Returns a OAuth2 state parameter.
26+
*/
27+
state?(): string | Promise<string>;
28+
2429
/**
2530
* Loads information about this OAuth client, as registered already with the
2631
* server, or returns `undefined` if the client is not registered with the
@@ -162,10 +167,13 @@ export async function auth(
162167
}
163168
}
164169

170+
const state = provider.state ? await provider.state() : undefined;
171+
165172
// Start new authorization flow
166173
const { authorizationUrl, codeVerifier } = await startAuthorization(authorizationServerUrl, {
167174
metadata,
168175
clientInformation,
176+
state,
169177
redirectUrl: provider.redirectUrl,
170178
scope: scope || provider.clientMetadata.scope,
171179
});
@@ -301,11 +309,13 @@ export async function startAuthorization(
301309
clientInformation,
302310
redirectUrl,
303311
scope,
312+
state,
304313
}: {
305314
metadata?: OAuthMetadata;
306315
clientInformation: OAuthClientInformation;
307316
redirectUrl: string | URL;
308317
scope?: string;
318+
state?: string;
309319
},
310320
): Promise<{ authorizationUrl: URL; codeVerifier: string }> {
311321
const responseType = "code";
@@ -347,6 +357,10 @@ export async function startAuthorization(
347357
);
348358
authorizationUrl.searchParams.set("redirect_uri", String(redirectUrl));
349359

360+
if (state) {
361+
authorizationUrl.searchParams.set("state", state);
362+
}
363+
350364
if (scope) {
351365
authorizationUrl.searchParams.set("scope", scope);
352366
}

0 commit comments

Comments
 (0)