Skip to content

Commit 54f643c

Browse files
committed
Validate redirect URIs _as_ URIs
1 parent 9dc4a4f commit 54f643c

File tree

3 files changed

+13
-3
lines changed

3 files changed

+13
-3
lines changed

src/server/auth/handlers/authorize.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { RequestHandler } from "express";
22
import { z } from "zod";
33
import { OAuthRegisteredClientsStore } from "../clients.js";
4+
import { isValidUrl } from "../validation.js";
45

56
export type AuthorizationHandlerOptions = {
67
/**
@@ -11,7 +12,7 @@ export type AuthorizationHandlerOptions = {
1112

1213
const ClientAuthorizationParamsSchema = z.object({
1314
client_id: z.string(),
14-
redirect_uri: z.string().optional(),
15+
redirect_uri: z.string().optional().refine((value) => value === undefined || isValidUrl(value), { message: "redirect_uri must be a valid URL" }),
1516
});
1617

1718
const RequestAuthorizationParamsSchema = z.object({
@@ -45,7 +46,7 @@ export function authorizationHandler({ store }: AuthorizationHandlerOptions): Re
4546

4647
if (redirect_uri !== undefined) {
4748
if (!client.redirect_uris.includes(redirect_uri)) {
48-
res.status(400).end("Bad Request: invalid redirect_uri");
49+
res.status(400).end("Bad Request: unregistered redirect_uri");
4950
return;
5051
}
5152
} else if (client.redirect_uris.length === 1) {

src/server/auth/validation.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export function isValidUrl(s: string): boolean {
2+
try {
3+
new URL(s);
4+
return true;
5+
} catch (error) {
6+
return false;
7+
}
8+
}

src/shared/auth.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { z } from "zod";
2+
import { isValidUrl } from "../server/auth/validation.js";
23

34
/**
45
* RFC 8414 OAuth 2.0 Authorization Server Metadata
@@ -61,7 +62,7 @@ export const OAuthErrorSchema = z
6162
* RFC 7591 OAuth 2.0 Dynamic Client Registration metadata
6263
*/
6364
export const OAuthClientMetadataSchema = z.object({
64-
redirect_uris: z.array(z.string()),
65+
redirect_uris: z.array(z.string()).refine((uris) => uris.every(isValidUrl), { message: "redirect_uris must contain valid URLs" }),
6566
token_endpoint_auth_method: z.string().optional(),
6667
grant_types: z.array(z.string()).optional(),
6768
response_types: z.array(z.string()).optional(),

0 commit comments

Comments
 (0)