1
1
import { z } from "zod" ;
2
2
3
+ /**
4
+ * Reusable URL validation that disallows javascript: scheme
5
+ */
6
+ export const SafeUrlSchema = z . string ( ) . url ( )
7
+ . refine (
8
+ ( url ) => URL . canParse ( url ) ,
9
+ { message : "URL must be parseable" }
10
+ ) . refine (
11
+ ( url ) => ! url . toLowerCase ( ) . startsWith ( 'javascript:' ) ,
12
+ { message : "URL cannot use javascript: scheme" }
13
+ ) ;
14
+
15
+
3
16
/**
4
17
* RFC 9728 OAuth Protected Resource Metadata
5
18
*/
6
19
export const OAuthProtectedResourceMetadataSchema = z
7
20
. object ( {
8
21
resource : z . string ( ) . url ( ) ,
9
- authorization_servers : z . array ( z . string ( ) . url ( ) ) . optional ( ) ,
22
+ authorization_servers : z . array ( SafeUrlSchema ) . optional ( ) ,
10
23
jwks_uri : z . string ( ) . url ( ) . optional ( ) ,
11
24
scopes_supported : z . array ( z . string ( ) ) . optional ( ) ,
12
25
bearer_methods_supported : z . array ( z . string ( ) ) . optional ( ) ,
@@ -28,9 +41,9 @@ export const OAuthProtectedResourceMetadataSchema = z
28
41
export const OAuthMetadataSchema = z
29
42
. object ( {
30
43
issuer : z . string ( ) ,
31
- authorization_endpoint : z . string ( ) ,
32
- token_endpoint : z . string ( ) ,
33
- registration_endpoint : z . string ( ) . optional ( ) ,
44
+ authorization_endpoint : SafeUrlSchema ,
45
+ token_endpoint : SafeUrlSchema ,
46
+ registration_endpoint : SafeUrlSchema . optional ( ) ,
34
47
scopes_supported : z . array ( z . string ( ) ) . optional ( ) ,
35
48
response_types_supported : z . array ( z . string ( ) ) ,
36
49
response_modes_supported : z . array ( z . string ( ) ) . optional ( ) ,
@@ -39,8 +52,8 @@ export const OAuthMetadataSchema = z
39
52
token_endpoint_auth_signing_alg_values_supported : z
40
53
. array ( z . string ( ) )
41
54
. optional ( ) ,
42
- service_documentation : z . string ( ) . optional ( ) ,
43
- revocation_endpoint : z . string ( ) . optional ( ) ,
55
+ service_documentation : SafeUrlSchema . optional ( ) ,
56
+ revocation_endpoint : SafeUrlSchema . optional ( ) ,
44
57
revocation_endpoint_auth_methods_supported : z . array ( z . string ( ) ) . optional ( ) ,
45
58
revocation_endpoint_auth_signing_alg_values_supported : z
46
59
. array ( z . string ( ) )
@@ -63,11 +76,11 @@ export const OAuthMetadataSchema = z
63
76
export const OpenIdProviderMetadataSchema = z
64
77
. object ( {
65
78
issuer : z . string ( ) ,
66
- authorization_endpoint : z . string ( ) ,
67
- token_endpoint : z . string ( ) ,
68
- userinfo_endpoint : z . string ( ) . optional ( ) ,
69
- jwks_uri : z . string ( ) ,
70
- registration_endpoint : z . string ( ) . optional ( ) ,
79
+ authorization_endpoint : SafeUrlSchema ,
80
+ token_endpoint : SafeUrlSchema ,
81
+ userinfo_endpoint : SafeUrlSchema . optional ( ) ,
82
+ jwks_uri : SafeUrlSchema ,
83
+ registration_endpoint : SafeUrlSchema . optional ( ) ,
71
84
scopes_supported : z . array ( z . string ( ) ) . optional ( ) ,
72
85
response_types_supported : z . array ( z . string ( ) ) ,
73
86
response_modes_supported : z . array ( z . string ( ) ) . optional ( ) ,
@@ -101,8 +114,8 @@ export const OpenIdProviderMetadataSchema = z
101
114
request_parameter_supported : z . boolean ( ) . optional ( ) ,
102
115
request_uri_parameter_supported : z . boolean ( ) . optional ( ) ,
103
116
require_request_uri_registration : z . boolean ( ) . optional ( ) ,
104
- op_policy_uri : z . string ( ) . optional ( ) ,
105
- op_tos_uri : z . string ( ) . optional ( ) ,
117
+ op_policy_uri : SafeUrlSchema . optional ( ) ,
118
+ op_tos_uri : SafeUrlSchema . optional ( ) ,
106
119
} )
107
120
. passthrough ( ) ;
108
121
@@ -146,18 +159,18 @@ export const OAuthErrorResponseSchema = z
146
159
* RFC 7591 OAuth 2.0 Dynamic Client Registration metadata
147
160
*/
148
161
export const OAuthClientMetadataSchema = z . object ( {
149
- redirect_uris : z . array ( z . string ( ) ) . refine ( ( uris ) => uris . every ( ( uri ) => URL . canParse ( uri ) ) , { message : "redirect_uris must contain valid URLs" } ) ,
162
+ redirect_uris : z . array ( SafeUrlSchema ) ,
150
163
token_endpoint_auth_method : z . string ( ) . optional ( ) ,
151
164
grant_types : z . array ( z . string ( ) ) . optional ( ) ,
152
165
response_types : z . array ( z . string ( ) ) . optional ( ) ,
153
166
client_name : z . string ( ) . optional ( ) ,
154
- client_uri : z . string ( ) . optional ( ) ,
155
- logo_uri : z . string ( ) . optional ( ) ,
167
+ client_uri : SafeUrlSchema . optional ( ) ,
168
+ logo_uri : SafeUrlSchema . optional ( ) ,
156
169
scope : z . string ( ) . optional ( ) ,
157
170
contacts : z . array ( z . string ( ) ) . optional ( ) ,
158
- tos_uri : z . string ( ) . optional ( ) ,
171
+ tos_uri : SafeUrlSchema . optional ( ) ,
159
172
policy_uri : z . string ( ) . optional ( ) ,
160
- jwks_uri : z . string ( ) . optional ( ) ,
173
+ jwks_uri : SafeUrlSchema . optional ( ) ,
161
174
jwks : z . any ( ) . optional ( ) ,
162
175
software_id : z . string ( ) . optional ( ) ,
163
176
software_version : z . string ( ) . optional ( ) ,
0 commit comments