2021-05-04 22:06:05 +00:00
package validator
import (
2022-10-02 02:07:40 +00:00
"crypto/rsa"
"crypto/x509"
"encoding/pem"
2021-05-04 22:06:05 +00:00
"errors"
"fmt"
2022-04-07 06:13:01 +00:00
"net/url"
2022-11-23 23:16:23 +00:00
"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 )
2021-08-03 09:55:21 +00:00
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , errFmtOIDCNoPrivateKey )
assert . EqualError ( t , validator . Errors ( ) [ 1 ] , errFmtOIDCNoClientsConfigured )
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" ,
2022-10-20 02:16:36 +00:00
IssuerPrivateKey : MustParseRSAPrivateKey ( testKey1 ) ,
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" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$example" ) ,
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" ,
2022-10-20 02:16:36 +00:00
IssuerPrivateKey : MustParseRSAPrivateKey ( testKey1 ) ,
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" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$example" ) ,
2022-04-07 00:58:51 +00:00
} ,
} ,
} ,
}
ValidateIdentityProviders ( config , validator )
require . Len ( t , validator . Errors ( ) , 1 )
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , "identity_providers: oidc: cors: option 'endpoints' contains an invalid value 'invalid_endpoint': must be one of 'authorization', 'token', 'introspection', 'revocation', 'userinfo'" )
}
2022-03-02 04:44:05 +00:00
func TestShouldRaiseErrorWhenOIDCPKCEEnforceValueInvalid ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := & schema . IdentityProvidersConfiguration {
OIDC : & schema . OpenIDConnectConfiguration {
HMACSecret : "rLABDrx87et5KvRHVUgTm3pezWWd8LMN" ,
2022-10-20 02:16:36 +00:00
IssuerPrivateKey : MustParseRSAPrivateKey ( testKey1 ) ,
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 )
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , "identity_providers: oidc: option 'enforce_pkce' must be 'never', 'public_clients_only' or 'always', but it is configured as 'invalid'" )
assert . EqualError ( t , validator . Errors ( ) [ 1 ] , errFmtOIDCNoClientsConfigured )
}
2022-04-07 00:58:51 +00:00
func TestShouldRaiseErrorWhenOIDCCORSOriginsHasInvalidValues ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := & schema . IdentityProvidersConfiguration {
OIDC : & schema . OpenIDConnectConfiguration {
HMACSecret : "rLABDrx87et5KvRHVUgTm3pezWWd8LMN" ,
2022-10-20 02:16:36 +00:00
IssuerPrivateKey : MustParseRSAPrivateKey ( testKey1 ) ,
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" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$jk12nb3klqwmnelqkwenm" ) ,
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" ,
2022-10-20 02:16:36 +00:00
IssuerPrivateKey : MustParseRSAPrivateKey ( testKey1 ) ,
2021-05-04 22:06:05 +00:00
} ,
}
ValidateIdentityProviders ( config , validator )
require . Len ( t , validator . Errors ( ) , 1 )
2021-08-03 09:55:21 +00:00
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , errFmtOIDCNoClientsConfigured )
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 {
fmt . Sprintf ( errFmtOIDCClientInvalidSecret , "" ) ,
errFmtOIDCClientsWithEmptyID ,
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" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$a-secret" ) ,
2021-05-04 22:06:05 +00:00
Policy : "a-policy" ,
RedirectURIs : [ ] string {
"https://google.com" ,
} ,
} ,
2022-01-21 11:05:53 +00:00
} ,
2022-04-07 06:13:01 +00:00
Errors : [ ] string { fmt . Sprintf ( errFmtOIDCClientInvalidPolicy , "client-1" , "a-policy" ) } ,
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" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$a-secret" ) ,
2022-01-21 11:05:53 +00:00
Policy : policyTwoFactor ,
RedirectURIs : [ ] string { } ,
} ,
{
ID : "client-x" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$a-secret" ) ,
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
} ,
2022-04-07 06:13:01 +00:00
Errors : [ ] string { errFmtOIDCClientsDuplicateID } ,
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" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$a-secret" ) ,
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 {
fmt . Sprintf ( errFmtOIDCClientRedirectURICantBeParsed , "client-check-uri-parse" , "http://abc@%two" , errors . New ( "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" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$a-secret" ) ,
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 {
fmt . Sprintf ( errFmtOIDCClientRedirectURIAbsolute , "client-check-uri-abs" , "google.com" ) ,
} ,
} ,
2022-04-08 07:38:38 +00:00
{
Name : "ValidSectorIdentifier" ,
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "client-valid-sector" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$a-secret" ) ,
2022-04-08 07:38:38 +00:00
Policy : policyTwoFactor ,
RedirectURIs : [ ] string {
"https://google.com" ,
} ,
2022-10-21 08:41:33 +00:00
SectorIdentifier : mustParseURL ( examplecom ) ,
2022-04-08 07:38:38 +00:00
} ,
} ,
} ,
{
Name : "ValidSectorIdentifierWithPort" ,
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "client-valid-sector" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$a-secret" ) ,
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" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$a-secret" ) ,
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 {
2022-10-21 08:41:33 +00:00
fmt . Sprintf ( errFmtOIDCClientInvalidSectorIdentifier , "client-invalid-sector" , "https://user:pass@example.com/path?query=abc#fragment" , examplecom , "scheme" , "https" ) ,
fmt . Sprintf ( errFmtOIDCClientInvalidSectorIdentifier , "client-invalid-sector" , "https://user:pass@example.com/path?query=abc#fragment" , examplecom , "path" , "/path" ) ,
fmt . Sprintf ( errFmtOIDCClientInvalidSectorIdentifier , "client-invalid-sector" , "https://user:pass@example.com/path?query=abc#fragment" , examplecom , "query" , "query=abc" ) ,
fmt . Sprintf ( errFmtOIDCClientInvalidSectorIdentifier , "client-invalid-sector" , "https://user:pass@example.com/path?query=abc#fragment" , examplecom , "fragment" , "fragment" ) ,
fmt . Sprintf ( errFmtOIDCClientInvalidSectorIdentifier , "client-invalid-sector" , "https://user:pass@example.com/path?query=abc#fragment" , examplecom , "username" , "user" ) ,
fmt . Sprintf ( errFmtOIDCClientInvalidSectorIdentifierWithoutValue , "client-invalid-sector" , "https://user:pass@example.com/path?query=abc#fragment" , examplecom , "password" ) ,
2022-04-07 06:13:01 +00:00
} ,
} ,
{
Name : "InvalidSectorIdentifierInvalidHost" ,
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "client-invalid-sector" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$a-secret" ) ,
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 {
fmt . Sprintf ( errFmtOIDCClientInvalidSectorIdentifierHost , "client-invalid-sector" , "example.com/path?query=abc#fragment" ) ,
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" ,
Secret : MustDecodeSecret ( "$plaintext$a-secret" ) ,
Policy : policyTwoFactor ,
RedirectURIs : [ ] string {
"https://google.com" ,
} ,
ConsentMode : "cap" ,
} ,
} ,
Errors : [ ] string {
fmt . Sprintf ( errFmtOIDCClientInvalidConsentMode , "client-bad-consent-mode" , strings . Join ( append ( validOIDCClientConsentModes , "auto" ) , "', '" ) , "cap" ) ,
} ,
} ,
2023-01-03 15:03:23 +00:00
{
Name : "InvalidPKCEChallengeMethod" ,
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "client-bad-pkce-mode" ,
Secret : MustDecodeSecret ( "$plaintext$a-secret" ) ,
Policy : policyTwoFactor ,
RedirectURIs : [ ] string {
"https://google.com" ,
} ,
PKCEChallengeMethod : "abc" ,
} ,
} ,
Errors : [ ] string {
fmt . Sprintf ( errFmtOIDCClientInvalidPKCEChallengeMethod , "client-bad-pkce-mode" , "abc" ) ,
} ,
} ,
{
Name : "InvalidPKCEChallengeMethodLowerCaseS256" ,
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "client-bad-pkce-mode-s256" ,
Secret : MustDecodeSecret ( "$plaintext$a-secret" ) ,
Policy : policyTwoFactor ,
RedirectURIs : [ ] string {
"https://google.com" ,
} ,
PKCEChallengeMethod : "s256" ,
} ,
} ,
Errors : [ ] string {
fmt . Sprintf ( errFmtOIDCClientInvalidPKCEChallengeMethod , "client-bad-pkce-mode-s256" , "s256" ) ,
} ,
} ,
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" ,
2022-10-20 02:16:36 +00:00
IssuerPrivateKey : MustParseRSAPrivateKey ( testKey1 ) ,
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" ,
2022-10-20 02:16:36 +00:00
IssuerPrivateKey : MustParseRSAPrivateKey ( testKey1 ) ,
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" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$good_secret" ) ,
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 )
2022-02-28 03:15:01 +00:00
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , "identity_providers: oidc: client 'good_id': option 'scopes' must only have the values 'openid', 'email', 'profile', 'groups', 'offline_access' but one option is configured as 'bad_scope'" )
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" ,
2022-10-20 02:16:36 +00:00
IssuerPrivateKey : MustParseRSAPrivateKey ( testKey1 ) ,
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" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$good_secret" ) ,
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 )
2022-02-28 03:15:01 +00:00
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , "identity_providers: oidc: client 'good_id': option 'grant_types' must only have the values 'implicit', 'refresh_token', 'authorization_code', 'password', 'client_credentials' but one option is configured as 'bad_grant_type'" )
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" ,
2022-10-20 02:16:36 +00:00
IssuerCertificateChain : MustParseX509CertificateChain ( testCert1 ) ,
IssuerPrivateKey : MustParseRSAPrivateKey ( testKey1 ) ,
2022-10-02 02:07:40 +00:00
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "good_id" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$good_secret" ) ,
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" ,
2022-10-20 02:16:36 +00:00
IssuerCertificateChain : MustParseX509CertificateChain ( testCert1 ) ,
IssuerPrivateKey : MustParseRSAPrivateKey ( testKey2 ) ,
2022-10-02 02:07:40 +00:00
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "good_id" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$good_secret" ) ,
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 )
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , "identity_providers: oidc: option 'issuer_private_key' does not appear to be the private key the certificate provided by option 'issuer_certificate_chain'" )
}
2022-10-20 02:16:36 +00:00
func TestShouldRaiseErrorOnKeySizeTooSmall ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := & schema . IdentityProvidersConfiguration {
OIDC : & schema . OpenIDConnectConfiguration {
HMACSecret : "rLABDrx87et5KvRHVUgTm3pezWWd8LMN" ,
IssuerPrivateKey : MustParseRSAPrivateKey ( testKey3 ) ,
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "good_id" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$good_secret" ) ,
2022-10-20 02:16:36 +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 )
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , "identity_providers: oidc: option 'issuer_private_key' must be an RSA private key with 2048 bits or more but it only has 1024 bits" )
}
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 TestShouldRaiseErrorWhenOIDCClientConfiguredWithBadResponseModes ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := & schema . IdentityProvidersConfiguration {
OIDC : & schema . OpenIDConnectConfiguration {
HMACSecret : "rLABDrx87et5KvRHVUgTm3pezWWd8LMN" ,
2022-10-20 02:16:36 +00:00
IssuerPrivateKey : MustParseRSAPrivateKey ( testKey1 ) ,
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" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$good_secret" ) ,
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" ,
ResponseModes : [ ] string { "bad_responsemode" } ,
RedirectURIs : [ ] string {
"https://google.com/callback" ,
} ,
} ,
} ,
} ,
}
ValidateIdentityProviders ( config , validator )
require . Len ( t , validator . Errors ( ) , 1 )
2022-02-28 03:15:01 +00:00
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , "identity_providers: oidc: client 'good_id': option 'response_modes' must only have the values 'form_post', 'query', 'fragment' but one option is configured as 'bad_responsemode'" )
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-10 04:56:33 +00:00
func TestShouldRaiseErrorWhenOIDCClientConfiguredWithBadUserinfoAlg ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := & schema . IdentityProvidersConfiguration {
OIDC : & schema . OpenIDConnectConfiguration {
HMACSecret : "rLABDrx87et5KvRHVUgTm3pezWWd8LMN" ,
2022-10-20 02:16:36 +00:00
IssuerPrivateKey : MustParseRSAPrivateKey ( testKey1 ) ,
2021-07-10 04:56:33 +00:00
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "good_id" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$good_secret" ) ,
2021-07-10 04:56:33 +00:00
Policy : "two_factor" ,
UserinfoSigningAlgorithm : "rs256" ,
RedirectURIs : [ ] string {
"https://google.com/callback" ,
} ,
} ,
} ,
} ,
}
ValidateIdentityProviders ( config , validator )
require . Len ( t , validator . Errors ( ) , 1 )
2022-02-28 03:15:01 +00:00
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , "identity_providers: oidc: client 'good_id': option 'userinfo_signing_algorithm' must be one of 'none, RS256' but it is configured as 'rs256'" )
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" ,
2022-10-20 02:16:36 +00:00
IssuerPrivateKey : MustParseRSAPrivateKey ( testKey1 ) ,
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" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$good_secret" ) ,
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" ,
2022-10-20 02:16:36 +00:00
IssuerPrivateKey : MustParseRSAPrivateKey ( testKey1 ) ,
2021-07-15 11:02:03 +00:00
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "client-with-invalid-secret" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$a-secret" ) ,
2021-07-15 11:02:03 +00:00
Public : true ,
Policy : "two_factor" ,
RedirectURIs : [ ] string {
"https://localhost" ,
} ,
} ,
{
ID : "client-with-bad-redirect-uri" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$a-secret" ) ,
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 )
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , fmt . Sprintf ( errFmtOIDCClientPublicInvalidSecret , "client-with-invalid-secret" ) )
assert . EqualError ( t , validator . Errors ( ) [ 1 ] , fmt . Sprintf ( errFmtOIDCClientRedirectURIPublic , "client-with-bad-redirect-uri" , oauth2InstalledApp ) )
}
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" ,
2022-10-20 02:16:36 +00:00
IssuerPrivateKey : MustParseRSAPrivateKey ( testKey1 ) ,
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 )
}
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 TestValidateIdentityProvidersShouldSetDefaultValues ( t * testing . T ) {
2022-11-23 23:16:23 +00:00
timeDay := time . Hour * 24
2021-05-04 22:06:05 +00:00
validator := schema . NewStructValidator ( )
config := & schema . IdentityProvidersConfiguration {
OIDC : & schema . OpenIDConnectConfiguration {
HMACSecret : "rLABDrx87et5KvRHVUgTm3pezWWd8LMN" ,
2022-10-20 02:16:36 +00:00
IssuerPrivateKey : MustParseRSAPrivateKey ( testKey1 ) ,
2021-05-04 22:06:05 +00:00
Clients : [ ] schema . OpenIDConnectClientConfiguration {
{
ID : "a-client" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$a-client-secret" ) ,
2021-05-04 22:06:05 +00:00
RedirectURIs : [ ] string {
"https://google.com" ,
} ,
2022-11-23 23:16:23 +00:00
ConsentPreConfiguredDuration : & timeDay ,
2021-05-04 22:06:05 +00:00
} ,
{
2021-07-10 04:56:33 +00:00
ID : "b-client" ,
Description : "Normal Description" ,
2022-10-20 03:21:45 +00:00
Secret : MustDecodeSecret ( "$plaintext$b-client-secret" ) ,
2021-08-03 09:55:21 +00:00
Policy : policyOneFactor ,
2021-07-10 04:56:33 +00:00
UserinfoSigningAlgorithm : "RS256" ,
2021-05-04 22:06:05 +00:00
RedirectURIs : [ ] string {
"https://google.com" ,
} ,
Scopes : [ ] string {
"groups" ,
} ,
GrantTypes : [ ] string {
"refresh_token" ,
} ,
ResponseTypes : [ ] string {
"token" ,
"code" ,
} ,
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
ResponseModes : [ ] string {
"form_post" ,
"fragment" ,
} ,
2021-05-04 22:06:05 +00:00
} ,
2022-11-23 23:16:23 +00:00
{
ID : "c-client" ,
Secret : MustDecodeSecret ( "$plaintext$a-client-secret" ) ,
RedirectURIs : [ ] string {
"https://google.com" ,
} ,
ConsentMode : "implicit" ,
} ,
{
ID : "d-client" ,
Secret : MustDecodeSecret ( "$plaintext$a-client-secret" ) ,
RedirectURIs : [ ] string {
"https://google.com" ,
} ,
ConsentMode : "explicit" ,
} ,
{
ID : "e-client" ,
Secret : MustDecodeSecret ( "$plaintext$a-client-secret" ) ,
RedirectURIs : [ ] string {
"https://google.com" ,
} ,
ConsentMode : "pre-configured" ,
} ,
2021-05-04 22:06:05 +00:00
} ,
} ,
}
ValidateIdentityProviders ( config , validator )
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
assert . Len ( t , validator . Warnings ( ) , 0 )
2021-05-04 22:06:05 +00:00
assert . Len ( t , validator . Errors ( ) , 0 )
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
// Assert Clients[0] Policy is set to the default, and the default doesn't override Clients[1]'s Policy.
2021-08-03 09:55:21 +00:00
assert . Equal ( t , policyTwoFactor , config . OIDC . Clients [ 0 ] . Policy )
assert . Equal ( t , policyOneFactor , config . OIDC . Clients [ 1 ] . Policy )
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-08-03 09:55:21 +00:00
assert . Equal ( t , "none" , config . OIDC . Clients [ 0 ] . UserinfoSigningAlgorithm )
assert . Equal ( t , "RS256" , config . OIDC . Clients [ 1 ] . UserinfoSigningAlgorithm )
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
// Assert Clients[0] Description is set to the Clients[0] ID, and Clients[1]'s Description is not overridden.
2021-05-04 22:06:05 +00:00
assert . Equal ( t , config . OIDC . Clients [ 0 ] . ID , config . OIDC . Clients [ 0 ] . Description )
assert . Equal ( t , "Normal Description" , config . OIDC . Clients [ 1 ] . Description )
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
// Assert Clients[0] ends up configured with the default Scopes.
2021-05-04 22:06:05 +00:00
require . Len ( t , config . OIDC . Clients [ 0 ] . Scopes , 4 )
assert . Equal ( t , "openid" , config . OIDC . Clients [ 0 ] . Scopes [ 0 ] )
assert . Equal ( t , "groups" , config . OIDC . Clients [ 0 ] . Scopes [ 1 ] )
assert . Equal ( t , "profile" , config . OIDC . Clients [ 0 ] . Scopes [ 2 ] )
assert . Equal ( t , "email" , config . OIDC . Clients [ 0 ] . Scopes [ 3 ] )
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
// Assert Clients[1] ends up configured with the configured Scopes and the openid Scope.
2021-05-04 22:06:05 +00:00
require . Len ( t , config . OIDC . Clients [ 1 ] . Scopes , 2 )
assert . Equal ( t , "groups" , config . OIDC . Clients [ 1 ] . Scopes [ 0 ] )
assert . Equal ( t , "openid" , config . OIDC . Clients [ 1 ] . Scopes [ 1 ] )
2022-11-23 23:16:23 +00:00
// Assert Clients[0] ends up configured with the correct consent mode.
require . NotNil ( t , config . OIDC . Clients [ 0 ] . ConsentPreConfiguredDuration )
assert . Equal ( t , time . Hour * 24 , * config . OIDC . Clients [ 0 ] . ConsentPreConfiguredDuration )
assert . Equal ( t , "pre-configured" , config . OIDC . Clients [ 0 ] . ConsentMode )
// Assert Clients[1] ends up configured with the correct consent mode.
assert . Nil ( t , config . OIDC . Clients [ 1 ] . ConsentPreConfiguredDuration )
assert . Equal ( t , "explicit" , config . OIDC . Clients [ 1 ] . ConsentMode )
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
// Assert Clients[0] ends up configured with the default GrantTypes.
require . Len ( t , config . OIDC . Clients [ 0 ] . GrantTypes , 2 )
assert . Equal ( t , "refresh_token" , config . OIDC . Clients [ 0 ] . GrantTypes [ 0 ] )
assert . Equal ( t , "authorization_code" , config . OIDC . Clients [ 0 ] . GrantTypes [ 1 ] )
// Assert Clients[1] ends up configured with only the configured GrantTypes.
2021-05-04 22:06:05 +00:00
require . Len ( t , config . OIDC . Clients [ 1 ] . GrantTypes , 1 )
assert . Equal ( t , "refresh_token" , config . OIDC . Clients [ 1 ] . GrantTypes [ 0 ] )
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
// Assert Clients[0] ends up configured with the default ResponseTypes.
require . Len ( t , config . OIDC . Clients [ 0 ] . ResponseTypes , 1 )
assert . Equal ( t , "code" , config . OIDC . Clients [ 0 ] . ResponseTypes [ 0 ] )
// Assert Clients[1] ends up configured only with the configured ResponseTypes.
2021-05-04 22:06:05 +00:00
require . Len ( t , config . OIDC . Clients [ 1 ] . ResponseTypes , 2 )
assert . Equal ( t , "token" , config . OIDC . Clients [ 1 ] . ResponseTypes [ 0 ] )
assert . Equal ( t , "code" , config . OIDC . Clients [ 1 ] . ResponseTypes [ 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
// Assert Clients[0] ends up configured with the default ResponseModes.
require . Len ( t , config . OIDC . Clients [ 0 ] . ResponseModes , 3 )
assert . Equal ( t , "form_post" , config . OIDC . Clients [ 0 ] . ResponseModes [ 0 ] )
assert . Equal ( t , "query" , config . OIDC . Clients [ 0 ] . ResponseModes [ 1 ] )
assert . Equal ( t , "fragment" , config . OIDC . Clients [ 0 ] . ResponseModes [ 2 ] )
// Assert Clients[1] ends up configured only with the configured ResponseModes.
require . Len ( t , config . OIDC . Clients [ 1 ] . ResponseModes , 2 )
assert . Equal ( t , "form_post" , config . OIDC . Clients [ 1 ] . ResponseModes [ 0 ] )
assert . Equal ( t , "fragment" , config . OIDC . Clients [ 1 ] . ResponseModes [ 1 ] )
assert . Equal ( t , false , config . OIDC . EnableClientDebugMessages )
assert . Equal ( t , time . Hour , config . OIDC . AccessTokenLifespan )
assert . Equal ( t , time . Minute , config . OIDC . AuthorizeCodeLifespan )
assert . Equal ( t , time . Hour , config . OIDC . IDTokenLifespan )
assert . Equal ( t , time . Minute * 90 , config . OIDC . RefreshTokenLifespan )
2022-11-23 23:16:23 +00:00
assert . Equal ( t , "implicit" , config . OIDC . Clients [ 2 ] . ConsentMode )
assert . Nil ( t , config . OIDC . Clients [ 2 ] . ConsentPreConfiguredDuration )
assert . Equal ( t , "explicit" , config . OIDC . Clients [ 3 ] . ConsentMode )
assert . Nil ( t , config . OIDC . Clients [ 3 ] . ConsentPreConfiguredDuration )
assert . Equal ( t , "pre-configured" , config . OIDC . Clients [ 4 ] . ConsentMode )
assert . Equal ( t , schema . DefaultOpenIDConnectClientConfiguration . ConsentPreConfiguredDuration , config . OIDC . Clients [ 4 ] . ConsentPreConfiguredDuration )
2021-05-04 22:06:05 +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 ) {
conf := 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" ,
2022-11-21 00:52:27 +00:00
oauth2InstalledApp ,
2022-01-21 11:05:53 +00:00
} ,
}
t . Run ( "public" , func ( t * testing . T ) {
validator := schema . NewStructValidator ( )
conf . Public = true
validateOIDCClientRedirectURIs ( conf , validator )
assert . Len ( t , validator . Warnings ( ) , 0 )
assert . Len ( t , validator . Errors ( ) , 0 )
} )
t . Run ( "not public" , func ( t * testing . T ) {
validator := schema . NewStructValidator ( )
conf . Public = false
validateOIDCClientRedirectURIs ( conf , validator )
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 {
2022-11-21 00:52:27 +00:00
errors . New ( "identity_providers: oidc: 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
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
}
}
2022-10-20 02:16:36 +00:00
func MustParseRSAPrivateKey ( data string ) * rsa . PrivateKey {
block , _ := pem . Decode ( [ ] byte ( data ) )
if block == nil || block . Bytes == nil || len ( block . Bytes ) == 0 {
panic ( "not pem encoded" )
}
if block . Type != "RSA PRIVATE KEY" {
panic ( "not private key" )
}
key , err := x509 . ParsePKCS1PrivateKey ( block . Bytes )
if err != nil {
panic ( err )
}
return key
}
func MustParseX509CertificateChain ( data string ) schema . X509CertificateChain {
chain , err := schema . NewX509CertificateChain ( data )
if err != nil {
panic ( err )
}
return * chain
}
2022-10-02 02:07:40 +00:00
var (
testCert1 = `
-- -- - BEGIN CERTIFICATE -- -- -
MIIC5jCCAc6gAwIBAgIRAJZ + 6 KrHw95zIDgm2arCTCgwDQYJKoZIhvcNAQELBQAw
EzERMA8GA1UEChMIQXV0aGVsaWEwHhcNMjIwOTA4MDIyNDQyWhcNMjMwOTA4MDIy
NDQyWjATMREwDwYDVQQKEwhBdXRoZWxpYTCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAMAE7muDAJtLsV3WgOpjrZ1JD1RlhuSOa3V + 4 zo2NYFQSdZW18SZ
fYYgUwLOleEy3VQ3N9MEFh / rWNHYHdsBjDvz / Q1EzAlXqthGd0Sic / UDYtrahrko
jCSkZCQ5YVO9ivMRth6XdUlu7RHVYY3aSOWPx2wiw9cdN + e4p73W6KwyzT7ezbUD
0 Nng0Z7CNQTLHv3LBsLUODc4aVOvp2B4aAaw6cn990buKMvUuo2ge9gh0c5gIOM5
dU7xOGAt7RzwCIHnG4CGAWPFuuS215ZeelgQr / 9 / fhtzDqSuBZw5f10vXnAyBwei
vN6Kffj2RXB + koFwBguT84A6cfmxWllGNF0CAwEAAaM1MDMwDgYDVR0PAQH / BAQD
AgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB / wQCMAAwDQYJKoZIhvcN
AQELBQADggEBAFvORjj7RGoIc3q0fv6QjuncZ0Mu1 / 24 O0smCr6tq5d6RQBRpb1M
jEsbTMLZErrHbyw / DWC75eJhW6T + 6 HiVTo6brBXkmDL + QGkLgRNOkZla6cnmIpmL
bf9iPmmcThscQERgYZzNg19zqK8JAQU / 6 PgU / N6OXTL / mQQoB972ET9dUl7lGx1Q
2 l8XBe8t4QTp4t1xd3c4azxWvFNpzWBjC5eBWiVHLJmFXr4xpcnPFYFETOkvEqwt
pMQ2x895BoLrep6b + g0xeF4pmmIQwA9KrUVr ++ gpYaRzytaOIYwcIPMzt9iLWKQe
6 ZSOrTVi8pPugYXp + LhVk / WI7r8EWtyADu0 =
-- -- - END CERTIFICATE -- -- - `
testKey1 = `
-- -- - BEGIN RSA PRIVATE KEY -- -- -
MIIEpAIBAAKCAQEAwATua4MAm0uxXdaA6mOtnUkPVGWG5I5rdX7jOjY1gVBJ1lbX
xJl9hiBTAs6V4TLdVDc30wQWH + tY0dgd2wGMO / P9DUTMCVeq2EZ3RKJz9QNi2tqG
uSiMJKRkJDlhU72K8xG2Hpd1SW7tEdVhjdpI5Y / HbCLD1x0357invdborDLNPt7N
tQPQ2eDRnsI1BMse / csGwtQ4NzhpU6 + nYHhoBrDpyf33Ru4oy9S6jaB72CHRzmAg
4 zl1TvE4YC3tHPAIgecbgIYBY8W65LbXll56WBCv / 39 + G3MOpK4FnDl / XS9ecDIH
B6K83op9 + PZFcH6SgXAGC5PzgDpx + bFaWUY0XQIDAQABAoIBAQClcdpHcglMxOwe
kRpkWdwWAAQgUJXoSbnW86wu1NRHBfmInyyrrSBVN3aunXbQITZIQIdt3kB94haW
P6KBt5Svd2saSqOOjSWb0SMkVOCaQ / + h19VqpcASNj4 + Y94y + 8 ZD5ofHVfJtghDr
Y7H5OhHDEZ3e0xlwODGaCyUkUY4KBv / oIlILoh4phbDYHkZH8AzDnEiyVE1JAWlN
voAQysgSU7eEnNCi1S07jl5bY + MD3XpJkAfQsJYhqYT / qetStZ12PuXjpbIr3y53
qjCrKeWTyDN + gOznyIGuiR6nvXeQAw / o9hZiah4RuHXTPs / 3 GAcRXcuMR0pbgJ + B
yfX6eLK1AoGBAPKkJKPYJD2NHukAelNbT2OgeDIgJmfOIvLa73 / x2hXvWwa4VwIC
POuKXtT / a02J4pYMGlaKXfHgLmaW2HPObOIjpxqgRIswsiKS1AbaDtkWnhaS1 / SJ
oZ7Fk8DdX + 1 QT4J / fj / 2 uxRT0GhXdMxDpK7ekpmRE + APPCGhmOMgmWszAoGBAMqX
Ts1RdGWgDxLi15rDqdqRBARJG7Om / xC2voXVmbAb4Q + QoNrNeiIAM2usuhrVuj5V
c16m9fxswRNYqQBYyShDi5wp5a8UjfqDpzJdku2bmrBaL + XVq8PY + oTK6KS3ss8U
CGQ8P6Phz5JGavn / nDMRZ4EwEWqbEMUqJAJlpmIvAoGAQ9Wj8LJyn0qew6FAkaFL
dpzcPZdDZW35009l + a0RvWQnXJ + Yo5UglvEeRgoKY6kS0cQccOlKDl8QWdn + NZIW
WrqA8y6vOwKoKoZGBIxd7k8mb0UqXtFDf / HYtuis8tmrAN7H2vYNo0czUphwrNKU
bdcHwSsQFWns87IL3iO1AIUCgYBzmBX8jOePPN6c9hXzVoVKEshp8ZT + 0 uBilwLq
tk / 07 lNiYDGH5woy8E5mt62QtjaIbpVfgoCEwUEBWutDKWXNtYypVDabyWyhbhEu
abn2HX0L9smxqFNTcjCvKF / J7I74HQQUvVPKnIOlgMx1TOXBNcMLMXQekc / lz / + v
5 nQjPQKBgQDjdJABeiy9tU0tzLWUVc5QoQKnlfSJoFLis46REb1yHwU9OjTc05Wx
5 lAXdTjDmnelDdGWNWHjWOiKSkTxhvQD3jXriI5y8Sdxe3zS3ikYvbMbi97GJz0O
5 oyNJo6 / froW1dLkJJWR8hg2PQbtoOo6l9HHSd91BnJJ4qFbq9ZrXQ ==
-- -- - END RSA PRIVATE KEY -- -- - `
testKey2 = `
-- -- - BEGIN RSA PRIVATE KEY -- -- -
MIIEpAIBAAKCAQEA6z1LOg1ZCqb0lytXWZ + MRBpMHEXOoTOLYgfZXt1IYyE3Z758
cyalk0NYQhY5cZDsXPYWPvAHiPMUxutWkoxFwby56S + AbIMa3 / Is + ILrHRJs8Exn
ZkpyrYFxPX12app2kErdmAkHSx0Z5 / kuXiz96PHs8S8 / ZbyZolLHzdfLtSzjvRm5
Zue5iFzsf19NJz5CIBfv8g5lRwtE8wNJoRSpn1xq7fqfuA0weDNFPzjlNWRLy6aa
rK7qJexRkmkCs4sLgyl + 9 NODYJpvmN8E1yhyC27E0joI6rBFVW7Ihv + cSPCdDzGp
EWe81x3AeqAa3mjVqkiq4u4Z2i8JDgBaPboqJwIDAQABAoIBAAFdLZ58jVOefDSU
L8F5R1rtvBs93GDa56f926jNJ6pLewLC + / 2 + 757 W + SAI + PRLntM7Kg3bXm / Q2QH +
Q1Y + MflZmspbWCdI61L5GIGoYKyeers59i + FpvySj5GHtLQRiTZ0 + Kv1AXHSDWBm
9 XneUOqU3IbZe0ifu1RRno72 / VtjkGXbW8Mkkw + ohyGbIeTx / 0 / JQ6sSNZTT3Vk7
8i 4 IXptq3HSF0 / vqZuah8rShoeNq72pD1YLM9YPdL5by1QkDLnqATDiCpLBTCaNV
I8sqYEun + HYbQzBj8ZACG2JVZpEEidONWQHw5BPWO95DSZYrVnEkuCqeH + u5vYt7
CHuJ3AECgYEA + W3v5z + j91w1VPHS0VB3SCDMouycAMIUnJPAbt + 0 LPP0scUFsBGE
hPAKddC54pmMZRQ2KIwBKiyWfCrJ8Xz8Yogn7fJgmwTHidJBr2WQpIEkNGlK3Dzi
jXL2sh0yC7sHvn0DqiQ79l / e7yRbSnv2wrTJEczOOH2haD7 / tBRyCYECgYEA8W + q
E9YyGvEltnPFaOxofNZ8LHVcZSsQI5b6fc0iE7fjxFqeXPXEwGSOTwqQLQRiHn9b
CfPmIG4Vhyq0otVmlPvUnfBZ2OK + tl5X2 / mQFO3ROMdvpi0KYa994uqfJdSTaqLn
jjoKFB906UFHnDQDLZUNiV1WwnkTglgLc + xrd6cCgYEAqqthyv6NyBTM3Tm2gcio
Ra9Dtntl51LlXZnvwy3IkDXBCd6BHM9vuLKyxZiziGx + Vy90O1xI872cnot8sINQ
Am + dur / tAEVN72zxyv0Y8qb2yfH96iKy9gxi5s75TnOEQgAygLnYWaWR2lorKRUX
bHTdXBOiS58S0UzCFEslGIECgYBqkO4SKWYeTDhoKvuEj2yjRYyzlu28XeCWxOo1
otiauX0YSyNBRt2cSgYiTzhKFng0m + QUJYp63 / wymB / 5 C5Zmxi0XtWIDADpLhqLj
HmmBQ2Mo26alQ5YkffBju0mZyhVzaQop1eZi8WuKFV1FThPlB7hc3E0SM5zv2Grd
tQnOWwKBgQC40yZY0PcjuILhy + sIc0Wvh7LUA7taSdTye149kRvbvsCDN7Jh75lM
USjhLXY0Nld2zBm9r8wMb81mXH29uvD + tDqqsICvyuKlA / tyzXR + QTr7dCVKVwu0
1 YjCJ36UpTsLre2f8nOSLtNmRfDPtbOE2mkOoO9dD9UU0XZwnvn9xw ==
-- -- - END RSA PRIVATE KEY -- -- - `
2022-10-20 02:16:36 +00:00
testKey3 = ` -- -- - BEGIN RSA PRIVATE KEY -- -- -
MIICXgIBAAKBgQDBi7fdmUmlpWklpgAvNUdhDrpsDVqAHuEzVApK6f6ohYAi0 / q2
+ YmOwyPKDSrOc6Sy1myJtV3FbZGvYaQhnokc4bnkS9DH0lY + 6 Hk2vKps5PrhRY / q
1 EjnfwXvzhAzb25rGFwKcSvfvndMTVvxgqXVob + 3 pRt9maD6HFHAh2 / NCQIDAQAB
AoGACT2bfLgJ3R / FomeHkLlxe //RBMGqdX2D8QhtKWB8qR0engsS6FOHrspAVjBE
v / Cjh2pXake / f2KY1w / JX1WLZEFXja2RFPeeDiiC / 4 S7pKCySUVeHO9rQ4SY5Frg
/ s / QWWtmq7 + 1i u2DXhdGJA6fIurzSoDgUXo3NGFCYqIFaAECQQDUi9AAgEljmc2q
dAUQD0KNTcJFkpTafhfPiYc2GT1vS / bArtXRmvJmbIiRfVuGbM8z5ES7JGd5FyYL
i2WCCzUBAkEA6R14GVhN8NIPWEUrzjgOvjKlc2ZHskT3dYb3djpm69TK7GjLtHyq
qO7l4VJowsXI + o / 6 YucagF6 + rH0O0VrwCQJBAM8twYDbi63knA8MrGqtFUg7haTf
bu1Tf84y1nOrQrEcMNg9E / sOuD2SicSXlwF / SrHgTgbFQ39LSzBxnm6WkgECQQCh
AQmB98tdGLggbyXiODV2h + Rd37aFGb0QHzerIIsVNtMwlPCcp733D4kWJqTUYWZ +
KBL3XEahgs6Os5EYZ4aBAkEAjKE + 2 / nBYUdHVusjMXeNsE5rqwJND5zvYzmToG7 +
xhv4RUAe4dHL4IDQoQRjhr3Nw + JYvtzBx0Iq / 178 xMnGKg ==
-- -- - END RSA PRIVATE KEY -- -- - `
)