@@ -220,24 +220,40 @@ describe('validate', () => {
220220 expect ( result . error ?. includes ( 'Invalid authorizer type' ) ) . toBeTruthy ( ) ;
221221 } ) ;
222222
223- // AC11: CUSTOM_JWT requires discoveryUrl and allowedClients (allowedAudience is optional)
224- it ( 'returns error for CUSTOM_JWT missing required fields' , ( ) => {
225- const jwtFields : { field : keyof AddGatewayOptions ; error : string } [ ] = [
226- { field : 'discoveryUrl' , error : '--discovery-url is required for CUSTOM_JWT authorizer' } ,
227- { field : 'allowedClients' , error : '--allowed-clients is required for CUSTOM_JWT authorizer' } ,
228- ] ;
223+ // AC11: CUSTOM_JWT requires discoveryUrl
224+ it ( 'returns error for CUSTOM_JWT missing discoveryUrl' , ( ) => {
225+ const opts = { ...validGatewayOptionsJwt , discoveryUrl : undefined } ;
226+ const result = validateAddGatewayOptions ( opts ) ;
227+ expect ( result . valid ) . toBe ( false ) ;
228+ expect ( result . error ) . toBe ( '--discovery-url is required for CUSTOM_JWT authorizer' ) ;
229+ } ) ;
229230
230- for ( const { field, error } of jwtFields ) {
231- const opts = { ...validGatewayOptionsJwt , [ field ] : undefined } ;
232- const result = validateAddGatewayOptions ( opts ) ;
233- expect ( result . valid , `Should fail for missing ${ String ( field ) } ` ) . toBe ( false ) ;
234- expect ( result . error ) . toBe ( error ) ;
235- }
231+ // AC11b: at least one of audience/clients/scopes required
232+ it ( 'returns error when all of audience, clients, and scopes are missing' , ( ) => {
233+ const opts = {
234+ ...validGatewayOptionsJwt ,
235+ allowedAudience : undefined ,
236+ allowedClients : undefined ,
237+ allowedScopes : undefined ,
238+ } ;
239+ const result = validateAddGatewayOptions ( opts ) ;
240+ expect ( result . valid ) . toBe ( false ) ;
241+ expect ( result . error ) . toContain ( 'At least one of' ) ;
242+ } ) ;
243+
244+ it ( 'allows CUSTOM_JWT with only allowedScopes' , ( ) => {
245+ const opts = {
246+ ...validGatewayOptionsJwt ,
247+ allowedAudience : undefined ,
248+ allowedClients : undefined ,
249+ allowedScopes : 'scope1' ,
250+ } ;
251+ const result = validateAddGatewayOptions ( opts ) ;
252+ expect ( result . valid ) . toBe ( true ) ;
236253 } ) ;
237254
238- // AC11b: allowedAudience is optional
239- it ( 'allows CUSTOM_JWT without allowedAudience' , ( ) => {
240- const opts = { ...validGatewayOptionsJwt , allowedAudience : undefined } ;
255+ it ( 'allows CUSTOM_JWT with only allowedAudience' , ( ) => {
256+ const opts = { ...validGatewayOptionsJwt , allowedClients : undefined , allowedScopes : undefined } ;
241257 const result = validateAddGatewayOptions ( opts ) ;
242258 expect ( result . valid ) . toBe ( true ) ;
243259 } ) ;
@@ -255,11 +271,19 @@ describe('validate', () => {
255271 expect ( result . error ?. includes ( '.well-known/openid-configuration' ) ) . toBeTruthy ( ) ;
256272 } ) ;
257273
258- // AC13: Empty comma-separated clients rejected (audience can be empty)
259- it ( 'returns error for empty clients' , ( ) => {
260- const result = validateAddGatewayOptions ( { ...validGatewayOptionsJwt , allowedClients : ' , ' } ) ;
274+ it ( 'returns error for HTTP discoveryUrl (HTTPS required)' , ( ) => {
275+ const result = validateAddGatewayOptions ( {
276+ ...validGatewayOptionsJwt ,
277+ discoveryUrl : 'http://example.com/.well-known/openid-configuration' ,
278+ } ) ;
261279 expect ( result . valid ) . toBe ( false ) ;
262- expect ( result . error ) . toBe ( 'At least one client value is required' ) ;
280+ expect ( result . error ) . toBe ( 'Discovery URL must use HTTPS' ) ;
281+ } ) ;
282+
283+ it ( 'allows CUSTOM_JWT with only allowedClients' , ( ) => {
284+ const opts = { ...validGatewayOptionsJwt , allowedAudience : undefined , allowedScopes : undefined } ;
285+ const result = validateAddGatewayOptions ( opts ) ;
286+ expect ( result . valid ) . toBe ( true ) ;
263287 } ) ;
264288
265289 // AC14: Valid options pass
@@ -268,42 +292,42 @@ describe('validate', () => {
268292 expect ( validateAddGatewayOptions ( validGatewayOptionsJwt ) ) . toEqual ( { valid : true } ) ;
269293 } ) ;
270294
271- // AC15: agentClientId and agentClientSecret must be provided together
272- it ( 'returns error when agentClientId provided without agentClientSecret ' , ( ) => {
295+ // AC15: clientId and clientSecret must be provided together
296+ it ( 'returns error when clientId provided without clientSecret ' , ( ) => {
273297 const result = validateAddGatewayOptions ( {
274298 ...validGatewayOptionsJwt ,
275- agentClientId : 'my-client-id' ,
299+ clientId : 'my-client-id' ,
276300 } ) ;
277301 expect ( result . valid ) . toBe ( false ) ;
278- expect ( result . error ) . toBe ( 'Both --agent- client-id and --agent -client-secret must be provided together' ) ;
302+ expect ( result . error ) . toBe ( 'Both --client-id and --client-secret must be provided together' ) ;
279303 } ) ;
280304
281- it ( 'returns error when agentClientSecret provided without agentClientId ' , ( ) => {
305+ it ( 'returns error when clientSecret provided without clientId ' , ( ) => {
282306 const result = validateAddGatewayOptions ( {
283307 ...validGatewayOptionsJwt ,
284- agentClientSecret : 'my-secret' ,
308+ clientSecret : 'my-secret' ,
285309 } ) ;
286310 expect ( result . valid ) . toBe ( false ) ;
287- expect ( result . error ) . toBe ( 'Both --agent- client-id and --agent -client-secret must be provided together' ) ;
311+ expect ( result . error ) . toBe ( 'Both --client-id and --client-secret must be provided together' ) ;
288312 } ) ;
289313
290- // AC16: agent credentials only valid with CUSTOM_JWT
291- it ( 'returns error when agent credentials used with non-CUSTOM_JWT authorizer' , ( ) => {
314+ // AC16: OAuth credentials only valid with CUSTOM_JWT
315+ it ( 'returns error when OAuth credentials used with non-CUSTOM_JWT authorizer' , ( ) => {
292316 const result = validateAddGatewayOptions ( {
293317 ...validGatewayOptionsNone ,
294- agentClientId : 'my-client-id' ,
295- agentClientSecret : 'my-secret' ,
318+ clientId : 'my-client-id' ,
319+ clientSecret : 'my-secret' ,
296320 } ) ;
297321 expect ( result . valid ) . toBe ( false ) ;
298- expect ( result . error ) . toBe ( 'Agent OAuth credentials are only valid with CUSTOM_JWT authorizer' ) ;
322+ expect ( result . error ) . toBe ( 'OAuth client credentials are only valid with CUSTOM_JWT authorizer' ) ;
299323 } ) ;
300324
301- // AC17: valid CUSTOM_JWT with agent credentials passes
302- it ( 'passes for CUSTOM_JWT with agent credentials' , ( ) => {
325+ // AC17: valid CUSTOM_JWT with OAuth credentials passes
326+ it ( 'passes for CUSTOM_JWT with OAuth credentials' , ( ) => {
303327 const result = validateAddGatewayOptions ( {
304328 ...validGatewayOptionsJwt ,
305- agentClientId : 'my-client-id' ,
306- agentClientSecret : 'my-secret' ,
329+ clientId : 'my-client-id' ,
330+ clientSecret : 'my-secret' ,
307331 allowedScopes : 'scope1,scope2' ,
308332 } ) ;
309333 expect ( result . valid ) . toBe ( true ) ;
0 commit comments