Skip to content

Commit 2d1d7f5

Browse files
authored
Merge pull request #2 from pace/verifier-alternative-issuer
add alternativeIssuer to verifier
2 parents 8b5101f + 25df11c commit 2d1d7f5

File tree

3 files changed

+36
-17
lines changed

3 files changed

+36
-17
lines changed

oidc.go

+11-8
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ func doRequest(ctx context.Context, req *http.Request) (*http.Response, error) {
6767

6868
// Provider represents an OpenID Connect server's configuration.
6969
type Provider struct {
70-
issuer string
70+
issuer string
71+
alternativeIssuer []string
72+
7173
authURL string
7274
tokenURL string
7375
userInfoURL string
@@ -151,13 +153,14 @@ func NewProvider(ctx context.Context, issuer string, alternativeIssuer ...string
151153
}
152154
}
153155
return &Provider{
154-
issuer: p.Issuer,
155-
authURL: p.AuthURL,
156-
tokenURL: p.TokenURL,
157-
userInfoURL: p.UserInfoURL,
158-
algorithms: algs,
159-
rawClaims: body,
160-
remoteKeySet: NewRemoteKeySet(ctx, p.JWKSURL),
156+
issuer: p.Issuer,
157+
alternativeIssuer: alternativeIssuer,
158+
authURL: p.AuthURL,
159+
tokenURL: p.TokenURL,
160+
userInfoURL: p.UserInfoURL,
161+
algorithms: algs,
162+
rawClaims: body,
163+
remoteKeySet: NewRemoteKeySet(ctx, p.JWKSURL),
161164
}, nil
162165
}
163166

verify.go

+10-8
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,10 @@ type KeySet interface {
3838

3939
// IDTokenVerifier provides verification for ID Tokens.
4040
type IDTokenVerifier struct {
41-
keySet KeySet
42-
config *Config
43-
issuer string
41+
keySet KeySet
42+
config *Config
43+
issuer string
44+
alternativeIssuer []string
4445
}
4546

4647
// NewVerifier returns a verifier manually constructed from a key set and issuer URL.
@@ -65,8 +66,8 @@ type IDTokenVerifier struct {
6566
// // Verifier uses the custom KeySet implementation.
6667
// verifier := oidc.NewVerifier("https://auth.example.com", keySet, config)
6768
//
68-
func NewVerifier(issuerURL string, keySet KeySet, config *Config) *IDTokenVerifier {
69-
return &IDTokenVerifier{keySet: keySet, config: config, issuer: issuerURL}
69+
func NewVerifier(issuerURL string, keySet KeySet, config *Config, alternativeIssuer ...string) *IDTokenVerifier {
70+
return &IDTokenVerifier{keySet: keySet, config: config, issuer: issuerURL, alternativeIssuer: alternativeIssuer}
7071
}
7172

7273
// Config is the configuration for an IDTokenVerifier.
@@ -114,7 +115,7 @@ func (p *Provider) Verifier(config *Config) *IDTokenVerifier {
114115
cp.SupportedSigningAlgs = p.algorithms
115116
config = cp
116117
}
117-
return NewVerifier(p.issuer, p.remoteKeySet, config)
118+
return NewVerifier(p.issuer, p.remoteKeySet, config, p.alternativeIssuer...)
118119
}
119120

120121
func parseJWT(p string) ([]byte, error) {
@@ -249,14 +250,15 @@ func (v *IDTokenVerifier) Verify(ctx context.Context, rawIDToken string) (*IDTok
249250
}
250251

251252
// Check issuer.
252-
if !v.config.SkipIssuerCheck && t.Issuer != v.issuer {
253+
issuerStr := strings.Join(append(v.alternativeIssuer, v.issuer), " ")
254+
if !v.config.SkipIssuerCheck && !strings.Contains(issuerStr, t.Issuer) {
253255
// Google sometimes returns "accounts.google.com" as the issuer claim instead of
254256
// the required "https://accounts.google.com". Detect this case and allow it only
255257
// for Google.
256258
//
257259
// We will not add hooks to let other providers go off spec like this.
258260
if !(v.issuer == issuerGoogleAccounts && t.Issuer == issuerGoogleAccountsNoScheme) {
259-
return nil, fmt.Errorf("oidc: id token issued by a different provider, expected %q got %q", v.issuer, t.Issuer)
261+
return nil, fmt.Errorf("oidc: id token issued by a different provider, expected one of %q got %q", issuerStr, t.Issuer)
260262
}
261263
}
262264

verify_test.go

+15-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,18 @@ func TestVerify(t *testing.T) {
4848
signKey: newRSAKey(t),
4949
wantErr: true,
5050
},
51+
{
52+
name: "alternative issuer",
53+
issuer: "https://bar",
54+
alternativeIssuer: []string{"https://bar", "https://baz"},
55+
idToken: `{"iss":"https://foo"}`,
56+
config: Config{
57+
SkipClientIDCheck: true,
58+
SkipExpiryCheck: true,
59+
},
60+
signKey: newRSAKey(t),
61+
wantErr: true,
62+
},
5163
{
5264
name: "skip issuer check",
5365
issuer: "https://bar",
@@ -535,6 +547,8 @@ type verificationTest struct {
535547
// If not provided defaults to "https://foo"
536548
issuer string
537549

550+
alternativeIssuer []string
551+
538552
// JWT payload (just the claims).
539553
idToken string
540554

@@ -564,7 +578,7 @@ func (v verificationTest) runGetToken(t *testing.T) (*IDToken, error) {
564578
} else {
565579
ks = &testVerifier{v.verificationKey.jwk()}
566580
}
567-
verifier := NewVerifier(issuer, ks, &v.config)
581+
verifier := NewVerifier(issuer, ks, &v.config, v.alternativeIssuer...)
568582

569583
return verifier.Verify(ctx, token)
570584
}

0 commit comments

Comments
 (0)