refactor: apply suggestions from code review

Co-authored-by: Amir Zarrinkafsh <nightah@me.com>
Signed-off-by: James Elliott <james-d-elliott@users.noreply.github.com>
fix-pkce-flow
James Elliott 2023-05-11 16:45:20 +10:00
parent aaeb3aa881
commit 2445b2e23a
No known key found for this signature in database
GPG Key ID: 0F1C4A096E857E49
40 changed files with 218 additions and 214 deletions

View File

@ -11,7 +11,7 @@
## - when using docker the container expects this by default to be at /config/configuration.yml
## - the default location where this file is loaded from can be overridden with the X_AUTHELIA_CONFIG environment var
## - the comments in this configuration file are helpful but users should consult the official documentation on the
## website at https://www.authellia.com/ or https://www.authelia.com/configuration/prologue/introduction/
## website at https://www.authelia.com/ or https://www.authelia.com/configuration/prologue/introduction/
## - this configuration file template is not automatically updated
##
@ -1387,7 +1387,7 @@ notifier:
# id_token_signing_alg: 'RS256'
## The algorithm used to sign userinfo endpoint responses for this client, either none or RS256.
# userinfo_signing_algorithm: 'none'
# userinfo_signing_alg: 'none'
## Trusted public keys configuration for request object signing for things such as private_key_jwt
# public_keys:

View File

@ -16,7 +16,7 @@ This section covers specifics regarding configuring the providers registered cli
provider specific configuration and information not related to clients see the [OpenID Connect 1.0 Provider](provider.md)
documentation.
More information about the beta can be found in the [roadmap](../../../roadmap/active/openid-connect.md) and in the
More information about OpenID Connect can be found in the [roadmap](../../../roadmap/active/openid-connect.md) and in the
[integration](../../../integration/openid-connect/introduction.md) documentation.
## Configuration
@ -60,7 +60,7 @@ identity_providers:
token_endpoint_auth_signing_alg: RS256
id_token_signing_alg: RS256
request_object_signing_alg: RS256
userinfo_signing_algorithm: none
userinfo_signing_alg: none
```
## Options
@ -319,7 +319,7 @@ See the response object section of the [integration guide](../../../integration/
for more information including the algorithm column for supported values. In addition to the values listed we also
support `none` as a value for this endpoint.
### userinfo_signing_algorithm
### userinfo_signing_alg
{{< confkey type="string" default="none" required="no" >}}

View File

@ -77,9 +77,9 @@ other configuration using the environment but instead of loading a file the valu
[authentication_backend.ldap.password]: ../first-factor/ldap.md#password
[authentication_backend.ldap.tls.certificate_chain]: ../first-factor/ldap.md#tls
[authentication_backend.ldap.tls.private_key]: ../first-factor/ldap.md#tls
[identity_providers.oidc.issuer_certificate_chain]: ../identity-providers/openid-connectx.md#issuercertificatechain
[identity_providers.oidc.issuer_private_key]: ../identity-providers/openid-connectx.md#issuerprivatekey
[identity_providers.oidc.hmac_secret]: ../identity-providers/openid-connectx.md#hmacsecret
[identity_providers.oidc.issuer_certificate_chain]: ../identity-providers/openid-connect.md#issuercertificatechain
[identity_providers.oidc.issuer_private_key]: ../identity-providers/openid-connect.md#issuerprivatekey
[identity_providers.oidc.hmac_secret]: ../identity-providers/openid-connect.md#hmacsecret
## Secrets in configuration file

View File

@ -44,7 +44,7 @@ accepted is recorded and checked in the browser
If the user has not accepted the policy they should not be able to interact with the Authelia UI via normal means.
Administrators who are required to abide by the [GDPR] or other privacy laws should be advised that
[OpenID Connect 1.0](../identity-providers/openid-connectx.md) clients configured with the `implicit` consent mode are
[OpenID Connect 1.0](../identity-providers/openid-connect.md) clients configured with the `implicit` consent mode are
unlikely to trigger the display of the Authelia UI if the user is already authenticated.
We wont be adding checks like this to the `implicit` consent mode when that mode in particular is unlikely to be

View File

@ -78,7 +78,7 @@ identity_providers:
- 'id_token'
grant_types:
- 'implicit'
userinfo_signing_algorithm: 'none'
userinfo_signing_alg: 'none'
```
## See Also

View File

@ -77,7 +77,7 @@ identity_providers:
- 'groups'
- 'email'
- 'profile'
userinfo_signing_algorithm: 'none'
userinfo_signing_alg: 'none'
- id: 'argocd-cli'
description: 'Argo CD (CLI)'
public: true
@ -90,7 +90,7 @@ identity_providers:
- 'email'
- 'profile'
- 'offline_access'
userinfo_signing_algorithm: 'none'
userinfo_signing_alg: 'none'
```
## See Also

View File

@ -78,7 +78,7 @@ identity_providers:
- 'openid'
- 'profile'
- 'email'
userinfo_signing_algorithm: 'none'
userinfo_signing_alg: 'none'
```
## See Also

View File

@ -86,7 +86,7 @@ identity_providers:
- 'openid'
- 'profile'
- 'email'
userinfo_signing_algorithm: 'none'
userinfo_signing_alg: 'none'
```
## See Also

View File

@ -89,7 +89,7 @@ identity_providers:
- 'openid'
- 'email'
- 'profile'
userinfo_signing_algorithm: 'none'
userinfo_signing_alg: 'none'
```
## See Also

View File

@ -97,7 +97,7 @@ identity_providers:
- 'openid'
- 'email'
- 'profile'
userinfo_signing_algorithm: 'none'
userinfo_signing_alg: 'none'
```
## See Also

View File

@ -90,7 +90,7 @@ identity_providers:
- 'profile'
- 'groups'
- 'email'
userinfo_signing_algorithm: 'none'
userinfo_signing_alg: 'none'
```
## See Also

