Skip to content

Commit 3fca22b

Browse files
committed
feat: allow native app callbacks in client post_logout_redirect_uris
1 parent 3b2bcc5 commit 3fca22b

2 files changed

Lines changed: 51 additions & 29 deletions

File tree

lib/helpers/client_schema.js

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -545,13 +545,7 @@ module.exports = function getSchema(provider) {
545545

546546
postLogoutRedirectUris() {
547547
if (this.post_logout_redirect_uris) {
548-
this.post_logout_redirect_uris.forEach((uri) => {
549-
try {
550-
new url.URL(uri); // eslint-disable-line no-new
551-
} catch (err) {
552-
this.invalidate('post_logout_redirect_uris must only contain uris');
553-
}
554-
});
548+
this.redirectUris(this.post_logout_redirect_uris, 'post_logout_redirect_uris');
555549
}
556550
}
557551

@@ -575,35 +569,35 @@ module.exports = function getSchema(provider) {
575569
});
576570
}
577571

578-
redirectUris() {
579-
this.redirect_uris.forEach((redirectUri) => {
572+
redirectUris(uris = this.redirect_uris, label = 'redirect_uris') {
573+
uris.forEach((redirectUri) => {
580574
let hostname;
581575
let protocol;
582576
try {
583577
({ hostname, protocol } = new url.URL(redirectUri));
584578
} catch (err) {
585-
this.invalidate('redirect_uris must only contain valid uris');
579+
this.invalidate(`${label} must only contain valid uris`);
586580
}
587581

588582
const { hash } = url.parse(redirectUri);
589583

590584
if (hash) {
591-
this.invalidate('redirect_uris must not contain fragments');
585+
this.invalidate(`${label} must not contain fragments`);
592586
}
593587

594588
switch (this.application_type) { // eslint-disable-line default-case
595589
case 'web': {
596590
if (!['https:', 'http:'].includes(protocol)) {
597-
this.invalidate('redirect_uris must only contain web uris');
591+
this.invalidate(`${label} must only contain web uris`);
598592
}
599593

600594
if (this.grant_types.includes('implicit')) {
601595
if (protocol === 'http:') {
602-
this.invalidate('redirect_uris for web clients using implicit flow MUST only register URLs using the https scheme', 'implicit-force-https');
596+
this.invalidate(`${label} for web clients using implicit flow MUST only register URLs using the https scheme', 'implicit-force-https`);
603597
}
604598

605599
if (hostname === 'localhost') {
606-
this.invalidate('redirect_uris for web clients using implicit flow must not be using localhost', 'implicit-forbid-localhost');
600+
this.invalidate(`${label} for web clients using implicit flow must not be using localhost', 'implicit-forbid-localhost`);
607601
}
608602
}
609603
break;
@@ -612,17 +606,17 @@ module.exports = function getSchema(provider) {
612606
switch (protocol) {
613607
case 'http:': // Loopback Interface Redirection
614608
if (!LOOPBACKS.has(hostname)) {
615-
this.invalidate('redirect_uris for native clients using http as a protocol can only use loopback addresses as hostnames');
609+
this.invalidate(`${label} for native clients using http as a protocol can only use loopback addresses as hostnames`);
616610
}
617611
break;
618612
case 'https:': // Claimed HTTPS URI Redirection
619613
if (LOOPBACKS.has(hostname)) {
620-
this.invalidate(`redirect_uris for native clients using claimed HTTPS URIs must not be using ${hostname} as hostname`);
614+
this.invalidate(`${label} for native clients using claimed HTTPS URIs must not be using ${hostname} as hostname`);
621615
}
622616
break;
623617
default: // Private-use URI Scheme Redirection
624618
if (!protocol.includes('.')) {
625-
this.invalidate('redirect_uris for native clients using Custom URI scheme should use reverse domain name based scheme');
619+
this.invalidate(`${label} for native clients using Custom URI scheme should use reverse domain name based scheme`);
626620
}
627621
}
628622
break;

test/configuration/client_metadata.test.js

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,46 @@ describe('Client metadata validation', () => {
372372
});
373373
});
374374

375+
context('post_logout_redirect_uris', function () {
376+
defaultsTo(this.title, [], undefined);
377+
defaultsTo(this.title, [], { post_logout_redirect_uris: undefined });
378+
mustBeArray(this.title, [{}, 'string', 123, true]);
379+
rejects(this.title, [123], /must only contain strings$/);
380+
381+
allows(this.title, ['http://some'], {
382+
application_type: 'web',
383+
});
384+
allows(this.title, ['https://some'], {
385+
application_type: 'web',
386+
});
387+
rejects(this.title, ['https://rp.example.com#'], /post_logout_redirect_uris must not contain fragments$/);
388+
rejects(this.title, ['https://rp.example.com#whatever'], /post_logout_redirect_uris must not contain fragments$/, {
389+
application_type: 'web',
390+
});
391+
rejects(this.title, ['no-dot-reverse-notation:/some'], undefined, {
392+
application_type: 'web',
393+
});
394+
rejects(this.title, ['https://localhost'], undefined, {
395+
application_type: 'web',
396+
grant_types: ['implicit', 'authorization_code'],
397+
response_types: ['code id_token'],
398+
});
399+
allows(this.title, ['http://localhost'], {
400+
application_type: 'web',
401+
});
402+
rejects(this.title, ['http://some'], undefined, {
403+
application_type: 'native',
404+
});
405+
rejects(this.title, ['not-a-uri'], undefined, {
406+
application_type: 'native',
407+
});
408+
rejects(this.title, ['http://foo/bar'], undefined, {
409+
application_type: 'web',
410+
grant_types: ['implicit'],
411+
response_types: ['id_token'],
412+
});
413+
});
414+
375415
context('request_object_signing_alg', function () {
376416
mustBeString(this.title);
377417
[
@@ -476,18 +516,6 @@ describe('Client metadata validation', () => {
476516
rejects(this.title, 'not-a-type');
477517
});
478518

479-
context('post_logout_redirect_uris', function () {
480-
defaultsTo(this.title, [], undefined);
481-
defaultsTo(this.title, [], { post_logout_redirect_uris: undefined });
482-
mustBeArray(this.title, undefined);
483-
484-
rejects(this.title, [123], /must only contain strings$/, undefined);
485-
allows(this.title, ['http://a-web-uri'], undefined);
486-
allows(this.title, ['https://a-web-uri'], undefined);
487-
allows(this.title, ['any-custom-scheme://not-a-web-uri'], undefined);
488-
rejects(this.title, ['not a uri'], /must only contain uris$/, undefined);
489-
});
490-
491519
[
492520
'token_endpoint_auth_method',
493521
'introspection_endpoint_auth_method',

0 commit comments

Comments
 (0)