mirror of
https://github.com/authelia/authelia.git
synced 2026-10-28 09:34:52 +08:00
209 lines
7.6 KiB
Go
209 lines
7.6 KiB
Go
// SPDX-FileCopyrightText: 2026 Authelia
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"strings"
|
|
|
|
"github.com/go-crypt/crypt/algorithm"
|
|
"github.com/go-crypt/crypt/algorithm/pbkdf2"
|
|
|
|
"github.com/authelia/authelia/v4/internal/configuration/schema"
|
|
"github.com/authelia/authelia/v4/internal/oidc"
|
|
"github.com/authelia/authelia/v4/internal/random"
|
|
)
|
|
|
|
// OpenIDConnectConformanceSuiteBuilder builds an OpenIDConnectConformanceSuite.
|
|
type OpenIDConnectConformanceSuiteBuilder struct {
|
|
brand string
|
|
name string
|
|
friendly string
|
|
certification bool
|
|
version string
|
|
consent string
|
|
policy string
|
|
suiteURL *url.URL
|
|
autheliaURL *url.URL
|
|
}
|
|
|
|
// Build returns the OpenIDConnectConformanceSuite for this builder.
|
|
func (b *OpenIDConnectConformanceSuiteBuilder) Build() OpenIDConnectConformanceSuite {
|
|
var (
|
|
apiname, namePrefix, clientIDPrefix, descriptionSuffix string
|
|
variant *OpenIDConnectConformanceSuitePlanVariant
|
|
)
|
|
|
|
if b.certification {
|
|
namePrefix = "conformance-"
|
|
clientIDPrefix = "conformance-certification"
|
|
descriptionSuffix = "Certification Profile"
|
|
} else {
|
|
clientIDPrefix = "conformance-test"
|
|
descriptionSuffix = "Test Profile"
|
|
}
|
|
|
|
aliasSuffix := fmt.Sprintf("%s-%s", strings.ReplaceAll(strings.ToLower(b.name), ".", "-"), b.brand+strings.ReplaceAll(strings.ToLower(b.version), ".", ""))
|
|
|
|
name := fmt.Sprintf("%s%s", namePrefix, b.name)
|
|
description := fmt.Sprintf("Authelia %s %s %s", b.version, b.friendly, descriptionSuffix)
|
|
|
|
switch name {
|
|
case suiteConformanceBasic, suiteConformanceBasicFormPost, suiteConformanceHybrid, suiteConformanceHybridFormPost, suiteConformanceImplicit, suiteConformanceImplicitFormPost:
|
|
variant = &OpenIDConnectConformanceSuitePlanVariant{
|
|
ServerMetadata: "discovery",
|
|
ClientRegistration: "static_client",
|
|
}
|
|
}
|
|
|
|
switch name {
|
|
case "conformance-config":
|
|
apiname = "oidcc-config-certification-test-plan"
|
|
case suiteConformanceBasic:
|
|
apiname = "oidcc-basic-certification-test-plan"
|
|
case suiteConformanceBasicFormPost:
|
|
apiname = "oidcc-formpost-basic-certification-test-plan"
|
|
case suiteConformanceHybrid:
|
|
apiname = "oidcc-hybrid-certification-test-plan"
|
|
case suiteConformanceHybridFormPost:
|
|
apiname = "oidcc-formpost-hybrid-certification-test-plan"
|
|
case suiteConformanceImplicit:
|
|
apiname = "oidcc-implicit-certification-test-plan"
|
|
case suiteConformanceImplicitFormPost:
|
|
apiname = "oidcc-formpost-implicit-certification-test-plan"
|
|
}
|
|
|
|
suite := OpenIDConnectConformanceSuite{
|
|
Name: name,
|
|
Plan: OpenIDConnectConformanceSuitePlan{
|
|
Name: apiname,
|
|
Variant: variant,
|
|
Alias: fmt.Sprintf("%s%s", namePrefix, aliasSuffix),
|
|
Publish: "summary",
|
|
Description: description,
|
|
Server: OpenIDConnectConformanceSuitePlanServer{
|
|
DiscoveryURL: b.autheliaURL.JoinPath(".well-known/openid-configuration").String(),
|
|
},
|
|
},
|
|
}
|
|
|
|
if b.suiteURL == nil {
|
|
return suite
|
|
}
|
|
|
|
r := random.New()
|
|
|
|
secret := r.StringCustom(80, random.CharSetAlphaNumeric)
|
|
secretAlternate := r.StringCustom(80, random.CharSetAlphaNumeric)
|
|
secretPost := r.StringCustom(80, random.CharSetAlphaNumeric)
|
|
|
|
suite.Plan.Client = &OpenIDConnectConformanceSuitePlanClient{
|
|
ID: fmt.Sprintf("%s-%s", clientIDPrefix, aliasSuffix),
|
|
Secret: secret,
|
|
}
|
|
|
|
suite.Plan.ClientAlternate = &OpenIDConnectConformanceSuitePlanClient{
|
|
ID: fmt.Sprintf("%s-%s-alt", clientIDPrefix, aliasSuffix),
|
|
Secret: secretAlternate,
|
|
}
|
|
|
|
suite.Plan.ClientSecretPost = &OpenIDConnectConformanceSuitePlanClient{
|
|
ID: fmt.Sprintf("%s-%s-post", clientIDPrefix, aliasSuffix),
|
|
Secret: secretPost,
|
|
}
|
|
|
|
var (
|
|
grantTypes []string
|
|
responseTypes []string
|
|
responseModes []string
|
|
)
|
|
|
|
switch b.name {
|
|
case "implicit", suiteNameImplicitFormPost:
|
|
grantTypes = []string{oidc.GrantTypeAuthorizationCode, oidc.GrantTypeImplicit, oidc.GrantTypeRefreshToken}
|
|
responseTypes = []string{oidc.ResponseTypeAuthorizationCodeFlow, oidc.ResponseTypeImplicitFlowIDToken, oidc.ResponseTypeImplicitFlowToken, oidc.ResponseTypeImplicitFlowBoth}
|
|
case "hybrid", suiteNameHybridFormPost:
|
|
grantTypes = []string{oidc.GrantTypeAuthorizationCode, oidc.GrantTypeImplicit, oidc.GrantTypeRefreshToken}
|
|
responseTypes = []string{oidc.ResponseTypeAuthorizationCodeFlow, oidc.ResponseTypeHybridFlowIDToken, oidc.ResponseTypeHybridFlowToken, oidc.ResponseTypeHybridFlowBoth}
|
|
default:
|
|
grantTypes = []string{oidc.GrantTypeAuthorizationCode, oidc.GrantTypeRefreshToken}
|
|
responseTypes = []string{oidc.ResponseTypeAuthorizationCodeFlow}
|
|
}
|
|
|
|
switch b.name {
|
|
case suiteNameBasicFormPost, suiteNameHybridFormPost, suiteNameImplicitFormPost:
|
|
responseModes = []string{oidc.ResponseModeFormPost, oidc.ResponseModeFormPostJWT}
|
|
default:
|
|
responseModes = []string{oidc.ResponseModeQuery, oidc.ResponseModeQueryJWT}
|
|
}
|
|
|
|
suite.Clients = []schema.IdentityProvidersOpenIDConnectClient{
|
|
{
|
|
ID: suite.Plan.Client.ID,
|
|
Name: description,
|
|
Secret: MustHash(suite.Plan.Client.Secret),
|
|
RedirectURIs: []string{b.suiteURL.JoinPath("test", "a", suite.Plan.Alias, "callback").String()},
|
|
AuthorizationPolicy: b.policy,
|
|
ConsentMode: b.consent,
|
|
Public: false,
|
|
Scopes: []string{oidc.ScopeOpenID, oidc.ScopeOfflineAccess, oidc.ScopeProfile, oidc.ScopeEmail, oidc.ScopePhone, oidc.ScopeAddress, "all"},
|
|
ResponseTypes: responseTypes,
|
|
GrantTypes: grantTypes,
|
|
ResponseModes: responseModes,
|
|
TokenEndpointAuthMethod: oidc.ClientAuthMethodClientSecretBasic,
|
|
RequestObjectSigningAlg: oidc.SigningAlgNone,
|
|
},
|
|
{
|
|
ID: suite.Plan.ClientAlternate.ID,
|
|
Name: fmt.Sprintf("%s (Alternate)", description),
|
|
Secret: MustHash(suite.Plan.ClientAlternate.Secret),
|
|
RedirectURIs: []string{b.suiteURL.JoinPath("test", "a", suite.Plan.Alias, "callback").String()},
|
|
AuthorizationPolicy: b.policy,
|
|
ConsentMode: b.consent,
|
|
Public: false,
|
|
Scopes: []string{oidc.ScopeOpenID, oidc.ScopeOfflineAccess, oidc.ScopeProfile, oidc.ScopeEmail, oidc.ScopePhone, oidc.ScopeAddress, "all"},
|
|
ResponseTypes: responseTypes,
|
|
GrantTypes: grantTypes,
|
|
ResponseModes: responseModes,
|
|
TokenEndpointAuthMethod: oidc.ClientAuthMethodClientSecretBasic,
|
|
RequestObjectSigningAlg: oidc.SigningAlgNone,
|
|
},
|
|
{
|
|
ID: suite.Plan.ClientSecretPost.ID,
|
|
Name: fmt.Sprintf("%s (Secret Post)", description),
|
|
Secret: MustHash(suite.Plan.ClientSecretPost.Secret),
|
|
RedirectURIs: []string{b.suiteURL.JoinPath("test", "a", suite.Plan.Alias, "callback").String()},
|
|
AuthorizationPolicy: b.policy,
|
|
ConsentMode: b.consent,
|
|
Public: false,
|
|
Scopes: []string{oidc.ScopeOpenID, oidc.ScopeOfflineAccess, oidc.ScopeProfile, oidc.ScopeEmail, oidc.ScopePhone, oidc.ScopeAddress, "all"},
|
|
ResponseTypes: responseTypes,
|
|
GrantTypes: grantTypes,
|
|
ResponseModes: responseModes,
|
|
TokenEndpointAuthMethod: oidc.ClientAuthMethodClientSecretPost,
|
|
RequestObjectSigningAlg: oidc.SigningAlgNone,
|
|
},
|
|
}
|
|
|
|
return suite
|
|
}
|
|
|
|
// MustHash returns the digest of the given value and panics if it fails.
|
|
func MustHash(value string) *schema.PasswordDigest {
|
|
hash, err := pbkdf2.New()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
var digest algorithm.Digest
|
|
|
|
if digest, err = hash.Hash(value); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return schema.NewPasswordDigest(digest)
|
|
}
|