2021-05-04 22:06:05 +00:00
package validator
import (
2023-05-15 00:03:19 +00:00
"crypto/ecdsa"
"crypto/ed25519"
2022-10-02 02:07:40 +00:00
"crypto/rsa"
"crypto/x509"
2021-05-04 22:06:05 +00:00
"errors"
"fmt"
2022-04-07 06:13:01 +00:00
"net/url"
2023-05-15 00:03:19 +00:00
"os"
"strings"
2021-05-04 22:06:05 +00:00
"testing"
feat(oidc): add additional config options, accurate token times, and refactoring (#1991)
* This gives admins more control over their OIDC installation exposing options that had defaults before. Things like lifespans for authorize codes, access tokens, id tokens, refresh tokens, a option to enable the debug client messages, minimum parameter entropy. It also allows admins to configure the response modes.
* Additionally this records specific values about a users session indicating when they performed a specific authz factor so this is represented in the token accurately.
* Lastly we also implemented a OIDC key manager which calculates the kid for jwk's using the SHA1 digest instead of being static, or more specifically the first 7 chars. As per https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key#section-8.1.1 the kid should not exceed 8 chars. While it's allowed to exceed 8 chars, it must only be done so with a compelling reason, which we do not have.
2021-07-03 23:44:30 +00:00
"time"
2021-05-04 22:06:05 +00:00
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
2021-08-11 01:04:35 +00:00
"github.com/authelia/authelia/v4/internal/configuration/schema"
2022-04-07 00:58:51 +00:00
"github.com/authelia/authelia/v4/internal/oidc"
"github.com/authelia/authelia/v4/internal/utils"
2021-05-04 22:06:05 +00:00
)
func TestShouldRaiseErrorWhenInvalidOIDCServerConfiguration ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := & schema . IdentityProvidersConfiguration {
OIDC : & schema . OpenIDConnectConfiguration {
2022-10-02 02:07:40 +00:00
HMACSecret : "abc" ,
2021-05-04 22:06:05 +00:00
} ,
}
ValidateIdentityProviders ( config , validator )
require . Len ( t , validator . Errors ( ) , 2 )
2023-05-15 00:32:10 +00:00
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , "identity_providers: oidc: option `issuer_private_keys` or 'issuer_private_key' is required" )
2023-04-13 10:58:18 +00:00
assert . EqualError ( t , validator . Errors ( ) [ 1 ] , "identity_providers: oidc: option 'clients' must have one or more clients configured" )
2021-05-04 22:06:05 +00:00
}
2022-04-07 00:58:51 +00:00
func TestShouldNotRaiseErrorWhenCORSEndpointsValid ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := & schema . IdentityProvidersConfiguration {
OIDC : & schema . OpenIDConnectConfiguration {
HMACSecret : "rLABDrx87et5KvRHVUgTm3pezWWd8LMN" ,
2023-05-15 00:03:19 +00:00
IssuerPrivateKey : keyRSA2048 ,
2022-04-07 00:58:51 +00:00
CORS : schema . OpenIDConnectCORSConfiguration {
2022-10-20 02:16:36 +00:00
Endpoints : [ ] string { oidc . EndpointAuthorization , oidc . EndpointToken , oidc . EndpointIntrospection , oidc . EndpointRevocation , oidc . EndpointUserinfo } ,
2022-04-07 00:58:51 +00:00
} ,
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "example" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPlainTextClientSecret ,
2022-04-07 00:58:51 +00:00
} ,
} ,
} ,
}
ValidateIdentityProviders ( config , validator )
assert . Len ( t , validator . Errors ( ) , 0 )
}
func TestShouldRaiseErrorWhenCORSEndpointsNotValid ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := & schema . IdentityProvidersConfiguration {
OIDC : & schema . OpenIDConnectConfiguration {
HMACSecret : "rLABDrx87et5KvRHVUgTm3pezWWd8LMN" ,
2023-05-15 00:03:19 +00:00
IssuerPrivateKey : keyRSA2048 ,
2022-04-07 00:58:51 +00:00
CORS : schema . OpenIDConnectCORSConfiguration {
2022-10-20 02:16:36 +00:00
Endpoints : [ ] string { oidc . EndpointAuthorization , oidc . EndpointToken , oidc . EndpointIntrospection , oidc . EndpointRevocation , oidc . EndpointUserinfo , "invalid_endpoint" } ,
2022-04-07 00:58:51 +00:00
} ,
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "example" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPlainTextClientSecret ,
2022-04-07 00:58:51 +00:00
} ,
} ,
} ,
}
ValidateIdentityProviders ( config , validator )
require . Len ( t , validator . Errors ( ) , 1 )
2023-04-13 10:58:18 +00:00
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , "identity_providers: oidc: cors: option 'endpoints' contains an invalid value 'invalid_endpoint': must be one of 'authorization', 'pushed-authorization-request', 'token', 'introspection', 'revocation', or 'userinfo'" )
2022-04-07 00:58:51 +00:00
}
2022-03-02 04:44:05 +00:00
func TestShouldRaiseErrorWhenOIDCPKCEEnforceValueInvalid ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := & schema . IdentityProvidersConfiguration {
OIDC : & schema . OpenIDConnectConfiguration {
HMACSecret : "rLABDrx87et5KvRHVUgTm3pezWWd8LMN" ,
2023-05-15 00:03:19 +00:00
IssuerPrivateKey : keyRSA2048 ,
2022-10-17 10:51:59 +00:00
EnforcePKCE : testInvalid ,
2022-03-02 04:44:05 +00:00
} ,
}
ValidateIdentityProviders ( config , validator )
require . Len ( t , validator . Errors ( ) , 2 )
2023-04-13 10:58:18 +00:00
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , "identity_providers: oidc: option 'enforce_pkce' must be 'never', 'public_clients_only' or 'always', but it's configured as 'invalid'" )
assert . EqualError ( t , validator . Errors ( ) [ 1 ] , "identity_providers: oidc: option 'clients' must have one or more clients configured" )
2022-03-02 04:44:05 +00:00
}
2022-04-07 00:58:51 +00:00
func TestShouldRaiseErrorWhenOIDCCORSOriginsHasInvalidValues ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := & schema . IdentityProvidersConfiguration {
OIDC : & schema . OpenIDConnectConfiguration {
HMACSecret : "rLABDrx87et5KvRHVUgTm3pezWWd8LMN" ,
2023-05-15 00:03:19 +00:00
IssuerPrivateKey : keyRSA2048 ,
2022-04-07 00:58:51 +00:00
CORS : schema . OpenIDConnectCORSConfiguration {
AllowedOrigins : utils . URLsFromStringSlice ( [ ] string { "https://example.com/" , "https://site.example.com/subpath" , "https://site.example.com?example=true" , "*" } ) ,
AllowedOriginsFromClientRedirectURIs : true ,
} ,
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "myclient" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPlainTextClientSecret ,
2022-04-07 00:58:51 +00:00
Policy : "two_factor" ,
RedirectURIs : [ ] string { "https://example.com/oauth2_callback" , "https://localhost:566/callback" , "http://an.example.com/callback" , "file://a/file" } ,
} ,
} ,
} ,
}
ValidateIdentityProviders ( config , validator )
2022-11-21 00:52:27 +00:00
require . Len ( t , validator . Errors ( ) , 5 )
2022-04-07 00:58:51 +00:00
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , "identity_providers: oidc: cors: option 'allowed_origins' contains an invalid value 'https://example.com/' as it has a path: origins must only be scheme, hostname, and an optional port" )
assert . EqualError ( t , validator . Errors ( ) [ 1 ] , "identity_providers: oidc: cors: option 'allowed_origins' contains an invalid value 'https://site.example.com/subpath' as it has a path: origins must only be scheme, hostname, and an optional port" )
assert . EqualError ( t , validator . Errors ( ) [ 2 ] , "identity_providers: oidc: cors: option 'allowed_origins' contains an invalid value 'https://site.example.com?example=true' as it has a query string: origins must only be scheme, hostname, and an optional port" )
assert . EqualError ( t , validator . Errors ( ) [ 3 ] , "identity_providers: oidc: cors: option 'allowed_origins' contains the wildcard origin '*' with more than one origin but the wildcard origin must be defined by itself" )
assert . EqualError ( t , validator . Errors ( ) [ 4 ] , "identity_providers: oidc: cors: option 'allowed_origins' contains the wildcard origin '*' cannot be specified with option 'allowed_origins_from_client_redirect_uris' enabled" )
require . Len ( t , config . OIDC . CORS . AllowedOrigins , 6 )
assert . Equal ( t , "*" , config . OIDC . CORS . AllowedOrigins [ 3 ] . String ( ) )
assert . Equal ( t , "https://example.com" , config . OIDC . CORS . AllowedOrigins [ 4 ] . String ( ) )
}
func TestShouldRaiseErrorWhenOIDCServerNoClients ( t * testing . T ) {
2021-05-04 22:06:05 +00:00
validator := schema . NewStructValidator ( )
config := & schema . IdentityProvidersConfiguration {
OIDC : & schema . OpenIDConnectConfiguration {
HMACSecret : "rLABDrx87et5KvRHVUgTm3pezWWd8LMN" ,
2023-05-15 00:03:19 +00:00
IssuerPrivateKey : keyRSA2048 ,
2021-05-04 22:06:05 +00:00
} ,
}
ValidateIdentityProviders ( config , validator )
require . Len ( t , validator . Errors ( ) , 1 )
2023-04-13 10:58:18 +00:00
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , "identity_providers: oidc: option 'clients' must have one or more clients configured" )
2021-05-04 22:06:05 +00:00
}
func TestShouldRaiseErrorWhenOIDCServerClientBadValues ( t * testing . T ) {
2022-04-07 06:13:01 +00:00
mustParseURL := func ( u string ) url . URL {
out , err := url . Parse ( u )
if err != nil {
panic ( err )
}
return * out
}
2022-01-21 11:05:53 +00:00
testCases := [ ] struct {
Name string
Clients [ ] schema . OpenIDConnectClientConfiguration
2022-04-07 06:13:01 +00:00
Errors [ ] string
2022-01-21 11:05:53 +00:00
} {
{
2022-04-07 06:13:01 +00:00
Name : "EmptyIDAndSecret" ,
2021-05-04 22:06:05 +00:00
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
2022-01-21 11:05:53 +00:00
ID : "" ,
2022-10-20 03:21:45 +00:00
Secret : nil ,
2022-01-21 11:05:53 +00:00
Policy : "" ,
RedirectURIs : [ ] string { } ,
2021-05-04 22:06:05 +00:00
} ,
2022-01-21 11:05:53 +00:00
} ,
2022-04-07 06:13:01 +00:00
Errors : [ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client '': option 'secret' is required" ,
2023-04-13 10:58:18 +00:00
"identity_providers: oidc: clients: option 'id' is required but was absent on the clients in positions #1" ,
2022-01-21 11:05:53 +00:00
} ,
} ,
{
2022-04-07 06:13:01 +00:00
Name : "InvalidPolicy" ,
2022-01-21 11:05:53 +00:00
Clients : [ ] schema . OpenIDConnectClientConfiguration {
2021-05-04 22:06:05 +00:00
{
2022-01-21 11:05:53 +00:00
ID : "client-1" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPlainTextClientSecret ,
2021-05-04 22:06:05 +00:00
Policy : "a-policy" ,
RedirectURIs : [ ] string {
"https://google.com" ,
} ,
} ,
2022-01-21 11:05:53 +00:00
} ,
2023-04-13 10:58:18 +00:00
Errors : [ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'client-1': option 'authorization_policy' must be one of 'one_factor' or 'two_factor' but it's configured as 'a-policy'" ,
2023-04-13 10:58:18 +00:00
} ,
2022-01-21 11:05:53 +00:00
} ,
{
2022-04-07 06:13:01 +00:00
Name : "ClientIDDuplicated" ,
2022-01-21 11:05:53 +00:00
Clients : [ ] schema . OpenIDConnectClientConfiguration {
2021-05-04 22:06:05 +00:00
{
2022-01-21 11:05:53 +00:00
ID : "client-x" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPlainTextClientSecret ,
2022-01-21 11:05:53 +00:00
Policy : policyTwoFactor ,
RedirectURIs : [ ] string { } ,
} ,
{
ID : "client-x" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPlainTextClientSecret ,
2022-01-21 11:05:53 +00:00
Policy : policyTwoFactor ,
RedirectURIs : [ ] string { } ,
2021-05-04 22:06:05 +00:00
} ,
2022-01-21 11:05:53 +00:00
} ,
2023-04-13 10:58:18 +00:00
Errors : [ ] string {
"identity_providers: oidc: clients: option 'id' must be unique for every client but one or more clients share the following 'id' values 'client-x'" ,
} ,
2022-01-21 11:05:53 +00:00
} ,
{
2022-04-07 06:13:01 +00:00
Name : "RedirectURIInvalid" ,
2022-01-21 11:05:53 +00:00
Clients : [ ] schema . OpenIDConnectClientConfiguration {
2021-05-04 22:06:05 +00:00
{
ID : "client-check-uri-parse" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPlainTextClientSecret ,
2021-08-03 09:55:21 +00:00
Policy : policyTwoFactor ,
2021-05-04 22:06:05 +00:00
RedirectURIs : [ ] string {
"http://abc@%two" ,
} ,
} ,
2022-01-21 11:05:53 +00:00
} ,
2022-04-07 06:13:01 +00:00
Errors : [ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'client-check-uri-parse': option 'redirect_uris' has an invalid value: redirect uri 'http://abc@%two' could not be parsed: parse \"http://abc@%two\": invalid URL escape \"%tw\"" ,
2022-01-21 11:05:53 +00:00
} ,
} ,
{
2022-04-07 06:13:01 +00:00
Name : "RedirectURINotAbsolute" ,
2022-01-21 11:05:53 +00:00
Clients : [ ] schema . OpenIDConnectClientConfiguration {
2021-07-15 11:02:03 +00:00
{
ID : "client-check-uri-abs" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPlainTextClientSecret ,
2021-08-03 09:55:21 +00:00
Policy : policyTwoFactor ,
2021-07-15 11:02:03 +00:00
RedirectURIs : [ ] string {
"google.com" ,
} ,
} ,
2021-05-04 22:06:05 +00:00
} ,
2022-04-07 06:13:01 +00:00
Errors : [ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'client-check-uri-abs': option 'redirect_uris' has an invalid value: redirect uri 'google.com' must have a scheme but it's absent" ,
2022-04-07 06:13:01 +00:00
} ,
} ,
2022-04-08 07:38:38 +00:00
{
Name : "ValidSectorIdentifier" ,
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "client-valid-sector" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPlainTextClientSecret ,
2022-04-08 07:38:38 +00:00
Policy : policyTwoFactor ,
RedirectURIs : [ ] string {
"https://google.com" ,
} ,
2023-01-12 10:57:44 +00:00
SectorIdentifier : mustParseURL ( exampleDotCom ) ,
2022-04-08 07:38:38 +00:00
} ,
} ,
} ,
{
Name : "ValidSectorIdentifierWithPort" ,
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "client-valid-sector" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPlainTextClientSecret ,
2022-04-08 07:38:38 +00:00
Policy : policyTwoFactor ,
RedirectURIs : [ ] string {
"https://google.com" ,
} ,
SectorIdentifier : mustParseURL ( "example.com:2000" ) ,
} ,
} ,
} ,
2022-04-07 06:13:01 +00:00
{
Name : "InvalidSectorIdentifierInvalidURL" ,
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "client-invalid-sector" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPlainTextClientSecret ,
2022-04-07 06:13:01 +00:00
Policy : policyTwoFactor ,
RedirectURIs : [ ] string {
"https://google.com" ,
} ,
SectorIdentifier : mustParseURL ( "https://user:pass@example.com/path?query=abc#fragment" ) ,
} ,
} ,
Errors : [ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'client-invalid-sector': option 'sector_identifier' with value 'https://user:pass@example.com/path?query=abc#fragment': must be a URL with only the host component for example 'example.com' but it has a scheme with the value 'https'" ,
"identity_providers: oidc: clients: client 'client-invalid-sector': option 'sector_identifier' with value 'https://user:pass@example.com/path?query=abc#fragment': must be a URL with only the host component for example 'example.com' but it has a path with the value '/path'" ,
"identity_providers: oidc: clients: client 'client-invalid-sector': option 'sector_identifier' with value 'https://user:pass@example.com/path?query=abc#fragment': must be a URL with only the host component for example 'example.com' but it has a query with the value 'query=abc'" ,
"identity_providers: oidc: clients: client 'client-invalid-sector': option 'sector_identifier' with value 'https://user:pass@example.com/path?query=abc#fragment': must be a URL with only the host component for example 'example.com' but it has a fragment with the value 'fragment'" ,
"identity_providers: oidc: clients: client 'client-invalid-sector': option 'sector_identifier' with value 'https://user:pass@example.com/path?query=abc#fragment': must be a URL with only the host component for example 'example.com' but it has a username with the value 'user'" ,
"identity_providers: oidc: clients: client 'client-invalid-sector': option 'sector_identifier' with value 'https://user:pass@example.com/path?query=abc#fragment': must be a URL with only the host component for example 'example.com' but it has a password" ,
2022-04-07 06:13:01 +00:00
} ,
} ,
{
Name : "InvalidSectorIdentifierInvalidHost" ,
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "client-invalid-sector" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPlainTextClientSecret ,
2022-04-07 06:13:01 +00:00
Policy : policyTwoFactor ,
RedirectURIs : [ ] string {
"https://google.com" ,
} ,
SectorIdentifier : mustParseURL ( "example.com/path?query=abc#fragment" ) ,
} ,
} ,
Errors : [ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'client-invalid-sector': option 'sector_identifier' with value 'example.com/path?query=abc#fragment': must be a URL with only the host component but appears to be invalid" ,
2022-01-21 11:05:53 +00:00
} ,
2021-05-04 22:06:05 +00:00
} ,
2022-11-23 23:16:23 +00:00
{
Name : "InvalidConsentMode" ,
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "client-bad-consent-mode" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPlainTextClientSecret ,
2022-11-23 23:16:23 +00:00
Policy : policyTwoFactor ,
RedirectURIs : [ ] string {
"https://google.com" ,
} ,
ConsentMode : "cap" ,
} ,
} ,
Errors : [ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'client-bad-consent-mode': consent: option 'mode' must be one of 'auto', 'implicit', 'explicit', 'pre-configured', or 'auto' but it's configured as 'cap'" ,
2022-11-23 23:16:23 +00:00
} ,
} ,
2023-01-03 15:03:23 +00:00
{
Name : "InvalidPKCEChallengeMethod" ,
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "client-bad-pkce-mode" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPlainTextClientSecret ,
2023-01-03 15:03:23 +00:00
Policy : policyTwoFactor ,
RedirectURIs : [ ] string {
"https://google.com" ,
} ,
PKCEChallengeMethod : "abc" ,
} ,
} ,
Errors : [ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'client-bad-pkce-mode': option 'pkce_challenge_method' must be one of 'plain' or 'S256' but it's configured as 'abc'" ,
2023-01-03 15:03:23 +00:00
} ,
} ,
{
Name : "InvalidPKCEChallengeMethodLowerCaseS256" ,
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "client-bad-pkce-mode-s256" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPlainTextClientSecret ,
2023-01-03 15:03:23 +00:00
Policy : policyTwoFactor ,
RedirectURIs : [ ] string {
"https://google.com" ,
} ,
PKCEChallengeMethod : "s256" ,
} ,
} ,
Errors : [ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'client-bad-pkce-mode-s256': option 'pkce_challenge_method' must be one of 'plain' or 'S256' but it's configured as 's256'" ,
2023-01-03 15:03:23 +00:00
} ,
} ,
2021-05-04 22:06:05 +00:00
}
2022-01-21 11:05:53 +00:00
for _ , tc := range testCases {
t . Run ( tc . Name , func ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := & schema . IdentityProvidersConfiguration {
OIDC : & schema . OpenIDConnectConfiguration {
HMACSecret : "rLABDrx87et5KvRHVUgTm3pezWWd8LMN" ,
2023-05-15 00:03:19 +00:00
IssuerPrivateKey : keyRSA2048 ,
2022-01-21 11:05:53 +00:00
Clients : tc . Clients ,
} ,
}
2021-05-04 22:06:05 +00:00
2022-01-21 11:05:53 +00:00
ValidateIdentityProviders ( config , validator )
2022-04-07 06:13:01 +00:00
errs := validator . Errors ( )
require . Len ( t , errs , len ( tc . Errors ) )
for i , errStr := range tc . Errors {
t . Run ( fmt . Sprintf ( "Error%d" , i + 1 ) , func ( t * testing . T ) {
assert . EqualError ( t , errs [ i ] , errStr )
} )
}
2022-01-21 11:05:53 +00:00
} )
}
2021-05-04 22:06:05 +00:00
}
feat(oidc): add additional config options, accurate token times, and refactoring (#1991)
* This gives admins more control over their OIDC installation exposing options that had defaults before. Things like lifespans for authorize codes, access tokens, id tokens, refresh tokens, a option to enable the debug client messages, minimum parameter entropy. It also allows admins to configure the response modes.
* Additionally this records specific values about a users session indicating when they performed a specific authz factor so this is represented in the token accurately.
* Lastly we also implemented a OIDC key manager which calculates the kid for jwk's using the SHA1 digest instead of being static, or more specifically the first 7 chars. As per https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key#section-8.1.1 the kid should not exceed 8 chars. While it's allowed to exceed 8 chars, it must only be done so with a compelling reason, which we do not have.
2021-07-03 23:44:30 +00:00
func TestShouldRaiseErrorWhenOIDCClientConfiguredWithBadScopes ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := & schema . IdentityProvidersConfiguration {
OIDC : & schema . OpenIDConnectConfiguration {
HMACSecret : "rLABDrx87et5KvRHVUgTm3pezWWd8LMN" ,
2023-05-15 00:03:19 +00:00
IssuerPrivateKey : keyRSA2048 ,
feat(oidc): add additional config options, accurate token times, and refactoring (#1991)
* This gives admins more control over their OIDC installation exposing options that had defaults before. Things like lifespans for authorize codes, access tokens, id tokens, refresh tokens, a option to enable the debug client messages, minimum parameter entropy. It also allows admins to configure the response modes.
* Additionally this records specific values about a users session indicating when they performed a specific authz factor so this is represented in the token accurately.
* Lastly we also implemented a OIDC key manager which calculates the kid for jwk's using the SHA1 digest instead of being static, or more specifically the first 7 chars. As per https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key#section-8.1.1 the kid should not exceed 8 chars. While it's allowed to exceed 8 chars, it must only be done so with a compelling reason, which we do not have.
2021-07-03 23:44:30 +00:00
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "good_id" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPlainTextClientSecret ,
feat(oidc): add additional config options, accurate token times, and refactoring (#1991)
* This gives admins more control over their OIDC installation exposing options that had defaults before. Things like lifespans for authorize codes, access tokens, id tokens, refresh tokens, a option to enable the debug client messages, minimum parameter entropy. It also allows admins to configure the response modes.
* Additionally this records specific values about a users session indicating when they performed a specific authz factor so this is represented in the token accurately.
* Lastly we also implemented a OIDC key manager which calculates the kid for jwk's using the SHA1 digest instead of being static, or more specifically the first 7 chars. As per https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key#section-8.1.1 the kid should not exceed 8 chars. While it's allowed to exceed 8 chars, it must only be done so with a compelling reason, which we do not have.
2021-07-03 23:44:30 +00:00
Policy : "two_factor" ,
Scopes : [ ] string { "openid" , "bad_scope" } ,
RedirectURIs : [ ] string {
"https://google.com/callback" ,
} ,
} ,
} ,
} ,
}
ValidateIdentityProviders ( config , validator )
require . Len ( t , validator . Errors ( ) , 1 )
2023-05-15 00:32:10 +00:00
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , "identity_providers: oidc: clients: client 'good_id': option 'scopes' must only have the values 'openid', 'email', 'profile', 'groups', or 'offline_access' but the values 'bad_scope' are present" )
feat(oidc): add additional config options, accurate token times, and refactoring (#1991)
* This gives admins more control over their OIDC installation exposing options that had defaults before. Things like lifespans for authorize codes, access tokens, id tokens, refresh tokens, a option to enable the debug client messages, minimum parameter entropy. It also allows admins to configure the response modes.
* Additionally this records specific values about a users session indicating when they performed a specific authz factor so this is represented in the token accurately.
* Lastly we also implemented a OIDC key manager which calculates the kid for jwk's using the SHA1 digest instead of being static, or more specifically the first 7 chars. As per https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key#section-8.1.1 the kid should not exceed 8 chars. While it's allowed to exceed 8 chars, it must only be done so with a compelling reason, which we do not have.
2021-07-03 23:44:30 +00:00
}
func TestShouldRaiseErrorWhenOIDCClientConfiguredWithBadGrantTypes ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := & schema . IdentityProvidersConfiguration {
OIDC : & schema . OpenIDConnectConfiguration {
HMACSecret : "rLABDrx87et5KvRHVUgTm3pezWWd8LMN" ,
2023-05-15 00:03:19 +00:00
IssuerPrivateKey : keyRSA2048 ,
feat(oidc): add additional config options, accurate token times, and refactoring (#1991)
* This gives admins more control over their OIDC installation exposing options that had defaults before. Things like lifespans for authorize codes, access tokens, id tokens, refresh tokens, a option to enable the debug client messages, minimum parameter entropy. It also allows admins to configure the response modes.
* Additionally this records specific values about a users session indicating when they performed a specific authz factor so this is represented in the token accurately.
* Lastly we also implemented a OIDC key manager which calculates the kid for jwk's using the SHA1 digest instead of being static, or more specifically the first 7 chars. As per https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key#section-8.1.1 the kid should not exceed 8 chars. While it's allowed to exceed 8 chars, it must only be done so with a compelling reason, which we do not have.
2021-07-03 23:44:30 +00:00
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "good_id" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPBKDF2ClientSecret ,
feat(oidc): add additional config options, accurate token times, and refactoring (#1991)
* This gives admins more control over their OIDC installation exposing options that had defaults before. Things like lifespans for authorize codes, access tokens, id tokens, refresh tokens, a option to enable the debug client messages, minimum parameter entropy. It also allows admins to configure the response modes.
* Additionally this records specific values about a users session indicating when they performed a specific authz factor so this is represented in the token accurately.
* Lastly we also implemented a OIDC key manager which calculates the kid for jwk's using the SHA1 digest instead of being static, or more specifically the first 7 chars. As per https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key#section-8.1.1 the kid should not exceed 8 chars. While it's allowed to exceed 8 chars, it must only be done so with a compelling reason, which we do not have.
2021-07-03 23:44:30 +00:00
Policy : "two_factor" ,
GrantTypes : [ ] string { "bad_grant_type" } ,
RedirectURIs : [ ] string {
"https://google.com/callback" ,
} ,
} ,
} ,
} ,
}
ValidateIdentityProviders ( config , validator )
require . Len ( t , validator . Errors ( ) , 1 )
2023-05-15 00:32:10 +00:00
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , "identity_providers: oidc: clients: client 'good_id': option 'grant_types' must only have the values 'implicit', 'refresh_token', or 'authorization_code' but the values 'bad_grant_type' are present" )
feat(oidc): add additional config options, accurate token times, and refactoring (#1991)
* This gives admins more control over their OIDC installation exposing options that had defaults before. Things like lifespans for authorize codes, access tokens, id tokens, refresh tokens, a option to enable the debug client messages, minimum parameter entropy. It also allows admins to configure the response modes.
* Additionally this records specific values about a users session indicating when they performed a specific authz factor so this is represented in the token accurately.
* Lastly we also implemented a OIDC key manager which calculates the kid for jwk's using the SHA1 digest instead of being static, or more specifically the first 7 chars. As per https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key#section-8.1.1 the kid should not exceed 8 chars. While it's allowed to exceed 8 chars, it must only be done so with a compelling reason, which we do not have.
2021-07-03 23:44:30 +00:00
}
2022-10-02 02:07:40 +00:00
func TestShouldNotErrorOnCertificateValid ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := & schema . IdentityProvidersConfiguration {
OIDC : & schema . OpenIDConnectConfiguration {
HMACSecret : "rLABDrx87et5KvRHVUgTm3pezWWd8LMN" ,
2023-05-15 00:03:19 +00:00
IssuerCertificateChain : certRSA2048 ,
IssuerPrivateKey : keyRSA2048 ,
2022-10-02 02:07:40 +00:00
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "good_id" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPBKDF2ClientSecret ,
2022-10-02 02:07:40 +00:00
Policy : "two_factor" ,
RedirectURIs : [ ] string {
"https://google.com/callback" ,
} ,
} ,
} ,
} ,
}
ValidateIdentityProviders ( config , validator )
assert . Len ( t , validator . Warnings ( ) , 0 )
assert . Len ( t , validator . Errors ( ) , 0 )
}
func TestShouldRaiseErrorOnCertificateNotValid ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := & schema . IdentityProvidersConfiguration {
OIDC : & schema . OpenIDConnectConfiguration {
HMACSecret : "rLABDrx87et5KvRHVUgTm3pezWWd8LMN" ,
2023-05-15 00:03:19 +00:00
IssuerCertificateChain : certRSA2048 ,
IssuerPrivateKey : keyRSA4096 ,
2022-10-02 02:07:40 +00:00
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "good_id" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPBKDF2ClientSecret ,
2022-10-02 02:07:40 +00:00
Policy : "two_factor" ,
RedirectURIs : [ ] string {
"https://google.com/callback" ,
} ,
} ,
} ,
} ,
}
ValidateIdentityProviders ( config , validator )
assert . Len ( t , validator . Warnings ( ) , 0 )
require . Len ( t , validator . Errors ( ) , 1 )
2023-05-15 00:32:10 +00:00
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'" )
2021-07-10 04:56:33 +00:00
}
feat(oidc): add additional config options, accurate token times, and refactoring (#1991)
* This gives admins more control over their OIDC installation exposing options that had defaults before. Things like lifespans for authorize codes, access tokens, id tokens, refresh tokens, a option to enable the debug client messages, minimum parameter entropy. It also allows admins to configure the response modes.
* Additionally this records specific values about a users session indicating when they performed a specific authz factor so this is represented in the token accurately.
* Lastly we also implemented a OIDC key manager which calculates the kid for jwk's using the SHA1 digest instead of being static, or more specifically the first 7 chars. As per https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key#section-8.1.1 the kid should not exceed 8 chars. While it's allowed to exceed 8 chars, it must only be done so with a compelling reason, which we do not have.
2021-07-03 23:44:30 +00:00
func TestValidateIdentityProvidersShouldRaiseWarningOnSecurityIssue ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := & schema . IdentityProvidersConfiguration {
OIDC : & schema . OpenIDConnectConfiguration {
HMACSecret : "abc" ,
2023-05-15 00:03:19 +00:00
IssuerPrivateKey : keyRSA2048 ,
feat(oidc): add additional config options, accurate token times, and refactoring (#1991)
* This gives admins more control over their OIDC installation exposing options that had defaults before. Things like lifespans for authorize codes, access tokens, id tokens, refresh tokens, a option to enable the debug client messages, minimum parameter entropy. It also allows admins to configure the response modes.
* Additionally this records specific values about a users session indicating when they performed a specific authz factor so this is represented in the token accurately.
* Lastly we also implemented a OIDC key manager which calculates the kid for jwk's using the SHA1 digest instead of being static, or more specifically the first 7 chars. As per https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key#section-8.1.1 the kid should not exceed 8 chars. While it's allowed to exceed 8 chars, it must only be done so with a compelling reason, which we do not have.
2021-07-03 23:44:30 +00:00
MinimumParameterEntropy : 1 ,
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "good_id" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPBKDF2ClientSecret ,
feat(oidc): add additional config options, accurate token times, and refactoring (#1991)
* This gives admins more control over their OIDC installation exposing options that had defaults before. Things like lifespans for authorize codes, access tokens, id tokens, refresh tokens, a option to enable the debug client messages, minimum parameter entropy. It also allows admins to configure the response modes.
* Additionally this records specific values about a users session indicating when they performed a specific authz factor so this is represented in the token accurately.
* Lastly we also implemented a OIDC key manager which calculates the kid for jwk's using the SHA1 digest instead of being static, or more specifically the first 7 chars. As per https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key#section-8.1.1 the kid should not exceed 8 chars. While it's allowed to exceed 8 chars, it must only be done so with a compelling reason, which we do not have.
2021-07-03 23:44:30 +00:00
Policy : "two_factor" ,
RedirectURIs : [ ] string {
"https://google.com/callback" ,
} ,
} ,
} ,
} ,
}
ValidateIdentityProviders ( config , validator )
assert . Len ( t , validator . Errors ( ) , 0 )
require . Len ( t , validator . Warnings ( ) , 1 )
2021-08-03 09:55:21 +00:00
assert . EqualError ( t , validator . Warnings ( ) [ 0 ] , "openid connect provider: SECURITY ISSUE - minimum parameter entropy is configured to an unsafe value, it should be above 8 but it's configured to 1" )
feat(oidc): add additional config options, accurate token times, and refactoring (#1991)
* This gives admins more control over their OIDC installation exposing options that had defaults before. Things like lifespans for authorize codes, access tokens, id tokens, refresh tokens, a option to enable the debug client messages, minimum parameter entropy. It also allows admins to configure the response modes.
* Additionally this records specific values about a users session indicating when they performed a specific authz factor so this is represented in the token accurately.
* Lastly we also implemented a OIDC key manager which calculates the kid for jwk's using the SHA1 digest instead of being static, or more specifically the first 7 chars. As per https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key#section-8.1.1 the kid should not exceed 8 chars. While it's allowed to exceed 8 chars, it must only be done so with a compelling reason, which we do not have.
2021-07-03 23:44:30 +00:00
}
2021-07-15 11:02:03 +00:00
func TestValidateIdentityProvidersShouldRaiseErrorsOnInvalidClientTypes ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := & schema . IdentityProvidersConfiguration {
OIDC : & schema . OpenIDConnectConfiguration {
HMACSecret : "hmac1" ,
2023-05-15 00:03:19 +00:00
IssuerPrivateKey : keyRSA2048 ,
2021-07-15 11:02:03 +00:00
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "client-with-invalid-secret" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPlainTextClientSecret ,
2021-07-15 11:02:03 +00:00
Public : true ,
Policy : "two_factor" ,
RedirectURIs : [ ] string {
"https://localhost" ,
} ,
} ,
{
ID : "client-with-bad-redirect-uri" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPBKDF2ClientSecret ,
2021-07-15 11:02:03 +00:00
Public : false ,
Policy : "two_factor" ,
RedirectURIs : [ ] string {
oauth2InstalledApp ,
} ,
} ,
} ,
} ,
}
ValidateIdentityProviders ( config , validator )
require . Len ( t , validator . Errors ( ) , 2 )
assert . Len ( t , validator . Warnings ( ) , 0 )
2023-05-15 00:32:10 +00:00
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , "identity_providers: oidc: clients: client 'client-with-invalid-secret': option 'secret' is required to be empty when option 'public' is true" )
assert . EqualError ( t , validator . Errors ( ) [ 1 ] , "identity_providers: oidc: clients: client 'client-with-bad-redirect-uri': option 'redirect_uris' has the redirect uri 'urn:ietf:wg:oauth:2.0:oob' when option 'public' is false but this is invalid as this uri is not valid for the openid connect confidential client type" )
2021-07-15 11:02:03 +00:00
}
2023-01-03 15:03:23 +00:00
func TestValidateIdentityProvidersShouldNotRaiseErrorsOnValidClientOptions ( t * testing . T ) {
2021-07-15 11:02:03 +00:00
validator := schema . NewStructValidator ( )
config := & schema . IdentityProvidersConfiguration {
OIDC : & schema . OpenIDConnectConfiguration {
HMACSecret : "hmac1" ,
2023-05-15 00:03:19 +00:00
IssuerPrivateKey : keyRSA2048 ,
2021-07-15 11:02:03 +00:00
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "installed-app-client" ,
Public : true ,
Policy : "two_factor" ,
RedirectURIs : [ ] string {
oauth2InstalledApp ,
} ,
} ,
{
ID : "client-with-https-scheme" ,
Public : true ,
Policy : "two_factor" ,
RedirectURIs : [ ] string {
"https://localhost:9000" ,
} ,
} ,
{
ID : "client-with-loopback" ,
Public : true ,
Policy : "two_factor" ,
RedirectURIs : [ ] string {
"http://127.0.0.1" ,
} ,
} ,
2023-01-03 15:03:23 +00:00
{
ID : "client-with-pkce-mode-plain" ,
Public : true ,
Policy : "two_factor" ,
RedirectURIs : [ ] string {
"https://pkce.com" ,
} ,
PKCEChallengeMethod : "plain" ,
} ,
{
ID : "client-with-pkce-mode-S256" ,
Public : true ,
Policy : "two_factor" ,
RedirectURIs : [ ] string {
"https://pkce.com" ,
} ,
PKCEChallengeMethod : "S256" ,
} ,
2021-07-15 11:02:03 +00:00
} ,
} ,
}
ValidateIdentityProviders ( config , validator )
assert . Len ( t , validator . Errors ( ) , 0 )
assert . Len ( t , validator . Warnings ( ) , 0 )
}
2023-03-09 07:26:52 +00:00
func TestValidateIdentityProvidersShouldRaiseWarningOnPlainTextClients ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := & schema . IdentityProvidersConfiguration {
OIDC : & schema . OpenIDConnectConfiguration {
HMACSecret : "hmac1" ,
2023-05-15 00:03:19 +00:00
IssuerPrivateKey : keyRSA2048 ,
2023-03-09 07:26:52 +00:00
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "client-with-invalid-secret_standard" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPlainTextClientSecret ,
2023-03-09 07:26:52 +00:00
Policy : "two_factor" ,
RedirectURIs : [ ] string {
"https://localhost" ,
} ,
} ,
} ,
} ,
}
ValidateIdentityProviders ( config , validator )
assert . Len ( t , validator . Errors ( ) , 0 )
require . Len ( t , validator . Warnings ( ) , 1 )
2023-05-15 00:32:10 +00:00
assert . EqualError ( t , validator . Warnings ( ) [ 0 ] , "identity_providers: oidc: clients: client 'client-with-invalid-secret_standard': option 'secret' is plaintext but for clients not using the 'token_endpoint_auth_method' of 'client_secret_jwt' it should be a hashed value as plaintext values are deprecated with the exception of 'client_secret_jwt' and will be removed when oidc becomes stable" )
2023-03-09 07:26:52 +00:00
}
2022-01-21 11:05:53 +00:00
// All valid schemes are supported as defined in https://datatracker.ietf.org/doc/html/rfc8252#section-7.1
func TestValidateOIDCClientRedirectURIsSupportingPrivateUseURISchemes ( t * testing . T ) {
2023-04-13 10:58:18 +00:00
have := & schema . OpenIDConnectConfiguration {
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "owncloud" ,
RedirectURIs : [ ] string {
"https://www.mywebsite.com" ,
"http://www.mywebsite.com" ,
"oc://ios.owncloud.com" ,
// example given in the RFC https://datatracker.ietf.org/doc/html/rfc8252#section-7.1
"com.example.app:/oauth2redirect/example-provider" ,
oauth2InstalledApp ,
} ,
} ,
2022-01-21 11:05:53 +00:00
} ,
}
t . Run ( "public" , func ( t * testing . T ) {
validator := schema . NewStructValidator ( )
2023-04-13 10:58:18 +00:00
have . Clients [ 0 ] . Public = true
validateOIDCClientRedirectURIs ( 0 , have , validator , nil )
2022-01-21 11:05:53 +00:00
assert . Len ( t , validator . Warnings ( ) , 0 )
assert . Len ( t , validator . Errors ( ) , 0 )
} )
t . Run ( "not public" , func ( t * testing . T ) {
validator := schema . NewStructValidator ( )
2023-04-13 10:58:18 +00:00
have . Clients [ 0 ] . Public = false
validateOIDCClientRedirectURIs ( 0 , have , validator , nil )
2022-01-21 11:05:53 +00:00
assert . Len ( t , validator . Warnings ( ) , 0 )
2022-11-21 00:52:27 +00:00
assert . Len ( t , validator . Errors ( ) , 1 )
2022-01-21 11:05:53 +00:00
assert . ElementsMatch ( t , validator . Errors ( ) , [ ] error {
2023-05-15 00:32:10 +00:00
errors . New ( "identity_providers: oidc: clients: client 'owncloud': option 'redirect_uris' has the redirect uri 'urn:ietf:wg:oauth:2.0:oob' when option 'public' is false but this is invalid as this uri is not valid for the openid connect confidential client type" ) ,
2022-01-21 11:05:53 +00:00
} )
} )
}
2022-10-02 02:07:40 +00:00
2023-04-13 10:58:18 +00:00
func TestValidateOIDCClients ( t * testing . T ) {
type tcv struct {
Scopes [ ] string
ResponseTypes [ ] string
ResponseModes [ ] string
GrantTypes [ ] string
}
testCasses := [ ] struct {
name string
setup func ( have * schema . OpenIDConnectConfiguration )
validate func ( t * testing . T , have * schema . OpenIDConnectConfiguration )
have tcv
expected tcv
serrs [ ] string // Soft errors which will be warnings before GA.
errs [ ] string
} {
{
"ShouldSetDefaultResponseTypeAndResponseModes" ,
nil ,
nil ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
nil ,
} ,
{
"ShouldIncludeMinimalScope" ,
nil ,
nil ,
tcv {
[ ] string { oidc . ScopeEmail } ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
nil ,
} ,
{
"ShouldSetDefaultResponseModesFlowAuthorizeCode" ,
nil ,
nil ,
tcv {
nil ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
nil ,
} ,
{
"ShouldSetDefaultResponseModesFlowImplicit" ,
nil ,
nil ,
tcv {
nil ,
[ ] string { oidc . ResponseTypeImplicitFlowBoth } ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeImplicitFlowBoth } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeFragment } ,
[ ] string { oidc . GrantTypeImplicit } ,
} ,
nil ,
nil ,
} ,
{
"ShouldSetDefaultResponseModesFlowHybrid" ,
nil ,
nil ,
tcv {
nil ,
[ ] string { oidc . ResponseTypeHybridFlowBoth } ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeHybridFlowBoth } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeFragment } ,
[ ] string { oidc . GrantTypeAuthorizationCode , oidc . GrantTypeImplicit } ,
} ,
nil ,
nil ,
} ,
{
"ShouldSetDefaultResponseModesFlowMixedAuthorizeCodeHybrid" ,
nil ,
nil ,
tcv {
nil ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow , oidc . ResponseTypeHybridFlowBoth } ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow , oidc . ResponseTypeHybridFlowBoth } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery , oidc . ResponseModeFragment } ,
[ ] string { oidc . GrantTypeAuthorizationCode , oidc . GrantTypeImplicit } ,
} ,
nil ,
nil ,
} ,
{
"ShouldSetDefaultResponseModesFlowMixedAuthorizeCodeImplicit" ,
nil ,
nil ,
tcv {
nil ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow , oidc . ResponseTypeImplicitFlowBoth } ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow , oidc . ResponseTypeImplicitFlowBoth } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery , oidc . ResponseModeFragment } ,
[ ] string { oidc . GrantTypeAuthorizationCode , oidc . GrantTypeImplicit } ,
} ,
nil ,
nil ,
} ,
{
"ShouldSetDefaultResponseModesFlowMixedAll" ,
nil ,
nil ,
tcv {
nil ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow , oidc . ResponseTypeImplicitFlowBoth , oidc . ResponseTypeHybridFlowBoth } ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow , oidc . ResponseTypeImplicitFlowBoth , oidc . ResponseTypeHybridFlowBoth } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery , oidc . ResponseModeFragment } ,
[ ] string { oidc . GrantTypeAuthorizationCode , oidc . GrantTypeImplicit } ,
} ,
nil ,
nil ,
} ,
{
"ShouldNotOverrideValues" ,
nil ,
nil ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow , oidc . ResponseTypeImplicitFlowBoth , oidc . ResponseTypeHybridFlowBoth } ,
[ ] string { oidc . ResponseModeFormPost } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow , oidc . ResponseTypeImplicitFlowBoth , oidc . ResponseTypeHybridFlowBoth } ,
[ ] string { oidc . ResponseModeFormPost } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
nil ,
} ,
{
"ShouldRaiseErrorOnDuplicateScopes" ,
nil ,
nil ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeProfile , oidc . ScopeOpenID } ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeProfile , oidc . ScopeOpenID } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'scopes' must have unique values but the values 'openid' are duplicated" ,
2023-04-13 10:58:18 +00:00
} ,
nil ,
} ,
{
"ShouldRaiseErrorOnInvalidScopes" ,
nil ,
nil ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeProfile , "group" } ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeProfile , "group" } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'scopes' must only have the values 'openid', 'email', 'profile', 'groups', or 'offline_access' but the values 'group' are present" ,
2023-04-13 10:58:18 +00:00
} ,
} ,
{
"ShouldRaiseErrorOnMissingAuthorizationCodeFlowResponseTypeWithRefreshTokenValues" ,
nil ,
nil ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeProfile , oidc . ScopeOfflineAccess } ,
[ ] string { oidc . ResponseTypeImplicitFlowBoth } ,
nil ,
[ ] string { oidc . GrantTypeImplicit , oidc . GrantTypeRefreshToken } ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeProfile , oidc . ScopeOfflineAccess } ,
[ ] string { oidc . ResponseTypeImplicitFlowBoth } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeFragment } ,
[ ] string { oidc . GrantTypeImplicit , oidc . GrantTypeRefreshToken } ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'scopes' should only have the values 'offline_access' or 'offline' if the client is also configured with a 'response_type' such as 'code', 'code id_token', 'code token', or 'code id_token token' which respond with authorization codes" ,
"identity_providers: oidc: clients: client 'test': option 'grant_types' should only have the values 'refresh_token' if the client is also configured with a 'response_type' such as 'code', 'code id_token', 'code token', or 'code id_token token' which respond with authorization codes" ,
2023-04-13 10:58:18 +00:00
} ,
nil ,
} ,
{
"ShouldRaiseErrorOnDuplicateResponseTypes" ,
nil ,
nil ,
tcv {
nil ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow , oidc . ResponseTypeImplicitFlowBoth , oidc . ResponseTypeAuthorizationCodeFlow } ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow , oidc . ResponseTypeImplicitFlowBoth , oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery , oidc . ResponseModeFragment } ,
[ ] string { oidc . GrantTypeAuthorizationCode , oidc . GrantTypeImplicit } ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'response_types' must have unique values but the values 'code' are duplicated" ,
2023-04-13 10:58:18 +00:00
} ,
nil ,
} ,
{
"ShouldRaiseErrorOnInvalidResponseTypesOrder" ,
nil ,
nil ,
tcv {
nil ,
[ ] string { oidc . ResponseTypeImplicitFlowBoth , "token id_token" } ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeImplicitFlowBoth , "token id_token" } ,
[ ] string { "form_post" , "fragment" } ,
[ ] string { "implicit" } ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'response_types' must only have the values 'code', 'id_token', 'token', 'id_token token', 'code id_token', 'code token', or 'code id_token token' but the values 'token id_token' are present" ,
2023-04-13 10:58:18 +00:00
} ,
nil ,
} ,
{
"ShouldRaiseErrorOnInvalidResponseTypes" ,
nil ,
nil ,
tcv {
nil ,
[ ] string { "not_valid" } ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { "not_valid" } ,
[ ] string { oidc . ResponseModeFormPost } ,
nil ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'response_types' must only have the values 'code', 'id_token', 'token', 'id_token token', 'code id_token', 'code token', or 'code id_token token' but the values 'not_valid' are present" ,
2023-04-13 10:58:18 +00:00
} ,
nil ,
} ,
{
"ShouldRaiseErrorOnInvalidResponseModes" ,
nil ,
nil ,
tcv {
nil ,
nil ,
[ ] string { "not_valid" } ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { "not_valid" } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'response_modes' must only have the values 'form_post', 'query', or 'fragment' but the values 'not_valid' are present" ,
2023-04-13 10:58:18 +00:00
} ,
} ,
{
"ShouldRaiseErrorOnDuplicateResponseModes" ,
nil ,
nil ,
tcv {
nil ,
nil ,
[ ] string { oidc . ResponseModeQuery , oidc . ResponseModeQuery } ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeQuery , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'response_modes' must have unique values but the values 'query' are duplicated" ,
2023-04-13 10:58:18 +00:00
} ,
nil ,
} ,
{
"ShouldRaiseErrorOnInvalidGrantTypes" ,
nil ,
nil ,
tcv {
nil ,
nil ,
nil ,
[ ] string { "invalid" } ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { "invalid" } ,
} ,
nil ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'grant_types' must only have the values 'implicit', 'refresh_token', or 'authorization_code' but the values 'invalid' are present" ,
2023-04-13 10:58:18 +00:00
} ,
} ,
{
"ShouldRaiseErrorOnDuplicateGrantTypes" ,
nil ,
nil ,
tcv {
nil ,
nil ,
nil ,
[ ] string { oidc . GrantTypeAuthorizationCode , oidc . GrantTypeAuthorizationCode } ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode , oidc . GrantTypeAuthorizationCode } ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'grant_types' must have unique values but the values 'authorization_code' are duplicated" ,
2023-04-13 10:58:18 +00:00
} ,
nil ,
} ,
{
"ShouldRaiseErrorOnGrantTypeRefreshTokenWithoutScopeOfflineAccess" ,
nil ,
nil ,
tcv {
nil ,
nil ,
nil ,
[ ] string { oidc . GrantTypeAuthorizationCode , oidc . GrantTypeRefreshToken } ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode , oidc . GrantTypeRefreshToken } ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'grant_types' should only have the 'refresh_token' value if the client is also configured with the 'offline_access' scope" ,
2023-04-13 10:58:18 +00:00
} ,
nil ,
} ,
{
"ShouldRaiseErrorOnGrantTypeAuthorizationCodeWithoutAuthorizationCodeOrHybridFlow" ,
nil ,
nil ,
tcv {
nil ,
[ ] string { oidc . ResponseTypeImplicitFlowBoth } ,
nil ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeImplicitFlowBoth } ,
[ ] string { "form_post" , "fragment" } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'grant_types' should only have grant type values which are valid with the configured 'response_types' for the client but 'authorization_code' expects a response type for either the authorization code or hybrid flow such as 'code', 'code id_token', 'code token', or 'code id_token token' but the response types are 'id_token token'" ,
2023-04-13 10:58:18 +00:00
} ,
nil ,
} ,
{
"ShouldRaiseErrorOnGrantTypeImplicitWithoutImplicitOrHybridFlow" ,
nil ,
nil ,
tcv {
nil ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
nil ,
[ ] string { oidc . GrantTypeImplicit } ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeImplicit } ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'grant_types' should only have grant type values which are valid with the configured 'response_types' for the client but 'implicit' expects a response type for either the implicit or hybrid flow such as 'id_token', 'token', 'id_token token', 'code id_token', 'code token', or 'code id_token token' but the response types are 'code'" ,
2023-04-13 10:58:18 +00:00
} ,
nil ,
} ,
{
"ShouldValidateCorrectRedirectURIsConfidentialClientType" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . RedirectURIs = [ ] string {
"https://google.com" ,
}
} ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , [ ] string { "https://google.com" } , have . Clients [ 0 ] . RedirectURIs )
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
nil ,
} ,
{
"ShouldValidateCorrectRedirectURIsPublicClientType" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . Public = true
have . Clients [ 0 ] . Secret = nil
have . Clients [ 0 ] . RedirectURIs = [ ] string {
oauth2InstalledApp ,
}
} ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , [ ] string { oauth2InstalledApp } , have . Clients [ 0 ] . RedirectURIs )
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
nil ,
} ,
{
"ShouldRaiseErrorOnInvalidRedirectURIsPublicOnly" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . RedirectURIs = [ ] string {
"urn:ietf:wg:oauth:2.0:oob" ,
}
} ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , [ ] string { oauth2InstalledApp } , have . Clients [ 0 ] . RedirectURIs )
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'redirect_uris' has the redirect uri 'urn:ietf:wg:oauth:2.0:oob' when option 'public' is false but this is invalid as this uri is not valid for the openid connect confidential client type" ,
2023-04-13 10:58:18 +00:00
} ,
} ,
{
"ShouldRaiseErrorOnInvalidRedirectURIsMalformedURI" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . RedirectURIs = [ ] string {
"http://abc@%two" ,
}
} ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , [ ] string { "http://abc@%two" } , have . Clients [ 0 ] . RedirectURIs )
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'redirect_uris' has an invalid value: redirect uri 'http://abc@%two' could not be parsed: parse \"http://abc@%two\": invalid URL escape \"%tw\"" ,
2023-04-13 10:58:18 +00:00
} ,
} ,
{
"ShouldRaiseErrorOnInvalidRedirectURIsNotAbsolute" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . RedirectURIs = [ ] string {
"google.com" ,
}
} ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , [ ] string { "google.com" } , have . Clients [ 0 ] . RedirectURIs )
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'redirect_uris' has an invalid value: redirect uri 'google.com' must have a scheme but it's absent" ,
2023-04-13 10:58:18 +00:00
} ,
} ,
{
"ShouldRaiseErrorOnDuplicateRedirectURI" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . RedirectURIs = [ ] string {
"https://google.com" ,
"https://google.com" ,
}
} ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , [ ] string { "https://google.com" , "https://google.com" } , have . Clients [ 0 ] . RedirectURIs )
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'redirect_uris' must have unique values but the values 'https://google.com' are duplicated" ,
2023-04-13 10:58:18 +00:00
} ,
nil ,
} ,
{
"ShouldNotSetDefaultTokenEndpointClientAuthMethodConfidentialClientType" ,
nil ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , "" , have . Clients [ 0 ] . TokenEndpointAuthMethod )
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
nil ,
} ,
{
"ShouldNotOverrideValidClientAuthMethod" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . TokenEndpointAuthMethod = oidc . ClientAuthMethodClientSecretPost
} ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , oidc . ClientAuthMethodClientSecretPost , have . Clients [ 0 ] . TokenEndpointAuthMethod )
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
nil ,
} ,
{
"ShouldRaiseErrorOnInvalidClientAuthMethod" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . TokenEndpointAuthMethod = "client_credentials"
} ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , "client_credentials" , have . Clients [ 0 ] . TokenEndpointAuthMethod )
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'token_endpoint_auth_method' must be one of 'none', 'client_secret_post', 'client_secret_basic', 'private_key_jwt', or 'client_secret_jwt' but it's configured as 'client_credentials'" ,
2023-04-13 10:58:18 +00:00
} ,
} ,
{
"ShouldRaiseErrorOnInvalidClientAuthMethodForPublicClientType" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . TokenEndpointAuthMethod = oidc . ClientAuthMethodClientSecretBasic
have . Clients [ 0 ] . Public = true
have . Clients [ 0 ] . Secret = nil
} ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , oidc . ClientAuthMethodClientSecretBasic , have . Clients [ 0 ] . TokenEndpointAuthMethod )
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'token_endpoint_auth_method' must be 'none' when configured as the public client type but it's configured as 'client_secret_basic'" ,
2023-04-13 10:58:18 +00:00
} ,
} ,
{
"ShouldRaiseErrorOnInvalidClientAuthMethodForConfidentialClientTypeAuthorizationCodeFlow" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . TokenEndpointAuthMethod = oidc . ClientAuthMethodNone
} ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , oidc . ClientAuthMethodNone , have . Clients [ 0 ] . TokenEndpointAuthMethod )
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'token_endpoint_auth_method' must be one of 'client_secret_post', 'client_secret_basic', or 'private_key_jwt' when configured as the confidential client type unless it only includes implicit flow response types such as 'id_token', 'token', and 'id_token token' but it's configured as 'none'" ,
2023-04-13 10:58:18 +00:00
} ,
} ,
{
"ShouldRaiseErrorOnInvalidClientAuthMethodForConfidentialClientTypeHybridFlow" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . TokenEndpointAuthMethod = oidc . ClientAuthMethodNone
} ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , oidc . ClientAuthMethodNone , have . Clients [ 0 ] . TokenEndpointAuthMethod )
} ,
tcv {
nil ,
[ ] string { oidc . ResponseTypeHybridFlowToken } ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeHybridFlowToken } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeFragment } ,
[ ] string { oidc . GrantTypeAuthorizationCode , oidc . GrantTypeImplicit } ,
} ,
nil ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'token_endpoint_auth_method' must be one of 'client_secret_post', 'client_secret_basic', or 'private_key_jwt' when configured as the confidential client type unless it only includes implicit flow response types such as 'id_token', 'token', and 'id_token token' but it's configured as 'none'" ,
2023-04-13 10:58:18 +00:00
} ,
} ,
{
"ShouldSetDefaultUserInfoAlg" ,
nil ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
2023-05-15 00:03:19 +00:00
assert . Equal ( t , oidc . SigningAlgNone , have . Clients [ 0 ] . UserinfoSigningAlg )
2023-04-13 10:58:18 +00:00
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
nil ,
} ,
{
"ShouldNotOverrideUserInfoAlg" ,
func ( have * schema . OpenIDConnectConfiguration ) {
2023-05-15 00:03:19 +00:00
have . Clients [ 0 ] . UserinfoSigningAlg = oidc . SigningAlgRSAUsingSHA256
2023-04-13 10:58:18 +00:00
} ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
2023-05-15 00:03:19 +00:00
assert . Equal ( t , oidc . SigningAlgRSAUsingSHA256 , have . Clients [ 0 ] . UserinfoSigningAlg )
2023-04-13 10:58:18 +00:00
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
nil ,
} ,
{
2023-05-15 00:32:10 +00:00
"ShouldRaiseErrorOnInvalidUserInfoSigningAlg" ,
2023-04-13 10:58:18 +00:00
func ( have * schema . OpenIDConnectConfiguration ) {
2023-05-15 00:32:10 +00:00
have . Clients [ 0 ] . UserinfoSigningAlg = rs256
2023-04-13 10:58:18 +00:00
} ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
2023-05-15 00:32:10 +00:00
assert . Equal ( t , rs256 , have . Clients [ 0 ] . UserinfoSigningAlg )
2023-04-13 10:58:18 +00:00
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'userinfo_signing_alg' must be one of 'RS256' or 'none' but it's configured as 'rs256'" ,
} ,
} ,
{
"ShouldRaiseErrorOnInvalidIDTokenSigningAlg" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . IDTokenSigningAlg = rs256
} ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , rs256 , have . Clients [ 0 ] . IDTokenSigningAlg )
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
[ ] string {
"identity_providers: oidc: clients: client 'test': option 'id_token_signing_alg' must be one of 'RS256' but it's configured as 'rs256'" ,
2023-04-13 10:58:18 +00:00
} ,
} ,
{
"ShouldSetDefaultConsentMode" ,
nil ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , "explicit" , have . Clients [ 0 ] . ConsentMode )
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
nil ,
} ,
{
"ShouldSetDefaultConsentModeAuto" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . ConsentMode = auto
} ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , "explicit" , have . Clients [ 0 ] . ConsentMode )
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
nil ,
} ,
{
"ShouldSetDefaultConsentModePreConfigured" ,
func ( have * schema . OpenIDConnectConfiguration ) {
d := time . Minute
have . Clients [ 0 ] . ConsentMode = ""
have . Clients [ 0 ] . ConsentPreConfiguredDuration = & d
} ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , "pre-configured" , have . Clients [ 0 ] . ConsentMode )
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
nil ,
} ,
{
"ShouldSetDefaultConsentModeAutoPreConfigured" ,
func ( have * schema . OpenIDConnectConfiguration ) {
d := time . Minute
have . Clients [ 0 ] . ConsentMode = auto
have . Clients [ 0 ] . ConsentPreConfiguredDuration = & d
} ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , "pre-configured" , have . Clients [ 0 ] . ConsentMode )
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
nil ,
} ,
{
"ShouldNotOverrideConsentMode" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . ConsentMode = "implicit"
} ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , "implicit" , have . Clients [ 0 ] . ConsentMode )
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
nil ,
} ,
{
"ShouldSentConsentPreConfiguredDefaultDuration" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . ConsentMode = "pre-configured"
} ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , "pre-configured" , have . Clients [ 0 ] . ConsentMode )
assert . Equal ( t , schema . DefaultOpenIDConnectClientConfiguration . ConsentPreConfiguredDuration , have . Clients [ 0 ] . ConsentPreConfiguredDuration )
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
nil ,
} ,
2023-05-15 00:32:10 +00:00
{
"ShouldRaiseErrorOnTokenEndpointClientAuthMethodPrivateKeyJWTMustSetAlg" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . TokenEndpointAuthMethod = oidc . ClientAuthMethodPrivateKeyJWT
have . Clients [ 0 ] . Secret = tOpenIDConnectPBKDF2ClientSecret
} ,
nil ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
[ ] string {
"identity_providers: oidc: clients: client 'test': option 'token_endpoint_auth_signing_alg' is required when option 'token_endpoint_auth_method' is configured to 'private_key_jwt'" ,
"identity_providers: oidc: clients: client 'test': option 'public_keys' is required with 'token_endpoint_auth_method' set to 'private_key_jwt'" ,
} ,
} ,
{
"ShouldRaiseErrorOnTokenEndpointClientAuthMethodPrivateKeyJWTMustSetAlg" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . TokenEndpointAuthMethod = oidc . ClientAuthMethodPrivateKeyJWT
have . Clients [ 0 ] . TokenEndpointAuthSigningAlg = "nope"
have . Clients [ 0 ] . Secret = tOpenIDConnectPBKDF2ClientSecret
} ,
nil ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
[ ] string {
"identity_providers: oidc: clients: client 'test': option 'token_endpoint_auth_signing_alg' must be one of 'RS256', 'PS256', 'ES256', 'RS384', 'PS384', 'ES384', 'RS512', 'PS512', or 'ES512' when option 'token_endpoint_auth_method' is configured to 'private_key_jwt'" ,
"identity_providers: oidc: clients: client 'test': option 'public_keys' is required with 'token_endpoint_auth_method' set to 'private_key_jwt'" ,
} ,
} ,
{
"ShouldRaiseErrorOnTokenEndpointClientAuthMethodPrivateKeyJWTMustSetKnownAlg" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . TokenEndpointAuthMethod = oidc . ClientAuthMethodPrivateKeyJWT
have . Clients [ 0 ] . TokenEndpointAuthSigningAlg = oidc . SigningAlgECDSAUsingP384AndSHA384
have . Clients [ 0 ] . Secret = tOpenIDConnectPBKDF2ClientSecret
have . Clients [ 0 ] . PublicKeys . Values = [ ] schema . JWK {
{
KeyID : "test" ,
Key : keyRSA2048 . Public ( ) ,
Algorithm : oidc . SigningAlgRSAUsingSHA256 ,
} ,
}
} ,
nil ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
[ ] string {
"identity_providers: oidc: clients: client 'test': option 'token_endpoint_auth_signing_alg' must be one of registered public key algorithm values 'RS256' when option 'token_endpoint_auth_method' is configured to 'private_key_jwt'" ,
} ,
} ,
{
"ShouldRaiseErrorOnTokenEndpointClientAuthMethodPrivateKeyJWTMustSetKnownAlg" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . TokenEndpointAuthMethod = oidc . ClientAuthMethodPrivateKeyJWT
have . Clients [ 0 ] . TokenEndpointAuthSigningAlg = oidc . SigningAlgECDSAUsingP384AndSHA384
have . Clients [ 0 ] . Secret = tOpenIDConnectPBKDF2ClientSecret
} ,
nil ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
[ ] string {
"identity_providers: oidc: clients: client 'test': option 'public_keys' is required with 'token_endpoint_auth_method' set to 'private_key_jwt'" ,
} ,
} ,
2023-05-15 00:03:19 +00:00
{
"ShouldRaiseErrorOnIncorrectlyConfiguredTokenEndpointClientAuthMethodClientSecretJWT" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . TokenEndpointAuthMethod = oidc . ClientAuthMethodClientSecretJWT
have . Clients [ 0 ] . Secret = tOpenIDConnectPBKDF2ClientSecret
} ,
nil ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'secret' must be plaintext with option 'token_endpoint_auth_method' with a value of 'client_secret_jwt'" ,
2023-05-15 00:03:19 +00:00
} ,
} ,
{
"ShouldNotRaiseWarningOrErrorOnCorrectlyConfiguredTokenEndpointClientAuthMethodClientSecretJWT" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . TokenEndpointAuthMethod = oidc . ClientAuthMethodClientSecretJWT
have . Clients [ 0 ] . Secret = tOpenIDConnectPlainTextClientSecret
} ,
nil ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
nil ,
} ,
2023-05-14 23:51:59 +00:00
{
"ShouldRaiseErrorOnIncorrectlyConfiguredTokenEndpointClientAuthMethodClientSecretJWT" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . TokenEndpointAuthMethod = oidc . ClientAuthMethodClientSecretJWT
have . Clients [ 0 ] . Secret = MustDecodeSecret ( "$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng" )
} ,
nil ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'secret' must be plaintext with option 'token_endpoint_auth_method' with a value of 'client_secret_jwt'" ,
2023-05-14 23:51:59 +00:00
} ,
} ,
{
"ShouldNotRaiseWarningOrErrorOnCorrectlyConfiguredTokenEndpointClientAuthMethodClientSecretJWT" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . TokenEndpointAuthMethod = oidc . ClientAuthMethodClientSecretJWT
have . Clients [ 0 ] . Secret = MustDecodeSecret ( "$plaintext$abc123" )
} ,
nil ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
nil ,
} ,
{
"ShouldSetDefaultTokenEndpointAuthSigAlg" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . TokenEndpointAuthMethod = oidc . ClientAuthMethodClientSecretJWT
2023-05-15 00:03:19 +00:00
have . Clients [ 0 ] . Secret = tOpenIDConnectPlainTextClientSecret
2023-05-14 23:51:59 +00:00
} ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , oidc . SigningAlgHMACUsingSHA256 , have . Clients [ 0 ] . TokenEndpointAuthSigningAlg )
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
nil ,
} ,
{
"ShouldRaiseErrorOnInvalidPublicTokenAuthAlg" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . TokenEndpointAuthMethod = oidc . ClientAuthMethodClientSecretJWT
have . Clients [ 0 ] . TokenEndpointAuthSigningAlg = oidc . SigningAlgHMACUsingSHA256
have . Clients [ 0 ] . Secret = nil
have . Clients [ 0 ] . Public = true
} ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , oidc . SigningAlgHMACUsingSHA256 , have . Clients [ 0 ] . TokenEndpointAuthSigningAlg )
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'token_endpoint_auth_method' must be 'none' when configured as the public client type but it's configured as 'client_secret_jwt'" ,
2023-05-14 23:51:59 +00:00
} ,
} ,
{
"ShouldRaiseErrorOnInvalidTokenAuthAlgClientTypeConfidential" ,
func ( have * schema . OpenIDConnectConfiguration ) {
have . Clients [ 0 ] . TokenEndpointAuthMethod = oidc . ClientAuthMethodClientSecretJWT
2023-05-15 00:03:19 +00:00
have . Clients [ 0 ] . TokenEndpointAuthSigningAlg = oidc . EndpointToken
have . Clients [ 0 ] . Secret = tOpenIDConnectPlainTextClientSecret
2023-05-14 23:51:59 +00:00
} ,
func ( t * testing . T , have * schema . OpenIDConnectConfiguration ) {
2023-05-15 00:03:19 +00:00
assert . Equal ( t , oidc . EndpointToken , have . Clients [ 0 ] . TokenEndpointAuthSigningAlg )
2023-05-14 23:51:59 +00:00
} ,
tcv {
nil ,
nil ,
nil ,
nil ,
} ,
tcv {
[ ] string { oidc . ScopeOpenID , oidc . ScopeGroups , oidc . ScopeProfile , oidc . ScopeEmail } ,
[ ] string { oidc . ResponseTypeAuthorizationCodeFlow } ,
[ ] string { oidc . ResponseModeFormPost , oidc . ResponseModeQuery } ,
[ ] string { oidc . GrantTypeAuthorizationCode } ,
} ,
nil ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'token_endpoint_auth_signing_alg' must be one of 'HS256', 'HS384', or 'HS512' when option 'token_endpoint_auth_method' is configured to 'client_secret_jwt'" ,
2023-05-14 23:51:59 +00:00
} ,
} ,
2023-04-13 10:58:18 +00:00
}
errDeprecatedFunc := func ( ) { }
for _ , tc := range testCasses {
t . Run ( tc . name , func ( t * testing . T ) {
have := & schema . OpenIDConnectConfiguration {
2023-05-15 00:03:19 +00:00
Discovery : schema . OpenIDConnectDiscovery {
2023-05-15 00:32:10 +00:00
ResponseObjectSigningAlgs : [ ] string { oidc . SigningAlgRSAUsingSHA256 } ,
2023-05-15 00:03:19 +00:00
} ,
2023-04-13 10:58:18 +00:00
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "test" ,
2023-05-15 00:03:19 +00:00
Secret : tOpenIDConnectPBKDF2ClientSecret ,
2023-04-13 10:58:18 +00:00
Scopes : tc . have . Scopes ,
ResponseModes : tc . have . ResponseModes ,
ResponseTypes : tc . have . ResponseTypes ,
GrantTypes : tc . have . GrantTypes ,
} ,
} ,
}
if tc . setup != nil {
tc . setup ( have )
}
val := schema . NewStructValidator ( )
validateOIDCClient ( 0 , have , val , errDeprecatedFunc )
t . Run ( "General" , func ( t * testing . T ) {
assert . Equal ( t , tc . expected . Scopes , have . Clients [ 0 ] . Scopes )
assert . Equal ( t , tc . expected . ResponseTypes , have . Clients [ 0 ] . ResponseTypes )
assert . Equal ( t , tc . expected . ResponseModes , have . Clients [ 0 ] . ResponseModes )
assert . Equal ( t , tc . expected . GrantTypes , have . Clients [ 0 ] . GrantTypes )
if tc . validate != nil {
tc . validate ( t , have )
}
} )
t . Run ( "Warnings" , func ( t * testing . T ) {
require . Len ( t , val . Warnings ( ) , len ( tc . serrs ) )
for i , err := range tc . serrs {
assert . EqualError ( t , val . Warnings ( ) [ i ] , err )
}
} )
t . Run ( "Errors" , func ( t * testing . T ) {
require . Len ( t , val . Errors ( ) , len ( tc . errs ) )
for i , err := range tc . errs {
assert . EqualError ( t , val . Errors ( ) [ i ] , err )
}
} )
} )
}
}
func TestValidateOIDCClientTokenEndpointAuthMethod ( t * testing . T ) {
testCasses := [ ] struct {
name string
have string
public bool
expected string
errs [ ] string
} {
{ "ShouldSetDefaultValueConfidential" , "" , false , "" , nil } ,
{ "ShouldErrorOnInvalidValue" , "abc" , false , "abc" ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'token_endpoint_auth_method' must be one of 'none', 'client_secret_post', 'client_secret_basic', 'private_key_jwt', or 'client_secret_jwt' but it's configured as 'abc'" ,
2023-04-13 10:58:18 +00:00
} ,
} ,
{ "ShouldErrorOnInvalidValueForPublicClient" , "client_secret_post" , true , "client_secret_post" ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'token_endpoint_auth_method' must be 'none' when configured as the public client type but it's configured as 'client_secret_post'" ,
2023-04-13 10:58:18 +00:00
} ,
} ,
{ "ShouldErrorOnInvalidValueForConfidentialClient" , "none" , false , "none" ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: clients: client 'test': option 'token_endpoint_auth_method' must be one of 'client_secret_post', 'client_secret_basic', or 'private_key_jwt' when configured as the confidential client type unless it only includes implicit flow response types such as 'id_token', 'token', and 'id_token token' but it's configured as 'none'" ,
2023-04-13 10:58:18 +00:00
} ,
} ,
}
for _ , tc := range testCasses {
t . Run ( tc . name , func ( t * testing . T ) {
have := & schema . OpenIDConnectConfiguration {
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "test" ,
Public : tc . public ,
TokenEndpointAuthMethod : tc . have ,
} ,
} ,
}
val := schema . NewStructValidator ( )
2023-05-14 23:51:59 +00:00
validateOIDCClientTokenEndpointAuth ( 0 , have , val )
2023-04-13 10:58:18 +00:00
assert . Equal ( t , tc . expected , have . Clients [ 0 ] . TokenEndpointAuthMethod )
assert . Len ( t , val . Warnings ( ) , 0 )
require . Len ( t , val . Errors ( ) , len ( tc . errs ) )
if tc . errs != nil {
for i , err := range tc . errs {
assert . EqualError ( t , val . Errors ( ) [ i ] , err )
}
}
} )
}
}
2023-05-15 00:32:10 +00:00
func TestValidateOIDCClientJWKS ( t * testing . T ) {
frankenchain := schema . NewX509CertificateChainFromCerts ( [ ] * x509 . Certificate { certRSA2048 . Leaf ( ) , certRSA1024 . Leaf ( ) } )
frankenkey := & rsa . PrivateKey { }
* frankenkey = * keyRSA2048
frankenkey . PublicKey . N = nil
testCases := [ ] struct {
name string
haveURI * url . URL
haveJWKS [ ] schema . JWK
setup func ( config * schema . OpenIDConnectConfiguration )
expected func ( t * testing . T , config * schema . OpenIDConnectConfiguration )
errs [ ] string
} {
{
"ShouldValidateURL" ,
MustParseURL ( "https://example.com" ) ,
nil ,
nil ,
nil ,
nil ,
} ,
{
"ShouldErrorOnHTTPURL" ,
MustParseURL ( "http://example.com" ) ,
nil ,
nil ,
nil ,
[ ] string {
"identity_providers: oidc: clients: client 'test': public_keys: option 'uri' must have the 'https' scheme but the scheme is 'http'" ,
} ,
} ,
{
"ShouldErrorOnBothDefined" ,
MustParseURL ( "http://example.com" ) ,
[ ] schema . JWK {
{ KeyID : "test" } ,
} ,
nil ,
nil ,
[ ] string {
"identity_providers: oidc: clients: client 'test': public_keys: option 'uri' must not be defined at the same time as option 'values'" ,
} ,
} ,
{
"ShouldAllowGoodKey" ,
nil ,
[ ] schema . JWK {
{ KeyID : "test" , Use : oidc . KeyUseSignature , Algorithm : oidc . SigningAlgRSAUsingSHA256 , Key : keyRSA2048PKCS8 . Public ( ) } ,
} ,
nil ,
nil ,
nil ,
} ,
{
"ShouldAllowGoodKeyWithCertificate" ,
nil ,
[ ] schema . JWK {
{ KeyID : "test" , Use : oidc . KeyUseSignature , Algorithm : oidc . SigningAlgRSAUsingSHA256 , Key : keyRSA2048 . Public ( ) , CertificateChain : certRSA2048 } ,
} ,
nil ,
nil ,
nil ,
} ,
{
"ShouldErrorOnPrivateKey" ,
nil ,
[ ] schema . JWK {
{ KeyID : "test" , Use : oidc . KeyUseSignature , Algorithm : oidc . SigningAlgRSAUsingSHA256 , Key : keyRSA2048PKCS8 } ,
} ,
nil ,
nil ,
[ ] string {
"identity_providers: oidc: clients: client 'test': public_keys: values: key #1 with key id 'test': option 'key' must be a RSA public key or ECDSA public key but it's type is *rsa.PrivateKey" ,
} ,
} ,
{
"ShouldErrorOnMissingKID" ,
nil ,
[ ] schema . JWK {
{ Use : oidc . KeyUseSignature , Algorithm : oidc . SigningAlgRSAUsingSHA256 , Key : keyRSA2048PKCS8 . Public ( ) } ,
} ,
nil ,
nil ,
[ ] string {
"identity_providers: oidc: clients: client 'test': public_keys: values: key #1: option 'key_id' must be provided" ,
} ,
} ,
{
"ShouldFailOnNonKey" ,
nil ,
[ ] schema . JWK {
{ Use : oidc . KeyUseSignature , Algorithm : oidc . SigningAlgRSAUsingSHA256 , Key : "nokey" , KeyID : "KeyID" } ,
} ,
nil ,
nil ,
[ ] string {
"identity_providers: oidc: clients: client 'test': public_keys: values: key #1 with key id 'KeyID': option 'key' failed to get key properties: the key type 'string' is unknown or not valid for the configuration" ,
} ,
} ,
{
"ShouldFailOnBadUseAlg" ,
nil ,
[ ] schema . JWK {
{ KeyID : "test" , Use : "enc" , Algorithm : "bad" , Key : keyRSA2048PKCS8 . Public ( ) } ,
} ,
nil ,
nil ,
[ ] string {
"identity_providers: oidc: clients: client 'test': public_keys: values: key #1 with key id 'test': option 'use' must be one of 'sig' but it's configured as 'enc'" ,
"identity_providers: oidc: clients: client 'test': public_keys: values: key #1 with key id 'test': option 'algorithm' must be one of 'RS256', 'PS256', 'ES256', 'RS384', 'PS384', 'ES384', 'RS512', 'PS512', or 'ES512' but it's configured as 'bad'" ,
} ,
} ,
{
"ShouldFailOnEmptyKey" ,
nil ,
[ ] schema . JWK {
{ KeyID : "test" , Use : oidc . KeyUseSignature , Algorithm : oidc . SigningAlgRSAUsingSHA256 , Key : nil } ,
} ,
nil ,
nil ,
[ ] string {
"identity_providers: oidc: clients: client 'test': public_keys: values: key #1: option 'key' must be provided" ,
} ,
} ,
{
"ShouldFailOnMalformedKey" ,
nil ,
[ ] schema . JWK {
{ KeyID : "test" , Use : oidc . KeyUseSignature , Algorithm : oidc . SigningAlgRSAUsingSHA256 , Key : frankenkey . Public ( ) } ,
} ,
nil ,
nil ,
[ ] string {
"identity_providers: oidc: clients: client 'test': public_keys: values: key #1: option 'key' option 'key' must be a valid private key but the provided data is malformed as it's missing the public key bits" ,
} ,
} ,
{
"ShouldFailOnBadKeySize" ,
nil ,
[ ] schema . JWK {
{ KeyID : "test" , Use : oidc . KeyUseSignature , Algorithm : oidc . SigningAlgRSAUsingSHA256 , Key : keyRSA1024 . Public ( ) } ,
} ,
nil ,
nil ,
[ ] string {
"identity_providers: oidc: clients: client 'test': public_keys: values: key #1 with key id 'test': option 'key' is an RSA 1024 bit private key but it must at minimum be a RSA 2048 bit private key" ,
} ,
} ,
{
"ShouldFailOnMismatchedKeyCert" ,
nil ,
[ ] schema . JWK {
{ KeyID : "test" , Use : oidc . KeyUseSignature , Algorithm : oidc . SigningAlgRSAUsingSHA256 , Key : keyRSA2048PKCS8 . Public ( ) , CertificateChain : certRSA2048 } ,
} ,
nil ,
nil ,
[ ] string {
"identity_providers: oidc: clients: client 'test': public_keys: values: key #1 with key id 'test': option 'certificate_chain' does not appear to contain the public key for the public key provided by option 'key'" ,
} ,
} ,
{
"ShouldFailOnMismatchedCertChain" ,
nil ,
[ ] schema . JWK {
{ KeyID : "test" , Use : oidc . KeyUseSignature , Algorithm : oidc . SigningAlgRSAUsingSHA256 , Key : keyRSA2048 . Public ( ) , CertificateChain : frankenchain } ,
} ,
nil ,
nil ,
[ ] string {
"identity_providers: oidc: clients: client 'test': public_keys: values: key #1 with key id 'test': 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" ,
} ,
} ,
{
"ShouldSetDefaultUseAlgRSA" ,
nil ,
[ ] schema . JWK {
{ KeyID : "test" , Use : "" , Algorithm : "" , Key : keyRSA2048PKCS8 . Public ( ) } ,
} ,
nil ,
func ( t * testing . T , config * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , oidc . KeyUseSignature , config . Clients [ 0 ] . PublicKeys . Values [ 0 ] . Use )
assert . Equal ( t , oidc . SigningAlgRSAUsingSHA256 , config . Clients [ 0 ] . PublicKeys . Values [ 0 ] . Algorithm )
} ,
nil ,
} ,
{
"ShouldSetDefaultUseAlgECDSA256" ,
nil ,
[ ] schema . JWK {
{ KeyID : "test" , Use : "" , Algorithm : "" , Key : keyECDSAP256 . Public ( ) } ,
} ,
nil ,
func ( t * testing . T , config * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , oidc . KeyUseSignature , config . Clients [ 0 ] . PublicKeys . Values [ 0 ] . Use )
assert . Equal ( t , oidc . SigningAlgECDSAUsingP256AndSHA256 , config . Clients [ 0 ] . PublicKeys . Values [ 0 ] . Algorithm )
} ,
nil ,
} ,
{
"ShouldSetDefaultUseAlgECDSA384" ,
nil ,
[ ] schema . JWK {
{ KeyID : "test" , Use : "" , Algorithm : "" , Key : keyECDSAP384 . Public ( ) } ,
} ,
nil ,
func ( t * testing . T , config * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , oidc . KeyUseSignature , config . Clients [ 0 ] . PublicKeys . Values [ 0 ] . Use )
assert . Equal ( t , oidc . SigningAlgECDSAUsingP384AndSHA384 , config . Clients [ 0 ] . PublicKeys . Values [ 0 ] . Algorithm )
} ,
nil ,
} ,
{
"ShouldSetDefaultUseAlgECDSA521" ,
nil ,
[ ] schema . JWK {
{ KeyID : "test" , Use : "" , Algorithm : "" , Key : keyECDSAP521 . Public ( ) } ,
} ,
nil ,
func ( t * testing . T , config * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , oidc . KeyUseSignature , config . Clients [ 0 ] . PublicKeys . Values [ 0 ] . Use )
assert . Equal ( t , oidc . SigningAlgECDSAUsingP521AndSHA512 , config . Clients [ 0 ] . PublicKeys . Values [ 0 ] . Algorithm )
} ,
nil ,
} ,
{
"ShouldConfigureRegisteredRequestObjectAlgs" ,
nil ,
[ ] schema . JWK {
{ KeyID : "test" , Use : "" , Algorithm : "" , Key : keyECDSAP521 . Public ( ) } ,
} ,
nil ,
func ( t * testing . T , config * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , oidc . KeyUseSignature , config . Clients [ 0 ] . PublicKeys . Values [ 0 ] . Use )
assert . Equal ( t , oidc . SigningAlgECDSAUsingP521AndSHA512 , config . Clients [ 0 ] . PublicKeys . Values [ 0 ] . Algorithm )
assert . Equal ( t , [ ] string { oidc . SigningAlgECDSAUsingP521AndSHA512 } , config . Discovery . RequestObjectSigningAlgs )
} ,
nil ,
} ,
{
"ShouldOnlyAllowRequetsObjectSigningAlgsThatTheClientHasKeysFor" ,
nil ,
[ ] schema . JWK {
{ KeyID : "test" , Use : "" , Algorithm : "" , Key : keyECDSAP521 . Public ( ) } ,
} ,
func ( config * schema . OpenIDConnectConfiguration ) {
config . Clients [ 0 ] . RequestObjectSigningAlg = oidc . SigningAlgRSAUsingSHA512
} ,
func ( t * testing . T , config * schema . OpenIDConnectConfiguration ) {
assert . Equal ( t , oidc . KeyUseSignature , config . Clients [ 0 ] . PublicKeys . Values [ 0 ] . Use )
assert . Equal ( t , oidc . SigningAlgECDSAUsingP521AndSHA512 , config . Clients [ 0 ] . PublicKeys . Values [ 0 ] . Algorithm )
assert . Equal ( t , [ ] string { oidc . SigningAlgECDSAUsingP521AndSHA512 } , config . Discovery . RequestObjectSigningAlgs )
} ,
[ ] string {
"identity_providers: oidc: clients: client 'test': option 'request_object_signing_alg' must be one of 'ES512' configured in the client option 'public_keys'" ,
} ,
} ,
}
for _ , tc := range testCases {
t . Run ( tc . name , func ( t * testing . T ) {
config := & schema . OpenIDConnectConfiguration {
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "test" ,
PublicKeys : schema . OpenIDConnectClientPublicKeys {
URI : tc . haveURI ,
Values : tc . haveJWKS ,
} ,
} ,
} ,
}
if tc . setup != nil {
tc . setup ( config )
}
val := schema . NewStructValidator ( )
validateOIDCClientPublicKeys ( 0 , config , val )
if tc . expected != nil {
tc . expected ( t , config )
}
n := len ( tc . errs )
assert . Len ( t , val . Warnings ( ) , 0 )
theErrors := val . Errors ( )
require . Len ( t , theErrors , n )
for i := 0 ; i < n ; i ++ {
assert . EqualError ( t , theErrors [ i ] , tc . errs [ i ] )
}
} )
}
}
2023-05-15 00:03:19 +00:00
func TestValidateOIDCIssuer ( t * testing . T ) {
frankenchain := schema . NewX509CertificateChainFromCerts ( [ ] * x509 . Certificate { certRSA2048 . Leaf ( ) , certRSA1024 . Leaf ( ) } )
frankenkey := & rsa . PrivateKey { }
* frankenkey = * keyRSA2048
frankenkey . PublicKey . N = nil
testCases := [ ] struct {
name string
have schema . OpenIDConnectConfiguration
expected schema . OpenIDConnectConfiguration
errs [ ] string
} {
{
"ShouldMapLegacyConfiguration" ,
schema . OpenIDConnectConfiguration {
IssuerPrivateKey : keyRSA2048 ,
} ,
schema . OpenIDConnectConfiguration {
IssuerPrivateKey : keyRSA2048 ,
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
{ KeyID : "1f8bfc" , Key : keyRSA2048 , Algorithm : oidc . SigningAlgRSAUsingSHA256 , Use : oidc . KeyUseSignature } ,
2023-05-15 00:03:19 +00:00
} ,
Discovery : schema . OpenIDConnectDiscovery {
2023-05-15 00:32:10 +00:00
DefaultKeyID : "1f8bfc" ,
ResponseObjectSigningAlgs : [ ] string { oidc . SigningAlgRSAUsingSHA256 } ,
2023-05-15 00:03:19 +00:00
} ,
} ,
nil ,
} ,
{
"ShouldSetDefaultKeyValues" ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
2023-05-15 00:03:19 +00:00
{ Key : keyRSA2048 , CertificateChain : certRSA2048 } ,
{ Key : keyECDSAP256 , CertificateChain : certECDSAP256 } ,
{ Key : keyECDSAP384 , CertificateChain : certECDSAP384 } ,
{ Key : keyECDSAP521 , CertificateChain : certECDSAP521 } ,
} ,
} ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
{ 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" } ,
2023-05-15 00:03:19 +00:00
} ,
Discovery : schema . OpenIDConnectDiscovery {
2023-05-15 00:32:10 +00:00
DefaultKeyID : "1f8bfc" ,
ResponseObjectSigningAlgs : [ ] string { oidc . SigningAlgRSAUsingSHA256 , oidc . SigningAlgECDSAUsingP256AndSHA256 , oidc . SigningAlgECDSAUsingP384AndSHA384 , oidc . SigningAlgECDSAUsingP521AndSHA512 } ,
2023-05-15 00:03:19 +00:00
} ,
} ,
nil ,
} ,
{
"ShouldRaiseErrorsDuplicateRSA256Keys" ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
2023-05-15 00:03:19 +00:00
{ Key : keyRSA2048 , CertificateChain : certRSA2048 } ,
{ Key : keyRSA4096 , CertificateChain : certRSA4096 } ,
} ,
} ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
{ Key : keyRSA2048 , CertificateChain : certRSA2048 , Algorithm : oidc . SigningAlgRSAUsingSHA256 , Use : oidc . KeyUseSignature , KeyID : "1f8bfc" } ,
{ Key : keyRSA4096 , CertificateChain : certRSA4096 , Algorithm : oidc . SigningAlgRSAUsingSHA256 , Use : oidc . KeyUseSignature , KeyID : "bf1e10" } ,
2023-05-15 00:03:19 +00:00
} ,
Discovery : schema . OpenIDConnectDiscovery {
2023-05-15 00:32:10 +00:00
DefaultKeyID : "1f8bfc" ,
ResponseObjectSigningAlgs : [ ] string { oidc . SigningAlgRSAUsingSHA256 } ,
2023-05-15 00:03:19 +00:00
} ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: issuer_private_keys: key #2 with key id 'bf1e10': option 'algorithm' must be unique" ,
2023-05-15 00:03:19 +00:00
} ,
} ,
{
"ShouldRaiseErrorsDuplicateRSA256Keys" ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
2023-05-15 00:03:19 +00:00
{ Key : keyRSA4096 , CertificateChain : certRSA4096 , Algorithm : oidc . SigningAlgRSAUsingSHA512 } ,
} ,
} ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
{ Key : keyRSA4096 , CertificateChain : certRSA4096 , Algorithm : oidc . SigningAlgRSAUsingSHA512 , Use : oidc . KeyUseSignature , KeyID : "bf1e10" } ,
2023-05-15 00:03:19 +00:00
} ,
Discovery : schema . OpenIDConnectDiscovery {
2023-05-15 00:32:10 +00:00
DefaultKeyID : "" ,
ResponseObjectSigningAlgs : [ ] string { oidc . SigningAlgRSAUsingSHA512 } ,
2023-05-15 00:03:19 +00:00
} ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: issuer_private_keys: keys: must at least have one key supporting the 'RS256' algorithm but only has 'RS512'" ,
2023-05-15 00:03:19 +00:00
} ,
} ,
{
"ShouldRaiseErrorOnBadCurve" ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
2023-05-15 00:03:19 +00:00
{ Key : keyRSA4096 , CertificateChain : certRSA4096 } ,
{ Key : keyECDSAP224 , CertificateChain : certECDSAP224 } ,
} ,
} ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
{ Key : keyRSA4096 , CertificateChain : certRSA4096 , Algorithm : oidc . SigningAlgRSAUsingSHA256 , Use : oidc . KeyUseSignature , KeyID : "bf1e10" } ,
2023-05-15 00:03:19 +00:00
{ Key : keyECDSAP224 , CertificateChain : certECDSAP224 } ,
} ,
Discovery : schema . OpenIDConnectDiscovery {
2023-05-15 00:32:10 +00:00
DefaultKeyID : "bf1e10" ,
ResponseObjectSigningAlgs : [ ] string { oidc . SigningAlgRSAUsingSHA256 } ,
2023-05-15 00:03:19 +00:00
} ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: issuer_private_keys: key #2: option 'key' failed to calculate thumbprint to configure key id value: square/go-jose: unsupported/unknown elliptic curve" ,
2023-05-15 00:03:19 +00:00
} ,
} ,
{
"ShouldRaiseErrorOnBadRSAKey" ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
2023-05-15 00:03:19 +00:00
{ Key : keyRSA1024 , CertificateChain : certRSA1024 } ,
} ,
} ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
{ Key : keyRSA1024 , CertificateChain : certRSA1024 , Algorithm : oidc . SigningAlgRSAUsingSHA256 , Use : oidc . KeyUseSignature , KeyID : "cf375e" } ,
2023-05-15 00:03:19 +00:00
} ,
Discovery : schema . OpenIDConnectDiscovery {
2023-05-15 00:32:10 +00:00
DefaultKeyID : "cf375e" ,
ResponseObjectSigningAlgs : [ ] string { oidc . SigningAlgRSAUsingSHA256 } ,
2023-05-15 00:03:19 +00:00
} ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"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" ,
2023-05-15 00:03:19 +00:00
} ,
} ,
{
"ShouldRaiseErrorOnBadAlg" ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
2023-05-15 00:03:19 +00:00
{ Key : keyRSA4096 , CertificateChain : certRSA4096 , Algorithm : "invalid" } ,
} ,
} ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
{ Key : keyRSA4096 , CertificateChain : certRSA4096 , Algorithm : "invalid" , Use : oidc . KeyUseSignature , KeyID : "bf1e10" } ,
2023-05-15 00:03:19 +00:00
} ,
Discovery : schema . OpenIDConnectDiscovery {
2023-05-15 00:32:10 +00:00
DefaultKeyID : "" ,
ResponseObjectSigningAlgs : [ ] string { "invalid" } ,
2023-05-15 00:03:19 +00:00
} ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"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'" ,
2023-05-15 00:03:19 +00:00
} ,
} ,
{
"ShouldRaiseErrorOnBadUse" ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
2023-05-15 00:03:19 +00:00
{ Key : keyRSA4096 , CertificateChain : certRSA4096 , Use : "invalid" } ,
} ,
} ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
{ Key : keyRSA4096 , CertificateChain : certRSA4096 , Algorithm : oidc . SigningAlgRSAUsingSHA256 , Use : "invalid" , KeyID : "bf1e10" } ,
2023-05-15 00:03:19 +00:00
} ,
Discovery : schema . OpenIDConnectDiscovery {
2023-05-15 00:32:10 +00:00
DefaultKeyID : "bf1e10" ,
ResponseObjectSigningAlgs : [ ] string { oidc . SigningAlgRSAUsingSHA256 } ,
2023-05-15 00:03:19 +00:00
} ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"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'" ,
2023-05-15 00:03:19 +00:00
} ,
} ,
{
"ShouldRaiseErrorOnBadKeyIDLength" ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
2023-05-15 00:03:19 +00:00
{ Key : keyRSA4096 , CertificateChain : certRSA4096 , KeyID : "thisistoolong" } ,
} ,
} ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
2023-05-15 00:03:19 +00:00
{ Key : keyRSA4096 , CertificateChain : certRSA4096 , Algorithm : oidc . SigningAlgRSAUsingSHA256 , Use : oidc . KeyUseSignature , KeyID : "thisistoolong" } ,
} ,
Discovery : schema . OpenIDConnectDiscovery {
2023-05-15 00:32:10 +00:00
DefaultKeyID : "thisistoolong" ,
ResponseObjectSigningAlgs : [ ] string { oidc . SigningAlgRSAUsingSHA256 } ,
2023-05-15 00:03:19 +00:00
} ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: issuer_private_keys: key #1 with key id 'thisistoolong': option `key_id`` must be 7 characters or less" ,
2023-05-15 00:03:19 +00:00
} ,
} ,
{
"ShouldRaiseErrorOnBadKeyIDCharacters" ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
2023-05-15 00:03:19 +00:00
{ Key : keyRSA4096 , CertificateChain : certRSA4096 , KeyID : "x@x" } ,
} ,
} ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
2023-05-15 00:03:19 +00:00
{ Key : keyRSA4096 , CertificateChain : certRSA4096 , Algorithm : oidc . SigningAlgRSAUsingSHA256 , Use : oidc . KeyUseSignature , KeyID : "x@x" } ,
} ,
Discovery : schema . OpenIDConnectDiscovery {
2023-05-15 00:32:10 +00:00
DefaultKeyID : "x@x" ,
ResponseObjectSigningAlgs : [ ] string { oidc . SigningAlgRSAUsingSHA256 } ,
2023-05-15 00:03:19 +00:00
} ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: issuer_private_keys: key #1 with key id 'x@x': option 'key_id' must only have alphanumeric characters" ,
2023-05-15 00:03:19 +00:00
} ,
} ,
{
"ShouldRaiseErrorOnBadKeyIDDuplicates" ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
2023-05-15 00:03:19 +00:00
{ Key : keyRSA4096 , CertificateChain : certRSA4096 , KeyID : "x" } ,
{ Key : keyRSA2048 , CertificateChain : certRSA2048 , Algorithm : oidc . SigningAlgRSAPSSUsingSHA256 , KeyID : "x" } ,
} ,
} ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
2023-05-15 00:03:19 +00:00
{ Key : keyRSA4096 , CertificateChain : certRSA4096 , Algorithm : oidc . SigningAlgRSAUsingSHA256 , Use : oidc . KeyUseSignature , KeyID : "x" } ,
{ Key : keyRSA2048 , CertificateChain : certRSA2048 , Algorithm : oidc . SigningAlgRSAPSSUsingSHA256 , Use : oidc . KeyUseSignature , KeyID : "x" } ,
} ,
Discovery : schema . OpenIDConnectDiscovery {
2023-05-15 00:32:10 +00:00
DefaultKeyID : "x" ,
ResponseObjectSigningAlgs : [ ] string { oidc . SigningAlgRSAUsingSHA256 , oidc . SigningAlgRSAPSSUsingSHA256 } ,
2023-05-15 00:03:19 +00:00
} ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: issuer_private_keys: key #2 with key id 'x': option 'key_id' must be unique" ,
2023-05-15 00:03:19 +00:00
} ,
} ,
{
"ShouldRaiseErrorOnEd25519Keys" ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
2023-05-15 00:03:19 +00:00
{ Key : keyEd2519 , CertificateChain : certEd15519 } ,
} ,
} ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
{ Key : keyEd2519 , CertificateChain : certEd15519 , KeyID : "14dfd3" } ,
2023-05-15 00:03:19 +00:00
} ,
Discovery : schema . OpenIDConnectDiscovery {
2023-05-15 00:32:10 +00:00
DefaultKeyID : "" ,
ResponseObjectSigningAlgs : [ ] string ( nil ) ,
2023-05-15 00:03:19 +00:00
} ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"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" ,
2023-05-15 00:03:19 +00:00
} ,
} ,
{
"ShouldRaiseErrorOnCertificateAsKey" ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
2023-05-15 00:03:19 +00:00
{ Key : publicRSA2048Pair } ,
} ,
} ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
{ Key : publicRSA2048Pair , Algorithm : oidc . SigningAlgRSAUsingSHA256 , Use : oidc . KeyUseSignature , KeyID : "9a0e71" } ,
2023-05-15 00:03:19 +00:00
} ,
Discovery : schema . OpenIDConnectDiscovery {
2023-05-15 00:32:10 +00:00
DefaultKeyID : "9a0e71" ,
ResponseObjectSigningAlgs : [ ] string { oidc . SigningAlgRSAUsingSHA256 } ,
2023-05-15 00:03:19 +00:00
} ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"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" ,
2023-05-15 00:03:19 +00:00
} ,
} ,
{
"ShouldRaiseErrorOnInvalidChain" ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
2023-05-15 00:03:19 +00:00
{ Key : keyRSA2048 , CertificateChain : frankenchain } ,
} ,
} ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
{ Key : keyRSA2048 , CertificateChain : frankenchain , Algorithm : oidc . SigningAlgRSAUsingSHA256 , Use : oidc . KeyUseSignature , KeyID : "1f8bfc" } ,
2023-05-15 00:03:19 +00:00
} ,
Discovery : schema . OpenIDConnectDiscovery {
2023-05-15 00:32:10 +00:00
DefaultKeyID : "1f8bfc" ,
ResponseObjectSigningAlgs : [ ] string { oidc . SigningAlgRSAUsingSHA256 } ,
2023-05-15 00:03:19 +00:00
} ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"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" ,
2023-05-15 00:03:19 +00:00
} ,
} ,
{
"ShouldRaiseErrorOnInvalidPrivateKeyN" ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
2023-05-15 00:03:19 +00:00
{ Key : frankenkey } ,
} ,
} ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
2023-05-15 00:03:19 +00:00
{ Key : frankenkey } ,
} ,
Discovery : schema . OpenIDConnectDiscovery {
2023-05-15 00:32:10 +00:00
DefaultKeyID : "" ,
ResponseObjectSigningAlgs : [ ] string ( nil ) ,
2023-05-15 00:03:19 +00:00
} ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: issuer_private_keys: key #1: option 'key' must be a valid private key but the provided data is malformed as it's missing the public key bits" ,
2023-05-15 00:03:19 +00:00
} ,
} ,
{
"ShouldRaiseErrorOnCertForKey" ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
2023-05-15 00:03:19 +00:00
{ Key : certRSA2048 } ,
} ,
} ,
schema . OpenIDConnectConfiguration {
2023-05-15 00:32:10 +00:00
IssuerPrivateKeys : [ ] schema . JWK {
2023-05-15 00:03:19 +00:00
{ Key : certRSA2048 } ,
} ,
Discovery : schema . OpenIDConnectDiscovery {
2023-05-15 00:32:10 +00:00
DefaultKeyID : "" ,
ResponseObjectSigningAlgs : [ ] string ( nil ) ,
2023-05-15 00:03:19 +00:00
} ,
} ,
[ ] string {
2023-05-15 00:32:10 +00:00
"identity_providers: oidc: issuer_private_keys: key #1 with key id '': option 'key' failed to get key properties: the key type 'schema.X509CertificateChain' is unknown or not valid for the configuration" ,
2023-05-15 00:03:19 +00:00
} ,
} ,
}
var n int
for _ , tc := range testCases {
t . Run ( tc . name , func ( t * testing . T ) {
val := schema . NewStructValidator ( )
validateOIDCIssuer ( & tc . have , val )
assert . Equal ( t , tc . expected . Discovery . DefaultKeyID , tc . have . Discovery . DefaultKeyID )
2023-05-15 00:32:10 +00:00
assert . Equal ( t , tc . expected . Discovery . ResponseObjectSigningAlgs , tc . have . Discovery . ResponseObjectSigningAlgs )
2023-05-15 00:03:19 +00:00
assert . Equal ( t , tc . expected . IssuerPrivateKey , tc . have . IssuerPrivateKey )
assert . Equal ( t , tc . expected . IssuerCertificateChain , tc . have . IssuerCertificateChain )
2023-05-15 00:32:10 +00:00
n = len ( tc . expected . IssuerPrivateKeys )
2023-05-15 00:03:19 +00:00
2023-05-15 00:32:10 +00:00
require . Len ( t , tc . have . IssuerPrivateKeys , n )
2023-05-15 00:03:19 +00:00
for i := 0 ; i < n ; i ++ {
t . Run ( fmt . Sprintf ( "Key%d" , i ) , func ( t * testing . T ) {
2023-05-15 00:32:10 +00:00
assert . Equal ( t , tc . expected . IssuerPrivateKeys [ i ] . Algorithm , tc . have . IssuerPrivateKeys [ i ] . Algorithm )
assert . Equal ( t , tc . expected . IssuerPrivateKeys [ i ] . Use , tc . have . IssuerPrivateKeys [ i ] . Use )
assert . Equal ( t , tc . expected . IssuerPrivateKeys [ i ] . KeyID , tc . have . IssuerPrivateKeys [ i ] . KeyID )
assert . Equal ( t , tc . expected . IssuerPrivateKeys [ i ] . Key , tc . have . IssuerPrivateKeys [ i ] . Key )
assert . Equal ( t , tc . expected . IssuerPrivateKeys [ i ] . CertificateChain , tc . have . IssuerPrivateKeys [ i ] . CertificateChain )
2023-05-15 00:03:19 +00:00
} )
}
n = len ( tc . errs )
require . Len ( t , val . Errors ( ) , n )
for i := 0 ; i < n ; i ++ {
assert . EqualError ( t , val . Errors ( ) [ i ] , tc . errs [ i ] )
}
} )
}
}
2022-10-20 03:21:45 +00:00
func MustDecodeSecret ( value string ) * schema . PasswordDigest {
2022-12-04 22:37:08 +00:00
if secret , err := schema . DecodePasswordDigest ( value ) ; err != nil {
2022-10-20 03:21:45 +00:00
panic ( err )
} else {
return secret
}
}
2023-05-15 00:03:19 +00:00
func MustLoadCrypto ( alg , mod , ext string , extra ... string ) any {
fparts := [ ] string { alg , mod }
if len ( extra ) != 0 {
fparts = append ( fparts , extra ... )
2022-10-20 02:16:36 +00:00
}
2023-05-15 00:03:19 +00:00
var (
data [ ] byte
decoded any
err error
)
if data , err = os . ReadFile ( fmt . Sprintf ( pathCrypto , strings . Join ( fparts , "_" ) , ext ) ) ; err != nil {
panic ( err )
2022-10-20 02:16:36 +00:00
}
2023-05-15 00:03:19 +00:00
if decoded , err = utils . ParseX509FromPEMRecursive ( data ) ; err != nil {
2022-10-20 02:16:36 +00:00
panic ( err )
}
2023-05-15 00:03:19 +00:00
return decoded
}
func MustLoadCertificateChain ( alg , op string ) schema . X509CertificateChain {
decoded := MustLoadCrypto ( alg , op , "crt" )
switch cert := decoded . ( type ) {
case * x509 . Certificate :
return schema . NewX509CertificateChainFromCerts ( [ ] * x509 . Certificate { cert } )
case [ ] * x509 . Certificate :
return schema . NewX509CertificateChainFromCerts ( cert )
default :
panic ( fmt . Errorf ( "the key was not a *x509.Certificate or []*x509.Certificate, it's a %T" , cert ) )
}
}
func MustLoadEd15519PrivateKey ( curve string , extra ... string ) ed25519 . PrivateKey {
decoded := MustLoadCrypto ( "ED25519" , curve , "pem" , extra ... )
key , ok := decoded . ( ed25519 . PrivateKey )
if ! ok {
panic ( fmt . Errorf ( "the key was not a ed25519.PrivateKey, it's a %T" , key ) )
}
2022-10-20 02:16:36 +00:00
return key
}
2023-05-15 00:03:19 +00:00
func MustLoadECDSAPrivateKey ( curve string , extra ... string ) * ecdsa . PrivateKey {
decoded := MustLoadCrypto ( "ECDSA" , curve , "pem" , extra ... )
2022-10-20 02:16:36 +00:00
2023-05-15 00:03:19 +00:00
key , ok := decoded . ( * ecdsa . PrivateKey )
if ! ok {
panic ( fmt . Errorf ( "the key was not a *ecdsa.PrivateKey, it's a %T" , key ) )
}
return key
}
func MustLoadRSAPublicKey ( bits string , extra ... string ) * rsa . PublicKey {
decoded := MustLoadCrypto ( "RSA" , bits , "pem" , extra ... )
key , ok := decoded . ( * rsa . PublicKey )
if ! ok {
panic ( fmt . Errorf ( "the key was not a *rsa.PublicKey, it's a %T" , key ) )
2022-10-20 02:16:36 +00:00
}
2023-05-15 00:03:19 +00:00
return key
2022-10-20 02:16:36 +00:00
}
2023-05-15 00:03:19 +00:00
func MustLoadRSAPrivateKey ( bits string , extra ... string ) * rsa . PrivateKey {
decoded := MustLoadCrypto ( "RSA" , bits , "pem" , extra ... )
key , ok := decoded . ( * rsa . PrivateKey )
if ! ok {
panic ( fmt . Errorf ( "the key was not a *rsa.PrivateKey, it's a %T" , key ) )
}
return key
}
const (
pathCrypto = "../test_resources/crypto/%s.%s"
)
2022-10-02 02:07:40 +00:00
var (
2023-05-15 00:03:19 +00:00
tOpenIDConnectPBKDF2ClientSecret , tOpenIDConnectPlainTextClientSecret * schema . PasswordDigest
// Standard RSA key pair.
publicRSA2048Pair * rsa . PublicKey
privateRSA2048Pair * rsa . PrivateKey
// Standard RSA key / certificate pairs.
keyRSA1024 , keyRSA2048 , keyRSA2048PKCS8 , keyRSA4096 * rsa . PrivateKey
certRSA1024 , certRSA2048 , certRSA4096 schema . X509CertificateChain
// Standard ECDSA key / certificate pairs.
keyECDSAP224 , keyECDSAP256 , keyECDSAP384 , keyECDSAP521 * ecdsa . PrivateKey
certECDSAP224 , certECDSAP256 , certECDSAP384 , certECDSAP521 schema . X509CertificateChain
// Standard ECDSA key / certificate pairs.
keyECDSAP256PKCS8 , keyECDSAP384PKCS8 , keyECDSAP521PKCS8 * ecdsa . PrivateKey
2023-05-15 00:32:10 +00:00
certECDSAP224PKCS8 , certECDSAP256PKCS8 , certECDSAP384PKCS8 , certECDSAP521PKCS8 schema . X509CertificateChain //nolint:unused
2023-05-15 00:03:19 +00:00
// Ed15519 key / certificate pair.
keyEd2519 ed25519 . PrivateKey
certEd15519 schema . X509CertificateChain
2022-10-20 02:16:36 +00:00
)
2023-05-15 00:03:19 +00:00
func init ( ) {
tOpenIDConnectPBKDF2ClientSecret = MustDecodeSecret ( "$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng" )
tOpenIDConnectPlainTextClientSecret = MustDecodeSecret ( "$plaintext$example" )
publicRSA2048Pair = MustLoadRSAPublicKey ( "2048" , "PAIR" , "PUBLIC" )
privateRSA2048Pair = MustLoadRSAPrivateKey ( "2048" , "PAIR" , "PRIVATE" )
keyRSA1024 = MustLoadRSAPrivateKey ( "1024" )
keyRSA2048 = MustLoadRSAPrivateKey ( "2048" )
keyRSA4096 = MustLoadRSAPrivateKey ( "4096" )
keyECDSAP224 = MustLoadECDSAPrivateKey ( "P224" )
keyECDSAP256 = MustLoadECDSAPrivateKey ( "P256" )
keyECDSAP384 = MustLoadECDSAPrivateKey ( "P384" )
keyECDSAP521 = MustLoadECDSAPrivateKey ( "P521" )
keyEd2519 = MustLoadEd15519PrivateKey ( "PKCS8" )
keyRSA2048PKCS8 = MustLoadRSAPrivateKey ( "2048" , "PKCS8" )
keyECDSAP256PKCS8 = MustLoadECDSAPrivateKey ( "P256" , "PKCS8" )
keyECDSAP384PKCS8 = MustLoadECDSAPrivateKey ( "P384" , "PKCS8" )
keyECDSAP521PKCS8 = MustLoadECDSAPrivateKey ( "P521" , "PKCS8" )
certRSA1024 = MustLoadCertificateChain ( "RSA" , "1024" )
certRSA2048 = MustLoadCertificateChain ( "RSA" , "2048" )
certRSA4096 = MustLoadCertificateChain ( "RSA" , "4096" )
certECDSAP224 = MustLoadCertificateChain ( "ECDSA" , "P224" )
certECDSAP256 = MustLoadCertificateChain ( "ECDSA" , "P256" )
certECDSAP384 = MustLoadCertificateChain ( "ECDSA" , "P384" )
certECDSAP521 = MustLoadCertificateChain ( "ECDSA" , "P521" )
certEd15519 = MustLoadCertificateChain ( "ED25519" , "PKCS8" )
}