From 25df11cd300f70af145e6f6292feb909c33b775a Mon Sep 17 00:00:00 2001 From: Nico Muerdter Date: Wed, 1 Jul 2020 15:54:53 +0200 Subject: [PATCH] add alternativeIssuer to verifier --- oidc.go | 19 +++++++++++-------- verify.go | 18 ++++++++++-------- verify_test.go | 16 +++++++++++++++- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/oidc.go b/oidc.go index fe24e0d9..becf994b 100644 --- a/oidc.go +++ b/oidc.go @@ -67,7 +67,9 @@ func doRequest(ctx context.Context, req *http.Request) (*http.Response, error) { // Provider represents an OpenID Connect server's configuration. type Provider struct { - issuer string + issuer string + alternativeIssuer []string + authURL string tokenURL string userInfoURL string @@ -151,13 +153,14 @@ func NewProvider(ctx context.Context, issuer string, alternativeIssuer ...string } } return &Provider{ - issuer: p.Issuer, - authURL: p.AuthURL, - tokenURL: p.TokenURL, - userInfoURL: p.UserInfoURL, - algorithms: algs, - rawClaims: body, - remoteKeySet: NewRemoteKeySet(ctx, p.JWKSURL), + issuer: p.Issuer, + alternativeIssuer: alternativeIssuer, + authURL: p.AuthURL, + tokenURL: p.TokenURL, + userInfoURL: p.UserInfoURL, + algorithms: algs, + rawClaims: body, + remoteKeySet: NewRemoteKeySet(ctx, p.JWKSURL), }, nil } diff --git a/verify.go b/verify.go index d43f0662..9ba022d1 100644 --- a/verify.go +++ b/verify.go @@ -38,9 +38,10 @@ type KeySet interface { // IDTokenVerifier provides verification for ID Tokens. type IDTokenVerifier struct { - keySet KeySet - config *Config - issuer string + keySet KeySet + config *Config + issuer string + alternativeIssuer []string } // NewVerifier returns a verifier manually constructed from a key set and issuer URL. @@ -65,8 +66,8 @@ type IDTokenVerifier struct { // // Verifier uses the custom KeySet implementation. // verifier := oidc.NewVerifier("https://auth.example.com", keySet, config) // -func NewVerifier(issuerURL string, keySet KeySet, config *Config) *IDTokenVerifier { - return &IDTokenVerifier{keySet: keySet, config: config, issuer: issuerURL} +func NewVerifier(issuerURL string, keySet KeySet, config *Config, alternativeIssuer ...string) *IDTokenVerifier { + return &IDTokenVerifier{keySet: keySet, config: config, issuer: issuerURL, alternativeIssuer: alternativeIssuer} } // Config is the configuration for an IDTokenVerifier. @@ -114,7 +115,7 @@ func (p *Provider) Verifier(config *Config) *IDTokenVerifier { cp.SupportedSigningAlgs = p.algorithms config = cp } - return NewVerifier(p.issuer, p.remoteKeySet, config) + return NewVerifier(p.issuer, p.remoteKeySet, config, p.alternativeIssuer...) } func parseJWT(p string) ([]byte, error) { @@ -249,14 +250,15 @@ func (v *IDTokenVerifier) Verify(ctx context.Context, rawIDToken string) (*IDTok } // Check issuer. - if !v.config.SkipIssuerCheck && t.Issuer != v.issuer { + issuerStr := strings.Join(append(v.alternativeIssuer, v.issuer), " ") + if !v.config.SkipIssuerCheck && !strings.Contains(issuerStr, t.Issuer) { // Google sometimes returns "accounts.google.com" as the issuer claim instead of // the required "https://accounts.google.com". Detect this case and allow it only // for Google. // // We will not add hooks to let other providers go off spec like this. if !(v.issuer == issuerGoogleAccounts && t.Issuer == issuerGoogleAccountsNoScheme) { - return nil, fmt.Errorf("oidc: id token issued by a different provider, expected %q got %q", v.issuer, t.Issuer) + return nil, fmt.Errorf("oidc: id token issued by a different provider, expected one of %q got %q", issuerStr, t.Issuer) } } diff --git a/verify_test.go b/verify_test.go index d2fffa9c..8da6f624 100644 --- a/verify_test.go +++ b/verify_test.go @@ -48,6 +48,18 @@ func TestVerify(t *testing.T) { signKey: newRSAKey(t), wantErr: true, }, + { + name: "alternative issuer", + issuer: "https://bar", + alternativeIssuer: []string{"https://bar", "https://baz"}, + idToken: `{"iss":"https://foo"}`, + config: Config{ + SkipClientIDCheck: true, + SkipExpiryCheck: true, + }, + signKey: newRSAKey(t), + wantErr: true, + }, { name: "skip issuer check", issuer: "https://bar", @@ -535,6 +547,8 @@ type verificationTest struct { // If not provided defaults to "https://foo" issuer string + alternativeIssuer []string + // JWT payload (just the claims). idToken string @@ -564,7 +578,7 @@ func (v verificationTest) runGetToken(t *testing.T) (*IDToken, error) { } else { ks = &testVerifier{v.verificationKey.jwk()} } - verifier := NewVerifier(issuer, ks, &v.config) + verifier := NewVerifier(issuer, ks, &v.config, v.alternativeIssuer...) return verifier.Verify(ctx, token) }