@@ -78,6 +78,7 @@ func TestAuthorize(t *testing.T) {
7878 return & AuthorizationResult {
7979 Code : location .Query ().Get ("code" ),
8080 State : location .Query ().Get ("state" ),
81+ Iss : location .Query ().Get ("iss" ),
8182 }, nil
8283 },
8384 })
@@ -176,6 +177,7 @@ func TestAuthorize_ScopeAccumulation(t *testing.T) {
176177 return & AuthorizationResult {
177178 Code : loc .Query ().Get ("code" ),
178179 State : loc .Query ().Get ("state" ),
180+ Iss : loc .Query ().Get ("iss" ),
179181 }, nil
180182 },
181183 })
@@ -607,6 +609,8 @@ func TestHandleRegistration(t *testing.T) {
607609 asm * oauthex.AuthServerMeta
608610 want * resolvedClientConfig
609611 wantError bool
612+ issuerMatch bool
613+ issuerSuffix string
610614 }{
611615 {
612616 name : "ClientIDMetadataDocument" ,
@@ -645,6 +649,79 @@ func TestHandleRegistration(t *testing.T) {
645649 authStyle : oauth2 .AuthStyleInParams ,
646650 },
647651 },
652+ {
653+ name : "Preregistered_IssuerMatch" ,
654+ serverConfig : & oauthtest.RegistrationConfig {
655+ PreregisteredClients : map [string ]oauthtest.ClientInfo {
656+ "pre_client_id" : {
657+ Secret : "pre_client_secret" ,
658+ },
659+ },
660+ },
661+ handlerConfig : & AuthorizationCodeHandlerConfig {
662+ PreregisteredClient : & oauthex.ClientCredentials {
663+ ClientID : "pre_client_id" ,
664+ ClientSecretAuth : & oauthex.ClientSecretAuth {
665+ ClientSecret : "pre_client_secret" ,
666+ },
667+ Issuer : "" , // set dynamically in the test
668+ },
669+ },
670+ want : & resolvedClientConfig {
671+ registrationType : registrationTypePreregistered ,
672+ clientID : "pre_client_id" ,
673+ clientSecret : "pre_client_secret" ,
674+ authStyle : oauth2 .AuthStyleInParams ,
675+ },
676+ issuerMatch : true ,
677+ },
678+ {
679+ name : "Preregistered_IssuerMismatch" ,
680+ serverConfig : & oauthtest.RegistrationConfig {
681+ PreregisteredClients : map [string ]oauthtest.ClientInfo {
682+ "pre_client_id" : {
683+ Secret : "pre_client_secret" ,
684+ },
685+ },
686+ },
687+ handlerConfig : & AuthorizationCodeHandlerConfig {
688+ PreregisteredClient : & oauthex.ClientCredentials {
689+ ClientID : "pre_client_id" ,
690+ ClientSecretAuth : & oauthex.ClientSecretAuth {
691+ ClientSecret : "pre_client_secret" ,
692+ },
693+ Issuer : "https://other-issuer.example.com" ,
694+ },
695+ },
696+ wantError : true ,
697+ },
698+ {
699+ name : "Preregistered_IssuerMatchTrailingSlash" ,
700+ serverConfig : & oauthtest.RegistrationConfig {
701+ PreregisteredClients : map [string ]oauthtest.ClientInfo {
702+ "pre_client_id" : {
703+ Secret : "pre_client_secret" ,
704+ },
705+ },
706+ },
707+ handlerConfig : & AuthorizationCodeHandlerConfig {
708+ PreregisteredClient : & oauthex.ClientCredentials {
709+ ClientID : "pre_client_id" ,
710+ ClientSecretAuth : & oauthex.ClientSecretAuth {
711+ ClientSecret : "pre_client_secret" ,
712+ },
713+ Issuer : "" , // set dynamically in the test (with trailing slash)
714+ },
715+ },
716+ want : & resolvedClientConfig {
717+ registrationType : registrationTypePreregistered ,
718+ clientID : "pre_client_id" ,
719+ clientSecret : "pre_client_secret" ,
720+ authStyle : oauth2 .AuthStyleInParams ,
721+ },
722+ issuerMatch : true ,
723+ issuerSuffix : "/" ,
724+ },
648725 {
649726 name : "NoneSupported" ,
650727 handlerConfig : & AuthorizationCodeHandlerConfig {
@@ -658,6 +735,10 @@ func TestHandleRegistration(t *testing.T) {
658735 t .Run (tt .name , func (t * testing.T ) {
659736 s := oauthtest .NewFakeAuthorizationServer (oauthtest.Config {RegistrationConfig : tt .serverConfig })
660737 s .Start (t )
738+ // Set the Issuer dynamically if requested by the test case.
739+ if tt .issuerMatch {
740+ tt .handlerConfig .PreregisteredClient .Issuer = s .URL () + tt .issuerSuffix
741+ }
661742 tt .handlerConfig .AuthorizationCodeFetcher = func (ctx context.Context , args * AuthorizationArgs ) (* AuthorizationResult , error ) {
662743 return nil , nil
663744 }
@@ -677,6 +758,9 @@ func TestHandleRegistration(t *testing.T) {
677758 }
678759 return
679760 }
761+ if tt .wantError {
762+ t .Fatal ("handleRegistration() expected error, got nil" )
763+ }
680764 if got .registrationType != tt .want .registrationType {
681765 t .Errorf ("handleRegistration() registrationType = %v, want %v" , got .registrationType , tt .want .registrationType )
682766 }
@@ -736,6 +820,59 @@ func TestDynamicRegistration(t *testing.T) {
736820 }
737821}
738822
823+ func TestValidateIssuerResponse (t * testing.T ) {
824+ const expectedIssuer = "https://auth.example.com"
825+
826+ tests := []struct {
827+ name string
828+ iss string
829+ issSupported bool
830+ wantErr bool
831+ wantErrContains string
832+ }{
833+ {
834+ name : "ValidIss" ,
835+ iss : expectedIssuer ,
836+ issSupported : true ,
837+ },
838+ {
839+ name : "WrongIss" ,
840+ iss : "https://attacker.example.com" ,
841+ issSupported : true ,
842+ wantErr : true ,
843+ wantErrContains : "does not match expected issuer" ,
844+ },
845+ {
846+ name : "MissingIssWhenRequired" ,
847+ iss : "" ,
848+ issSupported : true ,
849+ wantErr : true ,
850+ wantErrContains : "RFC 9207" ,
851+ },
852+ {
853+ name : "MissingIssWhenNotRequired" ,
854+ iss : "" ,
855+ issSupported : false ,
856+ },
857+ }
858+
859+ for _ , tt := range tests {
860+ t .Run (tt .name , func (t * testing.T ) {
861+ err := validateIssuerResponse (tt .iss , expectedIssuer , tt .issSupported )
862+ if tt .wantErr {
863+ if err == nil {
864+ t .Fatalf ("validateIssuerResponse() = nil, want error containing %q" , tt .wantErrContains )
865+ }
866+ if ! strings .Contains (err .Error (), tt .wantErrContains ) {
867+ t .Errorf ("validateIssuerResponse() error = %q, want it to contain %q" , err .Error (), tt .wantErrContains )
868+ }
869+ } else if err != nil {
870+ t .Fatalf ("validateIssuerResponse() unexpected error = %v" , err )
871+ }
872+ })
873+ }
874+ }
875+
739876func TestInferApplicationType (t * testing.T ) {
740877 tests := []struct {
741878 name string
0 commit comments