feat: add support for specifying allowed OIDC JWT signing algorithms (#2753)

TODO:
- [ ] update docs
- [ ] add support in yaml (modern) config
- [ ] add more test(s)?

Add (legacy for now) configuration flag "oidc-enabled-signing-alg" (cfg:
oidc_enabled_signing_algs) that allows setting what signing algorithms
are specified by provider in JWT header ("alg" header claim).

In particular useful when skip_oidc_discovery = true, as verifier
defaults to only accept "RS256" in alg field in such circumstances.
This commit is contained in:
andoks 2024-08-26 12:08:27 +02:00 committed by Jan Larwig
parent 566b3aac9f
commit 43752a9aa7
No known key found for this signature in database
GPG Key ID: C2172BFA220A037A
5 changed files with 19 additions and 9 deletions

View File

@ -186,6 +186,7 @@ redirect_url="http://localhost:4180/oauth2/callback"
InsecureAllowUnverifiedEmail: ptr.To(false),
InsecureSkipIssuerVerification: ptr.To(false),
SkipDiscovery: ptr.To(false),
EnabledSigningAlgs: []string{},
},
MicrosoftEntraIDConfig: options.MicrosoftEntraIDOptions{
FederatedTokenAuth: ptr.To(false),

View File

@ -51,15 +51,16 @@ func NewLegacyOptions() *LegacyOptions {
},
LegacyProvider: LegacyProvider{
ProviderType: "google",
AzureTenant: "common",
ApprovalPrompt: "force",
UserIDClaim: "email",
OIDCEmailClaim: "email",
OIDCGroupsClaim: "groups",
OIDCAudienceClaims: []string{"aud"},
OIDCExtraAudiences: []string{},
InsecureOIDCSkipNonce: true,
ProviderType: "google",
AzureTenant: "common",
ApprovalPrompt: "force",
UserIDClaim: "email",
OIDCEmailClaim: "email",
OIDCGroupsClaim: "groups",
OIDCAudienceClaims: []string{"aud"},
OIDCExtraAudiences: []string{},
OIDCEnabledSigningAlgs: []string{},
InsecureOIDCSkipNonce: true,
},
Options: *NewOptions(),
@ -545,6 +546,7 @@ type LegacyProvider struct {
OIDCAudienceClaims []string `flag:"oidc-audience-claim" cfg:"oidc_audience_claims"`
OIDCExtraAudiences []string `flag:"oidc-extra-audience" cfg:"oidc_extra_audiences"`
OIDCPublicKeyFiles []string `flag:"oidc-public-key-file" cfg:"oidc_public_key_files"`
OIDCEnabledSigningAlgs []string `flag:"oidc-enabled-signing-alg" cfg:"oidc_enabled_signing_algs"`
LoginURL string `flag:"login-url" cfg:"login_url"`
AuthRequestResponseMode string `flag:"auth-request-response-mode" cfg:"auth_request_response_mode"`
RedeemURL string `flag:"redeem-url" cfg:"redeem_url"`
@ -606,6 +608,7 @@ func legacyProviderFlagSet() *pflag.FlagSet {
flagSet.StringSlice("oidc-audience-claim", OIDCAudienceClaims, "which OIDC claims are used as audience to verify against client id")
flagSet.StringSlice("oidc-extra-audience", []string{}, "additional audiences allowed to pass audience verification")
flagSet.StringSlice("oidc-public-key-file", []string{}, "path to public key file in PEM format to use for verifying JWT tokens (may be given multiple times)")
flagSet.StringSlice("oidc-enabled-signing-alg", []string{}, "accepted signing algorithms for provider to use")
flagSet.String("login-url", "", "Authentication endpoint")
flagSet.String("redeem-url", "", "Token redemption endpoint")
flagSet.String("profile-url", "", "Profile access endpoint")
@ -727,6 +730,7 @@ func (l *LegacyProvider) convert() (Providers, error) {
AudienceClaims: l.OIDCAudienceClaims,
ExtraAudiences: l.OIDCExtraAudiences,
PublicKeyFiles: l.OIDCPublicKeyFiles,
EnabledSigningAlgs: l.OIDCEnabledSigningAlgs,
}
// Support for legacy configuration option

View File

@ -27,6 +27,7 @@ var _ = Describe("Legacy Options", func() {
legacyOpts.LegacyUpstreams.Upstreams = []string{"http://foo.bar/baz", "file:///var/lib/website#/bar", "static://204"}
legacyOpts.LegacyProvider.ClientID = "oauth-proxy"
legacyOpts.LegacyUpstreams.DisableKeepAlives = false
legacyOpts.LegacyProvider.OIDCEnabledSigningAlgs = []string{"EdDSA"}
staticCode := 204
opts.UpstreamServers = UpstreamConfig{
@ -128,6 +129,7 @@ var _ = Describe("Legacy Options", func() {
opts.Providers[0].OIDCConfig.ExtraAudiences = []string{}
opts.Providers[0].OIDCConfig.InsecureSkipNonce = ptr.To(true)
opts.Providers[0].OIDCConfig.InsecureSkipIssuerVerification = ptr.To(false)
opts.Providers[0].OIDCConfig.EnabledSigningAlgs = []string{"EdDSA"}
opts.Providers[0].LoginURLParameters = []LoginURLParameter{
{Name: "approval_prompt", Default: []string{"force"}},
}

View File

@ -318,6 +318,8 @@ type OIDCOptions struct {
// ExtraAudiences is a list of additional audiences that are allowed
// to pass verification in addition to the client id.
ExtraAudiences []string `yaml:"extraAudiences,omitempty"`
// EnabledSigningAlgs is a list of allowed JWT signing algorithms
EnabledSigningAlgs []string `json:"enabledSigningAlgs"`
}
type LoginGovOptions struct {

View File

@ -99,6 +99,7 @@ func newProviderDataFromConfig(providerConfig options.Provider) (*ProviderData,
IssuerURL: providerConfig.OIDCConfig.IssuerURL,
JWKsURL: providerConfig.OIDCConfig.JwksURL,
PublicKeyFiles: providerConfig.OIDCConfig.PublicKeyFiles,
SupportedSigningAlgs: providerConfig.OIDCConfig.EnabledSigningAlgs,
SkipDiscovery: ptr.Deref(providerConfig.OIDCConfig.SkipDiscovery, options.DefaultSkipDiscovery),
SkipIssuerVerification: ptr.Deref(providerConfig.OIDCConfig.InsecureSkipIssuerVerification, options.DefaultInsecureSkipIssuerVerification),
})