View File

@ -108,7 +108,7 @@ identity_providers:
- 'profile'
- 'groups'
- 'email'
userinfo_signing_algorithm: 'none'
userinfo_signing_alg: 'none'
```
## See Also

View File

@ -81,7 +81,7 @@ identity_providers:
- 'profile'
- 'groups'
- 'email'
userinfo_signing_algorithm: 'none'
userinfo_signing_alg: 'none'
```
## See Also

View File

@ -65,7 +65,7 @@ identity_providers:
- 'profile'
- 'groups'
- 'email'
userinfo_signing_algorithm: 'none'
userinfo_signing_alg: 'none'
```
## See Also

View File

@ -255,7 +255,7 @@ Below is a list of the potential values we place in the [Claim] and their meanin
## User Information Signing Algorithm
The following table describes the response from the [UserInfo] endpoint depending on the
[userinfo_signing_algorithm](../../configuration/identity-providers/openid-connect/clients.md#userinfosigningalgorithm).
[userinfo_signing_alg](../../configuration/identity-providers/openid-connect/clients.md#userinfosigningalg).
| Signing Algorithm | Encoding | Content Type |
|:-----------------:|:------------:|:-----------------------------------:|

View File

@ -80,7 +80,7 @@ identity_providers:
- 'groups'
- 'email'
consent_mode: 'implicit'
userinfo_signing_algorithm: 'none'
userinfo_signing_alg: 'none'
```
## See Also

View File

@ -87,7 +87,7 @@ identity_providers:
- 'email'
grant_types:
- 'authorization_code'
userinfo_signing_algorithm: 'none'
userinfo_signing_alg: 'none'
```
## See Also

View File

@ -84,7 +84,7 @@ identity_providers:
- 'profile'
- 'email'
- 'groups'
userinfo_signing_algorithm: 'none'
userinfo_signing_alg: 'none'
```
## See Also

View File

@ -104,7 +104,7 @@ identity_providers:
- 'code'
response_modes:
- 'query'
userinfo_signing_algorithm: 'none'
userinfo_signing_alg: 'none'
```
---

View File

@ -107,7 +107,7 @@ identity_providers:
- 'profile'
- 'email'
- 'groups'
userinfo_signing_algorithm: 'none'
userinfo_signing_alg: 'none'
```
## See Also

View File

@ -81,7 +81,7 @@ identity_providers:
- 'offline_access'
- 'profile'
- 'email'
userinfo_signing_algorithm: 'none'
userinfo_signing_alg: 'none'
```
## See Also

View File

@ -82,7 +82,7 @@ identity_providers:
- 'profile'
- 'groups'
- 'email'
userinfo_signing_algorithm: 'none'
userinfo_signing_alg: 'none'
```
## See Also

View File

@ -85,7 +85,7 @@ identity_providers:
- 'openid'
- 'profile'
- 'email'
userinfo_signing_algorithm: 'none'
userinfo_signing_alg: 'none'
```
## See Also

View File

@ -89,7 +89,7 @@ identity_providers:
- 'openid'
- 'profile'
- 'email'
userinfo_signing_algorithm: 'none'
userinfo_signing_alg: 'none'
```
## See Also

View File

@ -83,7 +83,7 @@ identity_providers:
- 'openid'
- 'profile'
- 'email'
userinfo_signing_algorithm: 'none'
userinfo_signing_alg: 'none'
```
## See Also

View File

@ -86,7 +86,7 @@ identity_providers:
- 'profile'
- 'groups'
- 'email'
userinfo_signing_algorithm: 'none'
userinfo_signing_alg: 'none'
```
## See Also

View File

