Skip to content

Commit

Permalink
Merge pull request #2 from pace/verifier-alternative-issuer
Browse files Browse the repository at this point in the history
add alternativeIssuer to verifier
  • Loading branch information
threez authored Jul 1, 2020
2 parents 8b5101f + 25df11c commit 2d1d7f5
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 17 deletions.
19 changes: 11 additions & 8 deletions oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}

Expand Down
18 changes: 10 additions & 8 deletions verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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)
}
}

Expand Down
16 changes: 15 additions & 1 deletion verify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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)
}
Expand Down

0 comments on commit 2d1d7f5

Please sign in to comment.