Skip to content

Commit

Permalink
add alternativeIssuer to verifier
Browse files Browse the repository at this point in the history
  • Loading branch information
Nico Muerdter authored and monstermunchkin committed Mar 4, 2025
1 parent 846bde7 commit 06ca5fb
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 20 deletions.
24 changes: 13 additions & 11 deletions oidc/oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,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
deviceAuthURL string
Expand Down Expand Up @@ -164,7 +166,7 @@ var supportedAlgorithms = map[string]bool{
// parsing.
//
// // Directly fetch the metadata document.
// resp, err := http.Get("https://login.example.com/custom-metadata-path")
// resp, err := http.Get("https://login.example.com/custom-metadata-path")
// if err != nil {
// // ...
// }
Expand Down Expand Up @@ -280,15 +282,15 @@ func NewProvider(ctx context.Context, issuer string, alternativeIssuer ...string
}
}
return &Provider{
issuer: issuerURL,
authURL: p.AuthURL,
tokenURL: p.TokenURL,
deviceAuthURL: p.DeviceAuthURL,
userInfoURL: p.UserInfoURL,
jwksURL: p.JWKSURL,
algorithms: algs,
rawClaims: body,
client: getClient(ctx),
issuer: p.Issuer,
alternativeIssuer: alternativeIssuer,
authURL: p.AuthURL,
tokenURL: p.TokenURL,
userInfoURL: p.UserInfoURL,
algorithms: algs,
rawClaims: body,
remoteKeySet: NewRemoteKeySet(ctx, p.JWKSURL),
client: getClient(ctx),
}, nil
}

Expand Down
18 changes: 10 additions & 8 deletions oidc/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,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 @@ -71,8 +72,8 @@ type IDTokenVerifier struct {
//
// keySet := &oidc.StaticKeySet{PublicKeys: []crypto.PublicKey{pub1, pub2}}
// verifier := oidc.NewVerifier("https://accounts.google.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 @@ -142,7 +143,7 @@ func (p *Provider) newVerifier(keySet KeySet, config *Config) *IDTokenVerifier {
cp.SupportedSigningAlgs = p.algorithms
config = cp
}
return NewVerifier(p.issuer, keySet, config)
return NewVerifier(p.issuer, p.remoteKeySet, config, p.alternativeIssuer...)
}

func parseJWT(p string) ([]byte, error) {
Expand Down Expand Up @@ -257,14 +258,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 oidc/verify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,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 @@ -561,6 +573,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 @@ -598,7 +612,7 @@ func (v verificationTest) runGetToken(t *testing.T) (*IDToken, error) {
} else if v.signKey != nil {
ks = &StaticKeySet{PublicKeys: []crypto.PublicKey{v.signKey.pub}}
}
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 06ca5fb

Please sign in to comment.