Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add require_nonce field to OIDC generic provider configuration #3982

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .schemastore/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,9 @@
"format": "uri",
"examples": ["https://accounts.google.com"]
},
"require_nonce": {
"type": "boolean"
},
"auth_url": {
"type": "string",
"format": "uri",
Expand Down
3 changes: 3 additions & 0 deletions embedx/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,9 @@
"https://accounts.google.com"
]
},
"require_nonce": {
"type": "boolean"
},
"auth_url": {
"type": "string",
"format": "uri",
Expand Down
9 changes: 0 additions & 9 deletions selfservice/strategy/oidc/provider_apple.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
"net/url"
"time"

"github.com/coreos/go-oidc/v3/oidc"
"github.com/golang-jwt/jwt/v4"

"github.com/pkg/errors"
Expand All @@ -35,7 +34,6 @@
config: config,
reg: reg,
},
JWKSUrl: "https://appleid.apple.com/auth/keys",
}
}

Expand Down Expand Up @@ -154,15 +152,8 @@

var _ IDTokenVerifier = new(ProviderApple)

const issuerUrlApple = "https://appleid.apple.com"

Check failure on line 155 in selfservice/strategy/oidc/provider_apple.go

View workflow job for this annotation

GitHub Actions / Run tests and lints

const `issuerUrlApple` is unused (unused)

func (a *ProviderApple) Verify(ctx context.Context, rawIDToken string) (*Claims, error) {
keySet := oidc.NewRemoteKeySet(ctx, a.JWKSUrl)

ctx = oidc.ClientContext(ctx, a.reg.HTTPClient(ctx).HTTPClient)
return verifyToken(ctx, keySet, a.config, rawIDToken, issuerUrlApple)
}

var _ NonceValidationSkipper = new(ProviderApple)

func (a *ProviderApple) CanSkipNonce(c *Claims) bool {
Expand Down
3 changes: 3 additions & 0 deletions selfservice/strategy/oidc/provider_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ type Configuration struct {
// If set, neither `auth_url` nor `token_url` are required.
IssuerURL string `json:"issuer_url"`

// For ID token validation, determines if nonce validation is required. Not all providers support nonce.
RequireNonce bool `json:"require_nonce"`

// AuthURL is the authorize url, typically something like: https://example.org/oauth2/auth
// Should only be used when the OAuth2 / OpenID Connect server is not supporting OpenID Connect Discovery and when
// `provider` is set to `generic`.
Expand Down
32 changes: 32 additions & 0 deletions selfservice/strategy/oidc/provider_generic_oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,17 @@ func (g *ProviderGenericOIDC) provider(ctx context.Context) (*gooidc.Provider, e
return g.p, nil
}

func getJWKSURL(provider *gooidc.Provider) (string, error) {
var claims struct {
JWKSURL string `json:"jwks_uri"`
}

if err := provider.Claims(&claims); err != nil {
return "", err
}
return claims.JWKSURL, nil
}

func (g *ProviderGenericOIDC) oauth2ConfigFromEndpoint(ctx context.Context, endpoint oauth2.Endpoint) *oauth2.Config {
scope := g.config.Scope
if !stringslice.Has(scope, gooidc.ScopeOpenID) {
Expand Down Expand Up @@ -214,3 +225,24 @@ func (g *ProviderGenericOIDC) verifiedIDToken(ctx context.Context, exchange *oau

return token, nil
}

var _ IDTokenVerifier = new(ProviderGenericOIDC)

func (p *ProviderGenericOIDC) Verify(ctx context.Context, rawIDToken string) (*Claims, error) {
provider, _ := p.provider(ctx)
jwksURL, _ := getJWKSURL(provider)
keySet := gooidc.NewRemoteKeySet(ctx, jwksURL)
ctx = gooidc.ClientContext(ctx, p.reg.HTTPClient(ctx).HTTPClient)
return verifyToken(ctx, keySet, p.config, rawIDToken, p.config.IssuerURL)
}

var _ NonceValidationSkipper = new(ProviderGenericOIDC)

func (a *ProviderGenericOIDC) CanSkipNonce(c *Claims) bool {
if a.config.RequireNonce {
return false
}

// Not all SDKs support nonce validation, so we skip it if no nonce is present in the claims of the ID Token.
return c.Nonce == ""
}
7 changes: 0 additions & 7 deletions selfservice/strategy/oidc/provider_google.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
config: config,
reg: reg,
},
JWKSUrl: "https://www.googleapis.com/oauth2/v3/certs",
}
}

Expand Down Expand Up @@ -71,14 +70,8 @@

var _ IDTokenVerifier = new(ProviderGoogle)

const issuerUrlGoogle = "https://accounts.google.com"

Check failure on line 73 in selfservice/strategy/oidc/provider_google.go

View workflow job for this annotation

GitHub Actions / Run tests and lints

const `issuerUrlGoogle` is unused (unused)

func (p *ProviderGoogle) Verify(ctx context.Context, rawIDToken string) (*Claims, error) {
keySet := gooidc.NewRemoteKeySet(ctx, p.JWKSUrl)
ctx = gooidc.ClientContext(ctx, p.reg.HTTPClient(ctx).HTTPClient)
return verifyToken(ctx, keySet, p.config, rawIDToken, issuerUrlGoogle)
}

var _ NonceValidationSkipper = new(ProviderGoogle)

func (a *ProviderGoogle) CanSkipNonce(c *Claims) bool {
Expand Down
Loading