@ -115,8 +115,15 @@ Feature List:
{{< roadmap-status stage="in-progress" version="v4.38.0" >}}
* [OAuth 2.0 Pushed Authorization Requests](https://datatracker.ietf.org/doc/html/rfc9126)
* [RFC9126: OAuth 2.0 Pushed Authorization Requests](https://datatracker.ietf.org/doc/html/rfc9126)
* [RFC7523: JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants](https://datatracker.ietf.org/doc/html/rfc7523):
* Client Auth Method `client_secret_jwt`
* Client Auth Method `private_key_jwt`
* Per-Client [Proof Key Code Exchange (PKCE)] Policy
* Multiple Issuer JWKs:
* RS256, RS384, RS512
* PS256, PS384, PS512
* ES256, ES384, ES512
### Beta 7

File diff suppressed because one or more lines are too long

View File

@ -11,7 +11,7 @@
## - when using docker the container expects this by default to be at /config/configuration.yml
## - the default location where this file is loaded from can be overridden with the X_AUTHELIA_CONFIG environment var
## - the comments in this configuration file are helpful but users should consult the official documentation on the
## website at https://www.authellia.com/ or https://www.authelia.com/configuration/prologue/introduction/
## website at https://www.authelia.com/ or https://www.authelia.com/configuration/prologue/introduction/
## - this configuration file template is not automatically updated
##
@ -1387,7 +1387,7 @@ notifier:
# id_token_signing_alg: 'RS256'
## The algorithm used to sign userinfo endpoint responses for this client, either none or RS256.
# userinfo_signing_algorithm: 'none'
# userinfo_signing_alg: 'none'
## Trusted public keys configuration for request object signing for things such as private_key_jwt
# public_keys:

View File

@ -253,4 +253,12 @@ var deprecations = map[string]Deprecation{
MapFunc: nil,
ErrFunc: nil,
},
"identity_providers.oidc.clients[].userinfo_signing_algorithm": {
Version: model.SemanticVersion{Major: 4, Minor: 38},
Key: "identity_providers.oidc.clients[].userinfo_signing_algorithm",
NewKey: "identity_providers.oidc.clients[].userinfo_signing_alg",
AutoMap: true,
MapFunc: nil,
ErrFunc: nil,
},
}

View File

@ -245,37 +245,6 @@ func TestShouldLoadURLList(t *testing.T) {
assert.Equal(t, "https://example.com", config.IdentityProviders.OIDC.CORS.AllowedOrigins[1].String())
}
/*
func TestShouldLoadNewOIDCConfig(t *testing.T) {
val := schema.NewStructValidator()
_, config, err := Load(val, NewDefaultSources([]string{"./test_resources/config_oidc_modern.yml"}, DefaultEnvPrefix, DefaultEnvDelimiter)...)
assert.NoError(t, err)
assert.Len(t, val.Errors(), 0)
assert.Len(t, val.Warnings(), 0)
val.Clear()
validator.ValidateIdentityProviders(&config.IdentityProviders, val)
assert.Len(t, val.Errors(), 0)
assert.Len(t, config.IdentityProviders.OIDC.IssuerPrivateKeys.Keys, 2)
assert.Equal(t, "keya", config.IdentityProviders.OIDC.IssuerPrivateKeys.DefaultKeyID)
assert.Equal(t, oidc.KeyUseSignature, config.IdentityProviders.OIDC.IssuerPrivateKeys.Keys["keya"].Use)
assert.Equal(t, oidc.SigningAlgRSAUsingSHA256, config.IdentityProviders.OIDC.IssuerPrivateKeys.Keys["keya"].Algorithm)
assert.Equal(t, oidc.KeyUseSignature, config.IdentityProviders.OIDC.IssuerPrivateKeys.Keys["ec521"].Use)
assert.Equal(t, oidc.SigningAlgECDSAUsingP521AndSHA512, config.IdentityProviders.OIDC.IssuerPrivateKeys.Keys["ec521"].Algorithm)
assert.Contains(t, config.IdentityProviders.OIDC.Discovery.ResponseObjectSigningAlgs, oidc.SigningAlgRSAUsingSHA256)
assert.Contains(t, config.IdentityProviders.OIDC.Discovery.ResponseObjectSigningAlgs, oidc.SigningAlgECDSAUsingP521AndSHA512)
}.
*/
func TestShouldConfigureConsent(t *testing.T) {
val := schema.NewStructValidator()
keys, config, err := Load(val, NewDefaultSources([]string{"./test_resources/config_oidc.yml"}, DefaultEnvPrefix, DefaultEnvDelimiter)...)
@ -289,6 +258,7 @@ func TestShouldConfigureConsent(t *testing.T) {
require.Len(t, config.IdentityProviders.OIDC.Clients, 1)
assert.Equal(t, config.IdentityProviders.OIDC.Clients[0].ConsentMode, "explicit")
assert.Equal(t, "none", config.IdentityProviders.OIDC.Clients[0].UserinfoSigningAlg)
}
func TestShouldValidateAndRaiseErrorsOnBadConfiguration(t *testing.T) {

View File

@ -89,7 +89,7 @@ type OpenIDConnectClientConfiguration struct {
TokenEndpointAuthSigningAlg string `koanf:"token_endpoint_auth_signing_alg"`
RequestObjectSigningAlg string `koanf:"request_object_signing_alg"`
IDTokenSigningAlg string `koanf:"id_token_signing_alg"`
UserinfoSigningAlg string `koanf:"userinfo_signing_algorithm"`
UserinfoSigningAlg string `koanf:"userinfo_signing_alg"`
PublicKeys OpenIDConnectClientPublicKeys `koanf:"public_keys"`

View File

@ -61,7 +61,7 @@ var Keys = []string{
"identity_providers.oidc.clients[].token_endpoint_auth_signing_alg",
"identity_providers.oidc.clients[].request_object_signing_alg",
"identity_providers.oidc.clients[].id_token_signing_alg",
"identity_providers.oidc.clients[].userinfo_signing_algorithm",
"identity_providers.oidc.clients[].userinfo_signing_alg",
"identity_providers.oidc.clients[].public_keys.uri",
"identity_providers.oidc.clients[].public_keys.values",
"identity_providers.oidc.clients[].public_keys.values[].key_id",

View File

@ -102,6 +102,7 @@ func NewX509CertificateChain(in string) (chain *X509CertificateChain, err error)
return chain, nil
}
// NewX509CertificateChainFromCerts returns a chain from a given list of certificates without validation.
func NewX509CertificateChainFromCerts(in []*x509.Certificate) (chain X509CertificateChain) {
return X509CertificateChain{certs: in}
}

View File

@ -218,6 +218,11 @@ func TestNewX509CertificateChain(t *testing.T) {
}
}
func TestNewX509CertificateChainFromCerts(t *testing.T) {
have := NewX509CertificateChainFromCerts(nil)
assert.NotNil(t, have)
}
func TestX509CertificateChain(t *testing.T) {
chain := &X509CertificateChain{}

View File

@ -131,4 +131,5 @@ identity_providers:
- id: 'abc'
secret: '123'
consent_mode: 'explicit'
userinfo_signing_alg: 'none'
...

View File

@ -149,7 +149,6 @@ const (
"'public_clients_only' or 'always', but it's configured as '%s'"
errFmtOIDCProviderInsecureParameterEntropy = "openid connect provider: SECURITY ISSUE - minimum parameter entropy is " +
"configured to an unsafe value, it should be above 8 but it's configured to %d"
errFmtOIDCProviderPrivateKeysInvalid = "identity_providers: oidc: issuer_private_keys: key #%d: option 'key' must be a valid private key but the provided data is malformed as it's missing the public key bits"
errFmtOIDCProviderPrivateKeysCalcThumbprint = "identity_providers: oidc: issuer_private_keys: key #%d: option 'key' failed to calculate thumbprint to configure key id value: %w"
errFmtOIDCProviderPrivateKeysKeyIDLength = "identity_providers: oidc: issuer_private_keys: key #%d with key id '%s': option `key_id`` must be 7 characters or less"
@ -436,7 +435,7 @@ const (
attrOIDCGrantTypes = "grant_types"
attrOIDCRedirectURIs = "redirect_uris"
attrOIDCTokenAuthMethod = "token_endpoint_auth_method"
attrOIDCUsrSigAlg = "userinfo_signing_algorithm"
attrOIDCUsrSigAlg = "userinfo_signing_alg"
attrOIDCIDTokenSigAlg = "id_token_signing_alg"
attrOIDCPKCEChallengeMethod = "pkce_challenge_method"
)

View File

@ -12,7 +12,7 @@ import (
"strings"
"time"
"gopkg.in/square/go-jose.v2"
jose "gopkg.in/square/go-jose.v2"
"github.com/authelia/authelia/v4/internal/configuration/schema"
"github.com/authelia/authelia/v4/internal/oidc"
@ -77,7 +77,27 @@ func validateOIDCIssuerPrivateKey(config *schema.OpenIDConnectConfiguration) {
}}, config.IssuerPrivateKeys...)
}
//nolint:gocyclo // Refactor time permitting.
func jwkCalculateThumbprint(key schema.CryptographicKey) (thumbprintStr string, err error) {
j := jose.JSONWebKey{}
switch k := key.(type) {
case schema.CryptographicPrivateKey:
j.Key = k.Public()
case *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey:
j.Key = k
default:
return "", nil
}
var thumbprint []byte
if thumbprint, err = j.Thumbprint(crypto.SHA256); err != nil {
return "", err
}
return fmt.Sprintf("%x", thumbprint)[:6], nil
}
func validateOIDCIssuerPrivateKeys(config *schema.OpenIDConnectConfiguration, val *schema.StructValidator) {
var (
props *JWKProperties
@ -95,30 +115,11 @@ func validateOIDCIssuerPrivateKeys(config *schema.OpenIDConnectConfiguration, va
switch n := len(config.IssuerPrivateKeys[i].KeyID); {
case n == 0:
j := jose.JSONWebKey{}
switch key := config.IssuerPrivateKeys[i].Key.(type) {
case schema.CryptographicPrivateKey:
j.Key = key.Public()
case *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey:
j.Key = key
default:
break
}
if j.Key == nil {
break
}
var thumbprint []byte
if thumbprint, err = j.Thumbprint(crypto.SHA1); err != nil {
if config.IssuerPrivateKeys[i].KeyID, err = jwkCalculateThumbprint(config.IssuerPrivateKeys[i].Key); err != nil {
val.Push(fmt.Errorf(errFmtOIDCProviderPrivateKeysCalcThumbprint, i+1, err))
continue
}
config.IssuerPrivateKeys[i].KeyID = fmt.Sprintf("%x", thumbprint)[:6]
case n > 7:
val.Push(fmt.Errorf(errFmtOIDCProviderPrivateKeysKeyIDLength, i+1, config.IssuerPrivateKeys[i].KeyID))
}
@ -139,6 +140,16 @@ func validateOIDCIssuerPrivateKeys(config *schema.OpenIDConnectConfiguration, va
continue
}
validateOIDCIssuerPrivateKeysUseAlg(i, props, config, val)
validateOIDCIssuerPrivateKeyPair(i, config, val)
}
if len(config.Discovery.ResponseObjectSigningAlgs) != 0 && !utils.IsStringInSlice(oidc.SigningAlgRSAUsingSHA256, config.Discovery.ResponseObjectSigningAlgs) {
val.Push(fmt.Errorf(errFmtOIDCProviderPrivateKeysNoRS256, oidc.SigningAlgRSAUsingSHA256, strJoinAnd(config.Discovery.ResponseObjectSigningAlgs)))
}
}
func validateOIDCIssuerPrivateKeysUseAlg(i int, props *JWKProperties, config *schema.OpenIDConnectConfiguration, val *schema.StructValidator) {
switch config.IssuerPrivateKeys[i].Use {
case "":
config.IssuerPrivateKeys[i].Use = props.Use
@ -168,8 +179,13 @@ func validateOIDCIssuerPrivateKeys(config *schema.OpenIDConnectConfiguration, va
if config.IssuerPrivateKeys[i].Algorithm == oidc.SigningAlgRSAUsingSHA256 && config.Discovery.DefaultKeyID == "" {
config.Discovery.DefaultKeyID = config.IssuerPrivateKeys[i].KeyID
}
}
var checkEqualKey bool
func validateOIDCIssuerPrivateKeyPair(i int, config *schema.OpenIDConnectConfiguration, val *schema.StructValidator) {
var (
checkEqualKey bool
err error
)
switch key := config.IssuerPrivateKeys[i].Key.(type) {
case *rsa.PrivateKey:
@ -195,11 +211,6 @@ func validateOIDCIssuerPrivateKeys(config *schema.OpenIDConnectConfiguration, va
val.Push(fmt.Errorf(errFmtOIDCProviderPrivateKeysCertificateChainInvalid, i+1, config.IssuerPrivateKeys[i].KeyID, err))
}
}
}
if len(config.Discovery.ResponseObjectSigningAlgs) != 0 && !utils.IsStringInSlice(oidc.SigningAlgRSAUsingSHA256, config.Discovery.ResponseObjectSigningAlgs) {
val.Push(fmt.Errorf(errFmtOIDCProviderPrivateKeysNoRS256, oidc.SigningAlgRSAUsingSHA256, strJoinAnd(config.Discovery.ResponseObjectSigningAlgs)))
}
}
func setOIDCDefaults(config *schema.OpenIDConnectConfiguration) {
@ -388,7 +399,6 @@ func validateOIDCClientPublicKeys(c int, config *schema.OpenIDConnectConfigurati
}
}
//nolint:gocyclo
func validateOIDCClientJSONWebKeysList(c int, config *schema.OpenIDConnectConfiguration, val *schema.StructValidator) {
var (
props *JWKProperties
@ -406,33 +416,7 @@ func validateOIDCClientJSONWebKeysList(c int, config *schema.OpenIDConnectConfig
continue
}
switch config.Clients[c].PublicKeys.Values[i].Use {
case "":
config.Clients[c].PublicKeys.Values[i].Use = props.Use
case oidc.KeyUseSignature:
break
default:
val.Push(fmt.Errorf(errFmtOIDCClientPublicKeysInvalidOptionOneOf, config.Clients[c].ID, i+1, config.Clients[c].PublicKeys.Values[i].KeyID, attrOIDCKeyUse, strJoinOr([]string{oidc.KeyUseSignature}), config.Clients[c].PublicKeys.Values[i].Use))
}
switch {
case config.Clients[c].PublicKeys.Values[i].Algorithm == "":
config.Clients[c].PublicKeys.Values[i].Algorithm = props.Algorithm
case utils.IsStringInSlice(config.Clients[c].PublicKeys.Values[i].Algorithm, validOIDCIssuerJWKSigningAlgs):
break
default:
val.Push(fmt.Errorf(errFmtOIDCClientPublicKeysInvalidOptionOneOf, config.Clients[c].ID, i+1, config.Clients[c].PublicKeys.Values[i].KeyID, attrOIDCAlgorithm, strJoinOr(validOIDCIssuerJWKSigningAlgs), config.Clients[c].PublicKeys.Values[i].Algorithm))
}
if config.Clients[c].PublicKeys.Values[i].Algorithm != "" {
if !utils.IsStringInSlice(config.Clients[c].PublicKeys.Values[i].Algorithm, config.Discovery.RequestObjectSigningAlgs) {
config.Discovery.RequestObjectSigningAlgs = append(config.Discovery.RequestObjectSigningAlgs, config.Clients[c].PublicKeys.Values[i].Algorithm)
}
if !utils.IsStringInSlice(config.Clients[c].PublicKeys.Values[i].Algorithm, config.Clients[c].Discovery.RequestObjectSigningAlgs) {
config.Clients[c].Discovery.RequestObjectSigningAlgs = append(config.Clients[c].Discovery.RequestObjectSigningAlgs, config.Clients[c].PublicKeys.Values[i].Algorithm)
}
}
validateOIDCClientJSONWebKeysListKeyUseAlg(c, i, props, config, val)
var checkEqualKey bool
@ -473,6 +457,36 @@ func validateOIDCClientJSONWebKeysList(c int, config *schema.OpenIDConnectConfig
}
}
func validateOIDCClientJSONWebKeysListKeyUseAlg(c, i int, props *JWKProperties, config *schema.OpenIDConnectConfiguration, val *schema.StructValidator) {
switch config.Clients[c].PublicKeys.Values[i].Use {
case "":
config.Clients[c].PublicKeys.Values[i].Use = props.Use
case oidc.KeyUseSignature:
break
default:
val.Push(fmt.Errorf(errFmtOIDCClientPublicKeysInvalidOptionOneOf, config.Clients[c].ID, i+1, config.Clients[c].PublicKeys.Values[i].KeyID, attrOIDCKeyUse, strJoinOr([]string{oidc.KeyUseSignature}), config.Clients[c].PublicKeys.Values[i].Use))
}
switch {
case config.Clients[c].PublicKeys.Values[i].Algorithm == "":
config.Clients[c].PublicKeys.Values[i].Algorithm = props.Algorithm
case utils.IsStringInSlice(config.Clients[c].PublicKeys.Values[i].Algorithm, validOIDCIssuerJWKSigningAlgs):
break
default:
val.Push(fmt.Errorf(errFmtOIDCClientPublicKeysInvalidOptionOneOf, config.Clients[c].ID, i+1, config.Clients[c].PublicKeys.Values[i].KeyID, attrOIDCAlgorithm, strJoinOr(validOIDCIssuerJWKSigningAlgs), config.Clients[c].PublicKeys.Values[i].Algorithm))
}
if config.Clients[c].PublicKeys.Values[i].Algorithm != "" {
if !utils.IsStringInSlice(config.Clients[c].PublicKeys.Values[i].Algorithm, config.Discovery.RequestObjectSigningAlgs) {
config.Discovery.RequestObjectSigningAlgs = append(config.Discovery.RequestObjectSigningAlgs, config.Clients[c].PublicKeys.Values[i].Algorithm)
}
if !utils.IsStringInSlice(config.Clients[c].PublicKeys.Values[i].Algorithm, config.Clients[c].Discovery.RequestObjectSigningAlgs) {
config.Clients[c].Discovery.RequestObjectSigningAlgs = append(config.Clients[c].Discovery.RequestObjectSigningAlgs, config.Clients[c].PublicKeys.Values[i].Algorithm)
}
}
}
func validateOIDCClientSectorIdentifier(c int, config *schema.OpenIDConnectConfiguration, val *schema.StructValidator) {
if config.Clients[c].SectorIdentifier.String() != "" {
if utils.IsURLHostComponent(config.Clients[c].SectorIdentifier) || utils.IsURLHostComponentWithPort(config.Clients[c].SectorIdentifier) {

View File

@ -501,7 +501,7 @@ func TestShouldRaiseErrorOnCertificateNotValid(t *testing.T) {
assert.Len(t, validator.Warnings(), 0)
require.Len(t, validator.Errors(), 1)
assert.EqualError(t, validator.Errors()[0], "identity_providers: oidc: issuer_private_keys: key #1 with key id '9c7423': option 'certificate_chain' does not appear to contain the public key for the private key provided by option 'key'")
assert.EqualError(t, validator.Errors()[0], "identity_providers: oidc: issuer_private_keys: key #1 with key id 'bf1e10': option 'certificate_chain' does not appear to contain the public key for the private key provided by option 'key'")
}
func TestValidateIdentityProvidersShouldRaiseWarningOnSecurityIssue(t *testing.T) {
@ -1531,7 +1531,7 @@ func TestValidateOIDCClients(t *testing.T) {
},
nil,
[]string{
"identity_providers: oidc: clients: client 'test': option 'userinfo_signing_algorithm' must be one of 'RS256' or 'none' but it's configured as 'rs256'",
"identity_providers: oidc: clients: client 'test': option 'userinfo_signing_alg' must be one of 'RS256' or 'none' but it's configured as 'rs256'",
},
},
{
@ -2419,10 +2419,10 @@ func TestValidateOIDCIssuer(t *testing.T) {
schema.OpenIDConnectConfiguration{
IssuerPrivateKey: keyRSA2048,
IssuerPrivateKeys: []schema.JWK{
{KeyID: "e7dfdc", Key: keyRSA2048, Algorithm: oidc.SigningAlgRSAUsingSHA256, Use: oidc.KeyUseSignature},
{KeyID: "1f8bfc", Key: keyRSA2048, Algorithm: oidc.SigningAlgRSAUsingSHA256, Use: oidc.KeyUseSignature},
},
Discovery: schema.OpenIDConnectDiscovery{
DefaultKeyID: "e7dfdc",
DefaultKeyID: "1f8bfc",
ResponseObjectSigningAlgs: []string{oidc.SigningAlgRSAUsingSHA256},
},
},
@ -2440,13 +2440,13 @@ func TestValidateOIDCIssuer(t *testing.T) {
},
schema.OpenIDConnectConfiguration{
IssuerPrivateKeys: []schema.JWK{
{Key: keyRSA2048, CertificateChain: certRSA2048, Algorithm: oidc.SigningAlgRSAUsingSHA256, Use: oidc.KeyUseSignature, KeyID: "e7dfdc"},
{Key: keyECDSAP256, CertificateChain: certECDSAP256, Algorithm: oidc.SigningAlgECDSAUsingP256AndSHA256, Use: oidc.KeyUseSignature, KeyID: "29b3f2"},
{Key: keyECDSAP384, CertificateChain: certECDSAP384, Algorithm: oidc.SigningAlgECDSAUsingP384AndSHA384, Use: oidc.KeyUseSignature, KeyID: "e968b4"},
{Key: keyECDSAP521, CertificateChain: certECDSAP521, Algorithm: oidc.SigningAlgECDSAUsingP521AndSHA512, Use: oidc.KeyUseSignature, KeyID: "6b20c3"},
{Key: keyRSA2048, CertificateChain: certRSA2048, Algorithm: oidc.SigningAlgRSAUsingSHA256, Use: oidc.KeyUseSignature, KeyID: "1f8bfc"},
{Key: keyECDSAP256, CertificateChain: certECDSAP256, Algorithm: oidc.SigningAlgECDSAUsingP256AndSHA256, Use: oidc.KeyUseSignature, KeyID: "1e7788"},
{Key: keyECDSAP384, CertificateChain: certECDSAP384, Algorithm: oidc.SigningAlgECDSAUsingP384AndSHA384, Use: oidc.KeyUseSignature, KeyID: "ba8508"},
{Key: keyECDSAP521, CertificateChain: certECDSAP521, Algorithm: oidc.SigningAlgECDSAUsingP521AndSHA512, Use: oidc.KeyUseSignature, KeyID: "7ecbac"},
},
Discovery: schema.OpenIDConnectDiscovery{
DefaultKeyID: "e7dfdc",
DefaultKeyID: "1f8bfc",
ResponseObjectSigningAlgs: []string{oidc.SigningAlgRSAUsingSHA256, oidc.SigningAlgECDSAUsingP256AndSHA256, oidc.SigningAlgECDSAUsingP384AndSHA384, oidc.SigningAlgECDSAUsingP521AndSHA512},
},
},
@ -2462,16 +2462,16 @@ func TestValidateOIDCIssuer(t *testing.T) {
},
schema.OpenIDConnectConfiguration{
IssuerPrivateKeys: []schema.JWK{
{Key: keyRSA2048, CertificateChain: certRSA2048, Algorithm: oidc.SigningAlgRSAUsingSHA256, Use: oidc.KeyUseSignature, KeyID: "e7dfdc"},
{Key: keyRSA4096, CertificateChain: certRSA4096, Algorithm: oidc.SigningAlgRSAUsingSHA256, Use: oidc.KeyUseSignature, KeyID: "9c7423"},
{Key: keyRSA2048, CertificateChain: certRSA2048, Algorithm: oidc.SigningAlgRSAUsingSHA256, Use: oidc.KeyUseSignature, KeyID: "1f8bfc"},
{Key: keyRSA4096, CertificateChain: certRSA4096, Algorithm: oidc.SigningAlgRSAUsingSHA256, Use: oidc.KeyUseSignature, KeyID: "bf1e10"},
},
Discovery: schema.OpenIDConnectDiscovery{
DefaultKeyID: "e7dfdc",
DefaultKeyID: "1f8bfc",
ResponseObjectSigningAlgs: []string{oidc.SigningAlgRSAUsingSHA256},
},
},
[]string{
"identity_providers: oidc: issuer_private_keys: key #2 with key id '9c7423': option 'algorithm' must be unique",
"identity_providers: oidc: issuer_private_keys: key #2 with key id 'bf1e10': option 'algorithm' must be unique",
},
},
{
@ -2483,7 +2483,7 @@ func TestValidateOIDCIssuer(t *testing.T) {
},
schema.OpenIDConnectConfiguration{
IssuerPrivateKeys: []schema.JWK{
{Key: keyRSA4096, CertificateChain: certRSA4096, Algorithm: oidc.SigningAlgRSAUsingSHA512, Use: oidc.KeyUseSignature, KeyID: "9c7423"},
{Key: keyRSA4096, CertificateChain: certRSA4096, Algorithm: oidc.SigningAlgRSAUsingSHA512, Use: oidc.KeyUseSignature, KeyID: "bf1e10"},
},
Discovery: schema.OpenIDConnectDiscovery{
DefaultKeyID: "",
@ -2504,11 +2504,11 @@ func TestValidateOIDCIssuer(t *testing.T) {
},
schema.OpenIDConnectConfiguration{
IssuerPrivateKeys: []schema.JWK{
{Key: keyRSA4096, CertificateChain: certRSA4096, Algorithm: oidc.SigningAlgRSAUsingSHA256, Use: oidc.KeyUseSignature, KeyID: "9c7423"},
{Key: keyRSA4096, CertificateChain: certRSA4096, Algorithm: oidc.SigningAlgRSAUsingSHA256, Use: oidc.KeyUseSignature, KeyID: "bf1e10"},
{Key: keyECDSAP224, CertificateChain: certECDSAP224},
},
Discovery: schema.OpenIDConnectDiscovery{
DefaultKeyID: "9c7423",
DefaultKeyID: "bf1e10",
ResponseObjectSigningAlgs: []string{oidc.SigningAlgRSAUsingSHA256},
},
},
@ -2525,15 +2525,15 @@ func TestValidateOIDCIssuer(t *testing.T) {
},
schema.OpenIDConnectConfiguration{
IssuerPrivateKeys: []schema.JWK{
{Key: keyRSA1024, CertificateChain: certRSA1024, Algorithm: oidc.SigningAlgRSAUsingSHA256, Use: oidc.KeyUseSignature, KeyID: "a9c018"},
{Key: keyRSA1024, CertificateChain: certRSA1024, Algorithm: oidc.SigningAlgRSAUsingSHA256, Use: oidc.KeyUseSignature, KeyID: "cf375e"},
},
Discovery: schema.OpenIDConnectDiscovery{
DefaultKeyID: "a9c018",
DefaultKeyID: "cf375e",
ResponseObjectSigningAlgs: []string{oidc.SigningAlgRSAUsingSHA256},
},
},
[]string{
"identity_providers: oidc: issuer_private_keys: key #1 with key id 'a9c018': option 'key' is an RSA 1024 bit private key but it must at minimum be a RSA 2048 bit private key",
"identity_providers: oidc: issuer_private_keys: key #1 with key id 'cf375e': option 'key' is an RSA 1024 bit private key but it must at minimum be a RSA 2048 bit private key",
},
},
{
@ -2545,7 +2545,7 @@ func TestValidateOIDCIssuer(t *testing.T) {
},
schema.OpenIDConnectConfiguration{
IssuerPrivateKeys: []schema.JWK{
{Key: keyRSA4096, CertificateChain: certRSA4096, Algorithm: "invalid", Use: oidc.KeyUseSignature, KeyID: "9c7423"},
{Key: keyRSA4096, CertificateChain: certRSA4096, Algorithm: "invalid", Use: oidc.KeyUseSignature, KeyID: "bf1e10"},
},
Discovery: schema.OpenIDConnectDiscovery{
DefaultKeyID: "",
@ -2553,7 +2553,7 @@ func TestValidateOIDCIssuer(t *testing.T) {
},
},
[]string{
"identity_providers: oidc: issuer_private_keys: key #1 with key id '9c7423': option 'algorithm' must be one of 'RS256', 'PS256', 'ES256', 'RS384', 'PS384', 'ES384', 'RS512', 'PS512', or 'ES512' but it's configured as 'invalid'",
"identity_providers: oidc: issuer_private_keys: key #1 with key id 'bf1e10': option 'algorithm' must be one of 'RS256', 'PS256', 'ES256', 'RS384', 'PS384', 'ES384', 'RS512', 'PS512', or 'ES512' but it's configured as 'invalid'",
"identity_providers: oidc: issuer_private_keys: keys: must at least have one key supporting the 'RS256' algorithm but only has 'invalid'",
},
},
@ -2566,15 +2566,15 @@ func TestValidateOIDCIssuer(t *testing.T) {
},
schema.OpenIDConnectConfiguration{
IssuerPrivateKeys: []schema.JWK{
{Key: keyRSA4096, CertificateChain: certRSA4096, Algorithm: oidc.SigningAlgRSAUsingSHA256, Use: "invalid", KeyID: "9c7423"},
{Key: keyRSA4096, CertificateChain: certRSA4096, Algorithm: oidc.SigningAlgRSAUsingSHA256, Use: "invalid", KeyID: "bf1e10"},
},
Discovery: schema.OpenIDConnectDiscovery{
DefaultKeyID: "9c7423",
DefaultKeyID: "bf1e10",
ResponseObjectSigningAlgs: []string{oidc.SigningAlgRSAUsingSHA256},
},
},
[]string{
"identity_providers: oidc: issuer_private_keys: key #1 with key id '9c7423': option 'use' must be one of 'sig' but it's configured as 'invalid'",
"identity_providers: oidc: issuer_private_keys: key #1 with key id 'bf1e10': option 'use' must be one of 'sig' but it's configured as 'invalid'",
},
},
{
@ -2648,7 +2648,7 @@ func TestValidateOIDCIssuer(t *testing.T) {
},
schema.OpenIDConnectConfiguration{
IssuerPrivateKeys: []schema.JWK{
{Key: keyEd2519, CertificateChain: certEd15519, KeyID: "d2dd94"},
{Key: keyEd2519, CertificateChain: certEd15519, KeyID: "14dfd3"},
},
Discovery: schema.OpenIDConnectDiscovery{
DefaultKeyID: "",
@ -2656,7 +2656,7 @@ func TestValidateOIDCIssuer(t *testing.T) {
},
},
[]string{
"identity_providers: oidc: issuer_private_keys: key #1 with key id 'd2dd94': option 'key' must be a RSA private key or ECDSA private key but it's type is ed25519.PrivateKey",
"identity_providers: oidc: issuer_private_keys: key #1 with key id '14dfd3': option 'key' must be a RSA private key or ECDSA private key but it's type is ed25519.PrivateKey",
},
},
{
@ -2668,15 +2668,15 @@ func TestValidateOIDCIssuer(t *testing.T) {
},
schema.OpenIDConnectConfiguration{
IssuerPrivateKeys: []schema.JWK{
{Key: publicRSA2048Pair, Algorithm: oidc.SigningAlgRSAUsingSHA256, Use: oidc.KeyUseSignature, KeyID: "904c62"},
{Key: publicRSA2048Pair, Algorithm: oidc.SigningAlgRSAUsingSHA256, Use: oidc.KeyUseSignature, KeyID: "9a0e71"},
},
Discovery: schema.OpenIDConnectDiscovery{
DefaultKeyID: "904c62",
DefaultKeyID: "9a0e71",
ResponseObjectSigningAlgs: []string{oidc.SigningAlgRSAUsingSHA256},
},
},
[]string{
"identity_providers: oidc: issuer_private_keys: key #1 with key id '904c62': option 'key' must be a RSA private key or ECDSA private key but it's type is *rsa.PublicKey",
"identity_providers: oidc: issuer_private_keys: key #1 with key id '9a0e71': option 'key' must be a RSA private key or ECDSA private key but it's type is *rsa.PublicKey",
},
},
{
@ -2688,15 +2688,15 @@ func TestValidateOIDCIssuer(t *testing.T) {
},
schema.OpenIDConnectConfiguration{
IssuerPrivateKeys: []schema.JWK{
{Key: keyRSA2048, CertificateChain: frankenchain, Algorithm: oidc.SigningAlgRSAUsingSHA256, Use: oidc.KeyUseSignature, KeyID: "e7dfdc"},
{Key: keyRSA2048, CertificateChain: frankenchain, Algorithm: oidc.SigningAlgRSAUsingSHA256, Use: oidc.KeyUseSignature, KeyID: "1f8bfc"},
},
Discovery: schema.OpenIDConnectDiscovery{
DefaultKeyID: "e7dfdc",
DefaultKeyID: "1f8bfc",
ResponseObjectSigningAlgs: []string{oidc.SigningAlgRSAUsingSHA256},
},
},
[]string{
"identity_providers: oidc: issuer_private_keys: key #1 with key id 'e7dfdc': option 'certificate_chain' produced an error during validation of the chain: certificate #1 in chain is not signed properly by certificate #2 in chain: x509: invalid signature: parent certificate cannot sign this kind of certificate",
"identity_providers: oidc: issuer_private_keys: key #1 with key id '1f8bfc': option 'certificate_chain' produced an error during validation of the chain: certificate #1 in chain is not signed properly by certificate #2 in chain: x509: invalid signature: parent certificate cannot sign this kind of certificate",
},
},
{
@ -2871,7 +2871,6 @@ const (
pathCrypto = "../test_resources/crypto/%s.%s"
)
//nolint:unused
var (
tOpenIDConnectPBKDF2ClientSecret, tOpenIDConnectPlainTextClientSecret *schema.PasswordDigest
@ -2889,7 +2888,7 @@ var (
// Standard ECDSA key / certificate pairs.
keyECDSAP256PKCS8, keyECDSAP384PKCS8, keyECDSAP521PKCS8 *ecdsa.PrivateKey
certECDSAP224PKCS8, certECDSAP256PKCS8, certECDSAP384PKCS8, certECDSAP521PKCS8 schema.X509CertificateChain
certECDSAP224PKCS8, certECDSAP256PKCS8, certECDSAP384PKCS8, certECDSAP521PKCS8 schema.X509CertificateChain //nolint:unused
// Ed15519 key / certificate pair.
keyEd2519 ed25519.PrivateKey

View File

@ -209,7 +209,7 @@ func TestNewOpenIDConnectProviderDiscovery(t *testing.T) {
assert.Equal(t, y, z)
}
func TestOpenIDConnectProvider_NewOpenIDConnectProvider_GetOpenIDConnectWellKnownConfiguration(t *testing.T) {
func TestNewOpenIDConnectProvider_GetOpenIDConnectWellKnownConfiguration(t *testing.T) {
provider := oidc.NewOpenIDConnectProvider(&schema.OpenIDConnectConfiguration{
IssuerCertificateChain: schema.X509CertificateChain{},
IssuerPrivateKey: keyRSA2048,
@ -336,7 +336,7 @@ func TestOpenIDConnectProvider_NewOpenIDConnectProvider_GetOpenIDConnectWellKnow
assert.Contains(t, disco.PromptValuesSupported, oidc.PromptNone)
}
func TestOpenIDConnectProvider_NewOpenIDConnectProvider_GetOAuth2WellKnownConfiguration(t *testing.T) {
func TestNewOpenIDConnectProvider_GetOAuth2WellKnownConfiguration(t *testing.T) {
provider := oidc.NewOpenIDConnectProvider(&schema.OpenIDConnectConfiguration{
IssuerCertificateChain: schema.X509CertificateChain{},
IssuerPrivateKey: keyRSA2048,
@ -426,7 +426,7 @@ func TestOpenIDConnectProvider_NewOpenIDConnectProvider_GetOAuth2WellKnownConfig
assert.Contains(t, disco.ClaimsSupported, oidc.ClaimFullName)
}
func TestOpenIDConnectProvider_NewOpenIDConnectProvider_GetOpenIDConnectWellKnownConfigurationWithPlainPKCE(t *testing.T) {
func TestNewOpenIDConnectProvider_GetOpenIDConnectWellKnownConfigurationWithPlainPKCE(t *testing.T) {
provider := oidc.NewOpenIDConnectProvider(&schema.OpenIDConnectConfiguration{
IssuerCertificateChain: schema.X509CertificateChain{},
IssuerPrivateKey: keyRSA2048,