refactor: apply godot recommendations (#2839)
parent
357c654db8
commit
1772a83190
|
@ -46,19 +46,19 @@ var hostEntries = []HostEntry{
|
||||||
{Domain: "proxy-client2.example.com", IP: "192.168.240.202"},
|
{Domain: "proxy-client2.example.com", IP: "192.168.240.202"},
|
||||||
{Domain: "proxy-client3.example.com", IP: "192.168.240.203"},
|
{Domain: "proxy-client3.example.com", IP: "192.168.240.203"},
|
||||||
|
|
||||||
// Redis Replicas
|
// Redis Replicas.
|
||||||
{Domain: "redis-node-0.example.com", IP: "192.168.240.110"},
|
{Domain: "redis-node-0.example.com", IP: "192.168.240.110"},
|
||||||
{Domain: "redis-node-1.example.com", IP: "192.168.240.111"},
|
{Domain: "redis-node-1.example.com", IP: "192.168.240.111"},
|
||||||
{Domain: "redis-node-2.example.com", IP: "192.168.240.112"},
|
{Domain: "redis-node-2.example.com", IP: "192.168.240.112"},
|
||||||
|
|
||||||
// Redis Sentinel Replicas
|
// Redis Sentinel Replicas.
|
||||||
{Domain: "redis-sentinel-0.example.com", IP: "192.168.240.120"},
|
{Domain: "redis-sentinel-0.example.com", IP: "192.168.240.120"},
|
||||||
{Domain: "redis-sentinel-1.example.com", IP: "192.168.240.121"},
|
{Domain: "redis-sentinel-1.example.com", IP: "192.168.240.121"},
|
||||||
{Domain: "redis-sentinel-2.example.com", IP: "192.168.240.122"},
|
{Domain: "redis-sentinel-2.example.com", IP: "192.168.240.122"},
|
||||||
|
|
||||||
// Kubernetes dashboard.
|
// Kubernetes dashboard.
|
||||||
{Domain: "kubernetes.example.com", IP: "192.168.240.110"},
|
{Domain: "kubernetes.example.com", IP: "192.168.240.110"},
|
||||||
// OIDC tester app
|
// OIDC tester app.
|
||||||
{Domain: "oidc.example.com", IP: "192.168.240.100"},
|
{Domain: "oidc.example.com", IP: "192.168.240.100"},
|
||||||
{Domain: "oidc-public.example.com", IP: "192.168.240.100"},
|
{Domain: "oidc-public.example.com", IP: "192.168.240.100"},
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,7 +125,7 @@ func setupSuite(cmd *cobra.Command, args []string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the .suite file
|
// Create the .suite file.
|
||||||
if err := createRunningSuiteFile(suiteName); err != nil {
|
if err := createRunningSuiteFile(suiteName); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ func NewFileUserProvider(configuration *schema.FileAuthenticationBackendConfigur
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Early check whether hashed passwords are correct for all users
|
// Early check whether hashed passwords are correct for all users.
|
||||||
err = checkPasswordHashes(database)
|
err = checkPasswordHashes(database)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
|
@ -19,7 +19,7 @@ func WithDatabase(content []byte, f func(path string)) {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer os.Remove(tmpfile.Name()) // Clean up
|
defer os.Remove(tmpfile.Name()) // Clean up.
|
||||||
|
|
||||||
if _, err := tmpfile.Write(content); err != nil {
|
if _, err := tmpfile.Write(content); err != nil {
|
||||||
tmpfile.Close()
|
tmpfile.Close()
|
||||||
|
|
|
@ -89,10 +89,10 @@ func TestEscapeSpecialCharsFromUserInput(t *testing.T) {
|
||||||
nil,
|
nil,
|
||||||
mockFactory)
|
mockFactory)
|
||||||
|
|
||||||
// No escape
|
// No escape.
|
||||||
assert.Equal(t, "xyz", ldapClient.ldapEscape("xyz"))
|
assert.Equal(t, "xyz", ldapClient.ldapEscape("xyz"))
|
||||||
|
|
||||||
// Escape
|
// Escape.
|
||||||
assert.Equal(t, "test\\,abc", ldapClient.ldapEscape("test,abc"))
|
assert.Equal(t, "test\\,abc", ldapClient.ldapEscape("test,abc"))
|
||||||
assert.Equal(t, "test\\5cabc", ldapClient.ldapEscape("test\\abc"))
|
assert.Equal(t, "test\\5cabc", ldapClient.ldapEscape("test\\abc"))
|
||||||
assert.Equal(t, "test\\2aabc", ldapClient.ldapEscape("test*abc"))
|
assert.Equal(t, "test\\2aabc", ldapClient.ldapEscape("test*abc"))
|
||||||
|
|
|
@ -9,7 +9,7 @@ type IdentityProvidersConfiguration struct {
|
||||||
|
|
||||||
// OpenIDConnectConfiguration configuration for OpenID Connect.
|
// OpenIDConnectConfiguration configuration for OpenID Connect.
|
||||||
type OpenIDConnectConfiguration struct {
|
type OpenIDConnectConfiguration struct {
|
||||||
// This secret must be 32 bytes long
|
// This secret must be 32 bytes long.
|
||||||
HMACSecret string `koanf:"hmac_secret"`
|
HMACSecret string `koanf:"hmac_secret"`
|
||||||
IssuerPrivateKey string `koanf:"issuer_private_key"`
|
IssuerPrivateKey string `koanf:"issuer_private_key"`
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ func validateFileAuthenticationBackend(configuration *schema.FileAuthenticationB
|
||||||
if configuration.Password == nil {
|
if configuration.Password == nil {
|
||||||
configuration.Password = &schema.DefaultPasswordConfiguration
|
configuration.Password = &schema.DefaultPasswordConfiguration
|
||||||
} else {
|
} else {
|
||||||
// Salt Length
|
// Salt Length.
|
||||||
switch {
|
switch {
|
||||||
case configuration.Password.SaltLength == 0:
|
case configuration.Password.SaltLength == 0:
|
||||||
configuration.Password.SaltLength = schema.DefaultPasswordConfiguration.SaltLength
|
configuration.Password.SaltLength = schema.DefaultPasswordConfiguration.SaltLength
|
||||||
|
@ -72,32 +72,32 @@ func validateFileAuthenticationBackend(configuration *schema.FileAuthenticationB
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateFileAuthenticationBackendSHA512(configuration *schema.FileAuthenticationBackendConfiguration) {
|
func validateFileAuthenticationBackendSHA512(configuration *schema.FileAuthenticationBackendConfiguration) {
|
||||||
// Iterations (time)
|
// Iterations (time).
|
||||||
if configuration.Password.Iterations == 0 {
|
if configuration.Password.Iterations == 0 {
|
||||||
configuration.Password.Iterations = schema.DefaultPasswordSHA512Configuration.Iterations
|
configuration.Password.Iterations = schema.DefaultPasswordSHA512Configuration.Iterations
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func validateFileAuthenticationBackendArgon2id(configuration *schema.FileAuthenticationBackendConfiguration, validator *schema.StructValidator) {
|
func validateFileAuthenticationBackendArgon2id(configuration *schema.FileAuthenticationBackendConfiguration, validator *schema.StructValidator) {
|
||||||
// Iterations (time)
|
// Iterations (time).
|
||||||
if configuration.Password.Iterations == 0 {
|
if configuration.Password.Iterations == 0 {
|
||||||
configuration.Password.Iterations = schema.DefaultPasswordConfiguration.Iterations
|
configuration.Password.Iterations = schema.DefaultPasswordConfiguration.Iterations
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parallelism
|
// Parallelism.
|
||||||
if configuration.Password.Parallelism == 0 {
|
if configuration.Password.Parallelism == 0 {
|
||||||
configuration.Password.Parallelism = schema.DefaultPasswordConfiguration.Parallelism
|
configuration.Password.Parallelism = schema.DefaultPasswordConfiguration.Parallelism
|
||||||
} else if configuration.Password.Parallelism < 1 {
|
} else if configuration.Password.Parallelism < 1 {
|
||||||
validator.Push(fmt.Errorf("Parallelism for argon2id must be 1 or more, you configured %d", configuration.Password.Parallelism))
|
validator.Push(fmt.Errorf("Parallelism for argon2id must be 1 or more, you configured %d", configuration.Password.Parallelism))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Memory
|
// Memory.
|
||||||
if configuration.Password.Memory == 0 {
|
if configuration.Password.Memory == 0 {
|
||||||
configuration.Password.Memory = schema.DefaultPasswordConfiguration.Memory
|
configuration.Password.Memory = schema.DefaultPasswordConfiguration.Memory
|
||||||
} else if configuration.Password.Memory < configuration.Password.Parallelism*8 {
|
} else if configuration.Password.Memory < configuration.Password.Parallelism*8 {
|
||||||
validator.Push(fmt.Errorf("Memory for argon2id must be %d or more (parallelism * 8), you configured memory as %d and parallelism as %d", configuration.Password.Parallelism*8, configuration.Password.Memory, configuration.Password.Parallelism))
|
validator.Push(fmt.Errorf("Memory for argon2id must be %d or more (parallelism * 8), you configured memory as %d and parallelism as %d", configuration.Password.Parallelism*8, configuration.Password.Memory, configuration.Password.Parallelism))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Key Length
|
// Key Length.
|
||||||
if configuration.Password.KeyLength == 0 {
|
if configuration.Password.KeyLength == 0 {
|
||||||
configuration.Password.KeyLength = schema.DefaultPasswordConfiguration.KeyLength
|
configuration.Password.KeyLength = schema.DefaultPasswordConfiguration.KeyLength
|
||||||
} else if configuration.Password.KeyLength < 16 {
|
} else if configuration.Password.KeyLength < 16 {
|
||||||
|
@ -185,12 +185,12 @@ func validateLDAPURL(ldapURL string, validator *schema.StructValidator) (finalUR
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateLDAPRequiredParameters(configuration *schema.LDAPAuthenticationBackendConfiguration, validator *schema.StructValidator) {
|
func validateLDAPRequiredParameters(configuration *schema.LDAPAuthenticationBackendConfiguration, validator *schema.StructValidator) {
|
||||||
// TODO: see if it's possible to disable this check if disable_reset_password is set and when anonymous/user binding is supported (#101 and #387)
|
// TODO: see if it's possible to disable this check if disable_reset_password is set and when anonymous/user binding is supported (#101 and #387).
|
||||||
if configuration.User == "" {
|
if configuration.User == "" {
|
||||||
validator.Push(errors.New("Please provide a user name to connect to the LDAP server"))
|
validator.Push(errors.New("Please provide a user name to connect to the LDAP server"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: see if it's possible to disable this check if disable_reset_password is set and when anonymous/user binding is supported (#101 and #387)
|
// TODO: see if it's possible to disable this check if disable_reset_password is set and when anonymous/user binding is supported (#101 and #387).
|
||||||
if configuration.Password == "" {
|
if configuration.Password == "" {
|
||||||
validator.Push(errors.New("Please provide a password to connect to the LDAP server"))
|
validator.Push(errors.New("Please provide a password to connect to the LDAP server"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,11 @@ import (
|
||||||
// ValidateRegulation validates and update regulator configuration.
|
// ValidateRegulation validates and update regulator configuration.
|
||||||
func ValidateRegulation(configuration *schema.RegulationConfiguration, validator *schema.StructValidator) {
|
func ValidateRegulation(configuration *schema.RegulationConfiguration, validator *schema.StructValidator) {
|
||||||
if configuration.FindTime == "" {
|
if configuration.FindTime == "" {
|
||||||
configuration.FindTime = schema.DefaultRegulationConfiguration.FindTime // 2 min
|
configuration.FindTime = schema.DefaultRegulationConfiguration.FindTime // 2 min.
|
||||||
}
|
}
|
||||||
|
|
||||||
if configuration.BanTime == "" {
|
if configuration.BanTime == "" {
|
||||||
configuration.BanTime = schema.DefaultRegulationConfiguration.BanTime // 5 min
|
configuration.BanTime = schema.DefaultRegulationConfiguration.BanTime // 5 min.
|
||||||
}
|
}
|
||||||
|
|
||||||
findTime, err := utils.ParseDurationString(configuration.FindTime)
|
findTime, err := utils.ParseDurationString(configuration.FindTime)
|
||||||
|
|
|
@ -32,19 +32,19 @@ func ValidateSession(configuration *schema.SessionConfiguration, validator *sche
|
||||||
|
|
||||||
func validateSession(configuration *schema.SessionConfiguration, validator *schema.StructValidator) {
|
func validateSession(configuration *schema.SessionConfiguration, validator *schema.StructValidator) {
|
||||||
if configuration.Expiration == "" {
|
if configuration.Expiration == "" {
|
||||||
configuration.Expiration = schema.DefaultSessionConfiguration.Expiration // 1 hour
|
configuration.Expiration = schema.DefaultSessionConfiguration.Expiration // 1 hour.
|
||||||
} else if _, err := utils.ParseDurationString(configuration.Expiration); err != nil {
|
} else if _, err := utils.ParseDurationString(configuration.Expiration); err != nil {
|
||||||
validator.Push(fmt.Errorf("Error occurred parsing session expiration string: %s", err))
|
validator.Push(fmt.Errorf("Error occurred parsing session expiration string: %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if configuration.Inactivity == "" {
|
if configuration.Inactivity == "" {
|
||||||
configuration.Inactivity = schema.DefaultSessionConfiguration.Inactivity // 5 min
|
configuration.Inactivity = schema.DefaultSessionConfiguration.Inactivity // 5 min.
|
||||||
} else if _, err := utils.ParseDurationString(configuration.Inactivity); err != nil {
|
} else if _, err := utils.ParseDurationString(configuration.Inactivity); err != nil {
|
||||||
validator.Push(fmt.Errorf("Error occurred parsing session inactivity string: %s", err))
|
validator.Push(fmt.Errorf("Error occurred parsing session inactivity string: %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if configuration.RememberMeDuration == "" {
|
if configuration.RememberMeDuration == "" {
|
||||||
configuration.RememberMeDuration = schema.DefaultSessionConfiguration.RememberMeDuration // 1 month
|
configuration.RememberMeDuration = schema.DefaultSessionConfiguration.RememberMeDuration // 1 month.
|
||||||
} else if _, err := utils.ParseDurationString(configuration.RememberMeDuration); err != nil {
|
} else if _, err := utils.ParseDurationString(configuration.RememberMeDuration); err != nil {
|
||||||
validator.Push(fmt.Errorf("Error occurred parsing session remember_me_duration string: %s", err))
|
validator.Push(fmt.Errorf("Error occurred parsing session remember_me_duration string: %s", err))
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,4 +13,4 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// PossibleMethods is the set of all possible Duo 2FA methods.
|
// PossibleMethods is the set of all possible Duo 2FA methods.
|
||||||
var PossibleMethods = []string{Push} // OTP, Phone, SMS
|
var PossibleMethods = []string{Push} // OTP, Phone, SMS.
|
||||||
|
|
|
@ -91,10 +91,10 @@ func FirstFactorPost(delayFunc middlewares.TimingAttackDelayFunc) middlewares.Re
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if bodyJSON.KeepMeLoggedIn can be deref'd and derive the value based on the configuration and JSON data
|
// Check if bodyJSON.KeepMeLoggedIn can be deref'd and derive the value based on the configuration and JSON data.
|
||||||
keepMeLoggedIn := ctx.Providers.SessionProvider.RememberMe != 0 && bodyJSON.KeepMeLoggedIn != nil && *bodyJSON.KeepMeLoggedIn
|
keepMeLoggedIn := ctx.Providers.SessionProvider.RememberMe != 0 && bodyJSON.KeepMeLoggedIn != nil && *bodyJSON.KeepMeLoggedIn
|
||||||
|
|
||||||
// Set the cookie to expire if remember me is enabled and the user has asked us to
|
// Set the cookie to expire if remember me is enabled and the user has asked us to.
|
||||||
if keepMeLoggedIn {
|
if keepMeLoggedIn {
|
||||||
err = ctx.Providers.SessionProvider.UpdateExpiration(ctx.RequestCtx, ctx.Providers.SessionProvider.RememberMe)
|
err = ctx.Providers.SessionProvider.UpdateExpiration(ctx.RequestCtx, ctx.Providers.SessionProvider.RememberMe)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -33,13 +33,13 @@ func (s *FirstFactorSuite) TearDownTest() {
|
||||||
func (s *FirstFactorSuite) TestShouldFailIfBodyIsNil() {
|
func (s *FirstFactorSuite) TestShouldFailIfBodyIsNil() {
|
||||||
FirstFactorPost(nil)(s.mock.Ctx)
|
FirstFactorPost(nil)(s.mock.Ctx)
|
||||||
|
|
||||||
// No body
|
// No body.
|
||||||
assert.Equal(s.T(), "Failed to parse 1FA request body: unable to parse body: unexpected end of JSON input", s.mock.Hook.LastEntry().Message)
|
assert.Equal(s.T(), "Failed to parse 1FA request body: unable to parse body: unexpected end of JSON input", s.mock.Hook.LastEntry().Message)
|
||||||
s.mock.Assert401KO(s.T(), "Authentication failed. Check your credentials.")
|
s.mock.Assert401KO(s.T(), "Authentication failed. Check your credentials.")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *FirstFactorSuite) TestShouldFailIfBodyIsInBadFormat() {
|
func (s *FirstFactorSuite) TestShouldFailIfBodyIsInBadFormat() {
|
||||||
// Missing password
|
// Missing password.
|
||||||
s.mock.Ctx.Request.SetBodyString(`{
|
s.mock.Ctx.Request.SetBodyString(`{
|
||||||
"username": "test"
|
"username": "test"
|
||||||
}`)
|
}`)
|
||||||
|
|
|
@ -65,7 +65,7 @@ func SecondFactorU2FSignGet(ctx *middlewares.AutheliaCtx) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the challenge and registration for use in next request
|
// Save the challenge and registration for use in next request.
|
||||||
userSession.U2FRegistration = &session.U2FRegistration{
|
userSession.U2FRegistration = &session.U2FRegistration{
|
||||||
KeyHandle: device.KeyHandle,
|
KeyHandle: device.KeyHandle,
|
||||||
PublicKey: device.PublicKey,
|
PublicKey: device.PublicKey,
|
||||||
|
|
|
@ -73,7 +73,7 @@ func isTargetURLAuthorized(authorizer *authorization.Authorizer, targetURL url.U
|
||||||
// deduce the access is forbidden
|
// deduce the access is forbidden
|
||||||
// For anonymous users though, we cannot be sure that she
|
// For anonymous users though, we cannot be sure that she
|
||||||
// could not be granted the rights to access the resource. Consequently
|
// could not be granted the rights to access the resource. Consequently
|
||||||
// for anonymous users we send Unauthorized instead of Forbidden
|
// for anonymous users we send Unauthorized instead of Forbidden.
|
||||||
return Forbidden
|
return Forbidden
|
||||||
case level == authorization.OneFactor && authLevel >= authentication.OneFactor,
|
case level == authorization.OneFactor && authLevel >= authentication.OneFactor,
|
||||||
level == authorization.TwoFactor && authLevel >= authentication.TwoFactor:
|
level == authorization.TwoFactor && authLevel >= authentication.TwoFactor:
|
||||||
|
@ -100,7 +100,7 @@ func verifyBasicAuth(ctx *middlewares.AutheliaCtx, header, auth []byte) (usernam
|
||||||
|
|
||||||
// If the user is not correctly authenticated, send a 401.
|
// If the user is not correctly authenticated, send a 401.
|
||||||
if !authenticated {
|
if !authenticated {
|
||||||
// Request Basic Authentication otherwise
|
// Request Basic Authentication otherwise.
|
||||||
return "", "", nil, nil, authentication.NotAuthenticated, fmt.Errorf("user %s is not authenticated", username)
|
return "", "", nil, nil, authentication.NotAuthenticated, fmt.Errorf("user %s is not authenticated", username)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,7 +391,7 @@ func getProfileRefreshSettings(cfg schema.AuthenticationBackendConfiguration) (r
|
||||||
refresh = true
|
refresh = true
|
||||||
|
|
||||||
if cfg.RefreshInterval != schema.ProfileRefreshAlways {
|
if cfg.RefreshInterval != schema.ProfileRefreshAlways {
|
||||||
// Skip Error Check since validator checks it
|
// Skip Error Check since validator checks it.
|
||||||
refreshInterval, _ = utils.ParseDurationString(cfg.RefreshInterval)
|
refreshInterval, _ = utils.ParseDurationString(cfg.RefreshInterval)
|
||||||
} else {
|
} else {
|
||||||
refreshInterval = schema.RefreshIntervalAlways
|
refreshInterval = schema.RefreshIntervalAlways
|
||||||
|
|
|
@ -1023,7 +1023,7 @@ func TestShouldDestroySessionWhenUserNotExist(t *testing.T) {
|
||||||
userSession = mock.Ctx.GetSession()
|
userSession = mock.Ctx.GetSession()
|
||||||
assert.Equal(t, clock.Now().Add(5*time.Minute).Unix(), userSession.RefreshTTL.Unix())
|
assert.Equal(t, clock.Now().Add(5*time.Minute).Unix(), userSession.RefreshTTL.Unix())
|
||||||
|
|
||||||
// Simulate a Deleted User
|
// Simulate a Deleted User.
|
||||||
userSession.RefreshTTL = clock.Now().Add(-1 * time.Minute)
|
userSession.RefreshTTL = clock.Now().Add(-1 * time.Minute)
|
||||||
err = mock.Ctx.SaveSession(userSession)
|
err = mock.Ctx.SaveSession(userSession)
|
||||||
|
|
||||||
|
|
|
@ -151,7 +151,7 @@ func IdentityVerificationFinish(args IdentityVerificationFinishArgs, next func(c
|
||||||
ctx.Error(fmt.Errorf("Cannot parse token"), messageOperationFailed)
|
ctx.Error(fmt.Errorf("Cannot parse token"), messageOperationFailed)
|
||||||
return
|
return
|
||||||
case ve.Errors&(jwt.ValidationErrorExpired|jwt.ValidationErrorNotValidYet) != 0:
|
case ve.Errors&(jwt.ValidationErrorExpired|jwt.ValidationErrorNotValidYet) != 0:
|
||||||
// Token is either expired or not active yet
|
// Token is either expired or not active yet.
|
||||||
ctx.Error(fmt.Errorf("Token expired"), messageIdentityVerificationTokenHasExpired)
|
ctx.Error(fmt.Errorf("Token expired"), messageIdentityVerificationTokenHasExpired)
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -117,7 +117,7 @@ func NewMockAutheliaCtx(t *testing.T) *MockAutheliaCtx {
|
||||||
|
|
||||||
request := &fasthttp.RequestCtx{}
|
request := &fasthttp.RequestCtx{}
|
||||||
// Set a cookie to identify this client throughout the test.
|
// Set a cookie to identify this client throughout the test.
|
||||||
// request.Request.Header.SetCookie("authelia_session", "client_cookie")
|
// request.Request.Header.SetCookie("authelia_session", "client_cookie").
|
||||||
|
|
||||||
autheliaCtx, _ := middlewares.NewAutheliaCtx(request, configuration, providers)
|
autheliaCtx, _ := middlewares.NewAutheliaCtx(request, configuration, providers)
|
||||||
mockAuthelia.Ctx = autheliaCtx
|
mockAuthelia.Ctx = autheliaCtx
|
||||||
|
|
|
@ -38,7 +38,7 @@ func NewSMTPNotifier(configuration *schema.SMTPNotifierConfiguration, certPool *
|
||||||
|
|
||||||
// Do startTLS if available (some servers only provide the auth extension after, and encryption is preferred).
|
// Do startTLS if available (some servers only provide the auth extension after, and encryption is preferred).
|
||||||
func (n *SMTPNotifier) startTLS() error {
|
func (n *SMTPNotifier) startTLS() error {
|
||||||
// Only start if not already encrypted
|
// Only start if not already encrypted.
|
||||||
if _, ok := n.client.TLSConnectionState(); ok {
|
if _, ok := n.client.TLSConnectionState(); ok {
|
||||||
n.log.Debugf("Notifier SMTP connection is already encrypted, skipping STARTTLS")
|
n.log.Debugf("Notifier SMTP connection is already encrypted, skipping STARTTLS")
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package ntp
|
package ntp
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ntpClientModeValue uint8 = 3 // 00000011
|
ntpClientModeValue uint8 = 3 // 00000011.
|
||||||
ntpLeapEnabledValue uint8 = 64 // 01000000
|
ntpLeapEnabledValue uint8 = 64 // 01000000.
|
||||||
ntpVersion3Value uint8 = 24 // 00011000
|
ntpVersion3Value uint8 = 24 // 00011000.
|
||||||
ntpVersion4Value uint8 = 40 // 00101000
|
ntpVersion4Value uint8 = 40 // 00101000.
|
||||||
)
|
)
|
||||||
|
|
||||||
const ntpEpochOffset = 2208988800
|
const ntpEpochOffset = 2208988800
|
||||||
|
|
|
@ -72,7 +72,7 @@ func NewOpenIDConnectProvider(configuration *schema.OpenIDConnectConfiguration)
|
||||||
compose.OAuth2ClientCredentialsGrantFactory,
|
compose.OAuth2ClientCredentialsGrantFactory,
|
||||||
compose.OAuth2RefreshTokenGrantFactory,
|
compose.OAuth2RefreshTokenGrantFactory,
|
||||||
compose.OAuth2ResourceOwnerPasswordCredentialsFactory,
|
compose.OAuth2ResourceOwnerPasswordCredentialsFactory,
|
||||||
// compose.RFC7523AssertionGrantFactory,
|
// compose.RFC7523AssertionGrantFactory,.
|
||||||
|
|
||||||
compose.OpenIDConnectExplicitFactory,
|
compose.OpenIDConnectExplicitFactory,
|
||||||
compose.OpenIDConnectImplicitFactory,
|
compose.OpenIDConnectImplicitFactory,
|
||||||
|
@ -82,7 +82,7 @@ func NewOpenIDConnectProvider(configuration *schema.OpenIDConnectConfiguration)
|
||||||
compose.OAuth2TokenIntrospectionFactory,
|
compose.OAuth2TokenIntrospectionFactory,
|
||||||
compose.OAuth2TokenRevocationFactory,
|
compose.OAuth2TokenRevocationFactory,
|
||||||
|
|
||||||
// compose.OAuth2PKCEFactory,
|
// compose.OAuth2PKCEFactory,.
|
||||||
)
|
)
|
||||||
|
|
||||||
provider.herodot = herodot.NewJSONWriter(nil)
|
provider.herodot = herodot.NewJSONWriter(nil)
|
||||||
|
|
|
@ -282,7 +282,7 @@ func (s *RegulatorSuite) TestShouldHaveRegulatorDisabled() {
|
||||||
LoadAuthenticationLogs(s.ctx, gomock.Eq("john"), gomock.Any(), gomock.Eq(10), gomock.Eq(0)).
|
LoadAuthenticationLogs(s.ctx, gomock.Eq("john"), gomock.Any(), gomock.Eq(10), gomock.Eq(0)).
|
||||||
Return(attemptsInDB, nil)
|
Return(attemptsInDB, nil)
|
||||||
|
|
||||||
// Check Disabled Functionality
|
// Check Disabled Functionality.
|
||||||
configuration := schema.RegulationConfiguration{
|
configuration := schema.RegulationConfiguration{
|
||||||
MaxRetries: 0,
|
MaxRetries: 0,
|
||||||
FindTime: "180",
|
FindTime: "180",
|
||||||
|
@ -293,7 +293,7 @@ func (s *RegulatorSuite) TestShouldHaveRegulatorDisabled() {
|
||||||
_, err := regulator.Regulate(s.ctx, "john")
|
_, err := regulator.Regulate(s.ctx, "john")
|
||||||
assert.NoError(s.T(), err)
|
assert.NoError(s.T(), err)
|
||||||
|
|
||||||
// Check Enabled Functionality
|
// Check Enabled Functionality.
|
||||||
configuration = schema.RegulationConfiguration{
|
configuration = schema.RegulationConfiguration{
|
||||||
MaxRetries: 1,
|
MaxRetries: 1,
|
||||||
FindTime: "180",
|
FindTime: "180",
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
type Regulator struct {
|
type Regulator struct {
|
||||||
// Is the regulation enabled.
|
// Is the regulation enabled.
|
||||||
enabled bool
|
enabled bool
|
||||||
// The number of failed authentication attempt before banning the user
|
// The number of failed authentication attempt before banning the user.
|
||||||
maxRetries int
|
maxRetries int
|
||||||
// If a user does the max number of retries within that duration, she will be banned.
|
// If a user does the max number of retries within that duration, she will be banned.
|
||||||
findTime time.Duration
|
findTime time.Duration
|
||||||
|
|
|
@ -59,7 +59,7 @@ func TestShouldCreateRedisSessionProviderTLS(t *testing.T) {
|
||||||
pConfig := providerConfig.redisConfig
|
pConfig := providerConfig.redisConfig
|
||||||
assert.Equal(t, "redis.example.com:6379", pConfig.Addr)
|
assert.Equal(t, "redis.example.com:6379", pConfig.Addr)
|
||||||
assert.Equal(t, "pass", pConfig.Password)
|
assert.Equal(t, "pass", pConfig.Password)
|
||||||
// DbNumber is the fasthttp/session property for the Redis DB Index
|
// DbNumber is the fasthttp/session property for the Redis DB Index.
|
||||||
assert.Equal(t, 0, pConfig.DB)
|
assert.Equal(t, 0, pConfig.DB)
|
||||||
assert.Equal(t, 0, pConfig.PoolSize)
|
assert.Equal(t, 0, pConfig.PoolSize)
|
||||||
assert.Equal(t, 0, pConfig.MinIdleConns)
|
assert.Equal(t, 0, pConfig.MinIdleConns)
|
||||||
|
@ -94,7 +94,7 @@ func TestShouldCreateRedisSessionProvider(t *testing.T) {
|
||||||
pConfig := providerConfig.redisConfig
|
pConfig := providerConfig.redisConfig
|
||||||
assert.Equal(t, "redis.example.com:6379", pConfig.Addr)
|
assert.Equal(t, "redis.example.com:6379", pConfig.Addr)
|
||||||
assert.Equal(t, "pass", pConfig.Password)
|
assert.Equal(t, "pass", pConfig.Password)
|
||||||
// DbNumber is the fasthttp/session property for the Redis DB Index
|
// DbNumber is the fasthttp/session property for the Redis DB Index.
|
||||||
assert.Equal(t, 0, pConfig.DB)
|
assert.Equal(t, 0, pConfig.DB)
|
||||||
assert.Equal(t, 0, pConfig.PoolSize)
|
assert.Equal(t, 0, pConfig.PoolSize)
|
||||||
assert.Equal(t, 0, pConfig.MinIdleConns)
|
assert.Equal(t, 0, pConfig.MinIdleConns)
|
||||||
|
@ -180,7 +180,7 @@ func TestShouldCreateRedisSentinelSessionProvider(t *testing.T) {
|
||||||
assert.Equal(t, 8, pConfig.PoolSize)
|
assert.Equal(t, 8, pConfig.PoolSize)
|
||||||
assert.Equal(t, 2, pConfig.MinIdleConns)
|
assert.Equal(t, 2, pConfig.MinIdleConns)
|
||||||
|
|
||||||
// DbNumber is the fasthttp/session property for the Redis DB Index
|
// DbNumber is the fasthttp/session property for the Redis DB Index.
|
||||||
assert.Equal(t, 0, pConfig.DB)
|
assert.Equal(t, 0, pConfig.DB)
|
||||||
assert.Nil(t, pConfig.TLSConfig)
|
assert.Nil(t, pConfig.TLSConfig)
|
||||||
}
|
}
|
||||||
|
@ -233,7 +233,7 @@ func TestShouldCreateRedisSessionProviderWithUnixSocket(t *testing.T) {
|
||||||
pConfig := providerConfig.redisConfig
|
pConfig := providerConfig.redisConfig
|
||||||
assert.Equal(t, "/var/run/redis/redis.sock", pConfig.Addr)
|
assert.Equal(t, "/var/run/redis/redis.sock", pConfig.Addr)
|
||||||
assert.Equal(t, "pass", pConfig.Password)
|
assert.Equal(t, "pass", pConfig.Password)
|
||||||
// DbNumber is the fasthttp/session property for the Redis DB Index
|
// DbNumber is the fasthttp/session property for the Redis DB Index.
|
||||||
assert.Equal(t, 0, pConfig.DB)
|
assert.Equal(t, 0, pConfig.DB)
|
||||||
assert.Nil(t, pConfig.TLSConfig)
|
assert.Nil(t, pConfig.TLSConfig)
|
||||||
}
|
}
|
||||||
|
@ -256,7 +256,7 @@ func TestShouldSetDbNumber(t *testing.T) {
|
||||||
|
|
||||||
assert.Equal(t, "redis", providerConfig.providerName)
|
assert.Equal(t, "redis", providerConfig.providerName)
|
||||||
pConfig := providerConfig.redisConfig
|
pConfig := providerConfig.redisConfig
|
||||||
// DbNumber is the fasthttp/session property for the Redis DB Index
|
// DbNumber is the fasthttp/session property for the Redis DB Index.
|
||||||
assert.Equal(t, 5, pConfig.DB)
|
assert.Equal(t, 5, pConfig.DB)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,7 +277,7 @@ func TestShouldUseEncryptingSerializerWithRedis(t *testing.T) {
|
||||||
encoded, err := providerConfig.config.EncodeFunc(payload)
|
encoded, err := providerConfig.config.EncodeFunc(payload)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Now we try to decrypt what has been serialized
|
// Now we try to decrypt what has been serialized.
|
||||||
key := sha256.Sum256([]byte("abc"))
|
key := sha256.Sum256([]byte("abc"))
|
||||||
decrypted, err := utils.Decrypt(encoded, &key)
|
decrypted, err := utils.Decrypt(encoded, &key)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
|
@ -111,7 +111,7 @@ type SQLProvider struct {
|
||||||
sqlUpdateU2FDevicePublicKey string
|
sqlUpdateU2FDevicePublicKey string
|
||||||
sqlUpdateU2FDevicePublicKeyByUsername string
|
sqlUpdateU2FDevicePublicKeyByUsername string
|
||||||
|
|
||||||
// Table: duo_devices
|
// Table: duo_devices.
|
||||||
sqlUpsertDuoDevice string
|
sqlUpsertDuoDevice string
|
||||||
sqlDeleteDuoDevice string
|
sqlDeleteDuoDevice string
|
||||||
sqlSelectDuoDevice string
|
sqlSelectDuoDevice string
|
||||||
|
|
|
@ -39,7 +39,7 @@ func (rs *RodSession) doLoginTwoFactor(t *testing.T, page *rod.Page, username, p
|
||||||
rs.doLoginOneFactor(t, page, username, password, keepMeLoggedIn, targetURL)
|
rs.doLoginOneFactor(t, page, username, password, keepMeLoggedIn, targetURL)
|
||||||
rs.verifyIsSecondFactorPage(t, page)
|
rs.verifyIsSecondFactorPage(t, page)
|
||||||
rs.doValidateTOTP(t, page, otpSecret)
|
rs.doValidateTOTP(t, page, otpSecret)
|
||||||
// timeout when targetURL is not defined to prevent a show stopping redirect when visiting a protected domain
|
// timeout when targetURL is not defined to prevent a show stopping redirect when visiting a protected domain.
|
||||||
if targetURL == "" {
|
if targetURL == "" {
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,10 +11,10 @@ import (
|
||||||
func (rs *RodSession) doInitiatePasswordReset(t *testing.T, page *rod.Page, username string) {
|
func (rs *RodSession) doInitiatePasswordReset(t *testing.T, page *rod.Page, username string) {
|
||||||
err := rs.WaitElementLocatedByCSSSelector(t, page, "reset-password-button").Click("left")
|
err := rs.WaitElementLocatedByCSSSelector(t, page, "reset-password-button").Click("left")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
// Fill in username
|
// Fill in username.
|
||||||
err = rs.WaitElementLocatedByCSSSelector(t, page, "username-textfield").Input(username)
|
err = rs.WaitElementLocatedByCSSSelector(t, page, "username-textfield").Input(username)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
// And click on the reset button
|
// And click on the reset button.
|
||||||
err = rs.WaitElementLocatedByCSSSelector(t, page, "reset-button").Click("left")
|
err = rs.WaitElementLocatedByCSSSelector(t, page, "reset-button").Click("left")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ func (rs *RodSession) doUnsuccessfulPasswordReset(t *testing.T, page *rod.Page,
|
||||||
|
|
||||||
func (rs *RodSession) doResetPassword(t *testing.T, page *rod.Page, username, newPassword1, newPassword2 string, unsuccessful bool) {
|
func (rs *RodSession) doResetPassword(t *testing.T, page *rod.Page, username, newPassword1, newPassword2 string, unsuccessful bool) {
|
||||||
rs.doInitiatePasswordReset(t, page, username)
|
rs.doInitiatePasswordReset(t, page, username)
|
||||||
// then wait for the "email sent notification"
|
// then wait for the "email sent notification".
|
||||||
rs.verifyMailNotificationDisplayed(t, page)
|
rs.verifyMailNotificationDisplayed(t, page)
|
||||||
|
|
||||||
if unsuccessful {
|
if unsuccessful {
|
||||||
|
|
|
@ -84,7 +84,7 @@ func (s *OIDCScenario) TestShouldAuthorizeAccessToOIDCApp() {
|
||||||
|
|
||||||
s.waitBodyContains(s.T(), s.Context(ctx), "Not logged yet...")
|
s.waitBodyContains(s.T(), s.Context(ctx), "Not logged yet...")
|
||||||
|
|
||||||
// Search for the 'login' link
|
// Search for the 'login' link.
|
||||||
err := s.Page.MustSearch("Log in").Click("left")
|
err := s.Page.MustSearch("Log in").Click("left")
|
||||||
assert.NoError(s.T(), err)
|
assert.NoError(s.T(), err)
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ func (s *OIDCScenario) TestShouldAuthorizeAccessToOIDCApp() {
|
||||||
err = s.WaitElementLocatedByCSSSelector(s.T(), s.Context(ctx), "accept-button").Click("left")
|
err = s.WaitElementLocatedByCSSSelector(s.T(), s.Context(ctx), "accept-button").Click("left")
|
||||||
assert.NoError(s.T(), err)
|
assert.NoError(s.T(), err)
|
||||||
|
|
||||||
// Verify that the app is showing the info related to the user stored in the JWT token
|
// Verify that the app is showing the info related to the user stored in the JWT token.
|
||||||
s.waitBodyContains(s.T(), s.Context(ctx), "Logged in as john!")
|
s.waitBodyContains(s.T(), s.Context(ctx), "Logged in as john!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ func (s *OIDCScenario) TestShouldDenyConsent() {
|
||||||
|
|
||||||
s.waitBodyContains(s.T(), s.Context(ctx), "Not logged yet...")
|
s.waitBodyContains(s.T(), s.Context(ctx), "Not logged yet...")
|
||||||
|
|
||||||
// Search for the 'login' link
|
// Search for the 'login' link.
|
||||||
err := s.Page.MustSearch("Log in").Click("left")
|
err := s.Page.MustSearch("Log in").Click("left")
|
||||||
assert.NoError(s.T(), err)
|
assert.NoError(s.T(), err)
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ func (s *PasswordComplexityScenario) TestShouldRejectPasswordReset() {
|
||||||
s.doVisit(s.T(), s.Context(ctx), GetLoginBaseURL())
|
s.doVisit(s.T(), s.Context(ctx), GetLoginBaseURL())
|
||||||
s.verifyIsFirstFactorPage(s.T(), s.Context(ctx))
|
s.verifyIsFirstFactorPage(s.T(), s.Context(ctx))
|
||||||
|
|
||||||
// Attempt to reset the password to a
|
// Attempt to reset the password to a.
|
||||||
s.doResetPassword(s.T(), s.Context(ctx), "john", "a", "a", true)
|
s.doResetPassword(s.T(), s.Context(ctx), "john", "a", "a", true)
|
||||||
s.verifyNotificationDisplayed(s.T(), s.Context(ctx), "Your supplied password does not meet the password policy requirements.")
|
s.verifyNotificationDisplayed(s.T(), s.Context(ctx), "Your supplied password does not meet the password policy requirements.")
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,13 +48,13 @@ func (s *RedirectionCheckScenario) TearDownTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var redirectionAuthorizations = map[string]bool{
|
var redirectionAuthorizations = map[string]bool{
|
||||||
// external website
|
// external website.
|
||||||
"https://www.google.fr": false,
|
"https://www.google.fr": false,
|
||||||
// Not the right domain
|
// Not the right domain.
|
||||||
"https://public.example.com.a:8080/secret.html": false,
|
"https://public.example.com.a:8080/secret.html": false,
|
||||||
// Not https
|
// Not https.
|
||||||
"http://secure.example.com:8080/secret.html": false,
|
"http://secure.example.com:8080/secret.html": false,
|
||||||
// Domain handled by Authelia
|
// Domain handled by Authelia.
|
||||||
"https://secure.example.com:8080/secret.html": true,
|
"https://secure.example.com:8080/secret.html": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,13 +83,13 @@ func (s *RedirectionCheckScenario) TestShouldRedirectOnLoginOnlyWhenDomainIsSafe
|
||||||
}
|
}
|
||||||
|
|
||||||
var logoutRedirectionURLs = map[string]bool{
|
var logoutRedirectionURLs = map[string]bool{
|
||||||
// external website
|
// external website.
|
||||||
"https://www.google.fr": false,
|
"https://www.google.fr": false,
|
||||||
// Not the right domain
|
// Not the right domain.
|
||||||
"https://public.example-not-right.com:8080/index.html": false,
|
"https://public.example-not-right.com:8080/index.html": false,
|
||||||
// Not https
|
// Not https.
|
||||||
"http://public.example.com:8080/index.html": false,
|
"http://public.example.com:8080/index.html": false,
|
||||||
// Domain handled by Authelia
|
// Domain handled by Authelia.
|
||||||
"https://public.example.com:8080/index.html": true,
|
"https://public.example.com:8080/index.html": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ func (s *RegulationScenario) TestShouldBanUserAfterTooManyAttempt() {
|
||||||
require.NoError(s.T(), err)
|
require.NoError(s.T(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enter the correct password and test the regulation lock out
|
// Enter the correct password and test the regulation lock out.
|
||||||
err := s.WaitElementLocatedByCSSSelector(s.T(), s.Context(ctx), "password-textfield").Input("password")
|
err := s.WaitElementLocatedByCSSSelector(s.T(), s.Context(ctx), "password-textfield").Input("password")
|
||||||
require.NoError(s.T(), err)
|
require.NoError(s.T(), err)
|
||||||
err = s.WaitElementLocatedByCSSSelector(s.T(), s.Context(ctx), "sign-in-button").Click("left")
|
err = s.WaitElementLocatedByCSSSelector(s.T(), s.Context(ctx), "sign-in-button").Click("left")
|
||||||
|
@ -76,7 +76,7 @@ func (s *RegulationScenario) TestShouldBanUserAfterTooManyAttempt() {
|
||||||
s.verifyIsFirstFactorPage(s.T(), s.Context(ctx))
|
s.verifyIsFirstFactorPage(s.T(), s.Context(ctx))
|
||||||
time.Sleep(10 * time.Second)
|
time.Sleep(10 * time.Second)
|
||||||
|
|
||||||
// Enter the correct password and test a successful login
|
// Enter the correct password and test a successful login.
|
||||||
err = s.WaitElementLocatedByCSSSelector(s.T(), s.Context(ctx), "password-textfield").Input("password")
|
err = s.WaitElementLocatedByCSSSelector(s.T(), s.Context(ctx), "password-textfield").Input("password")
|
||||||
require.NoError(s.T(), err)
|
require.NoError(s.T(), err)
|
||||||
err = s.WaitElementLocatedByCSSSelector(s.T(), s.Context(ctx), "sign-in-button").Click("left")
|
err = s.WaitElementLocatedByCSSSelector(s.T(), s.Context(ctx), "sign-in-button").Click("left")
|
||||||
|
|
|
@ -55,20 +55,20 @@ func (s *ResetPasswordScenario) TestShouldResetPassword() {
|
||||||
s.doVisit(s.T(), s.Context(ctx), GetLoginBaseURL())
|
s.doVisit(s.T(), s.Context(ctx), GetLoginBaseURL())
|
||||||
s.verifyIsFirstFactorPage(s.T(), s.Context(ctx))
|
s.verifyIsFirstFactorPage(s.T(), s.Context(ctx))
|
||||||
|
|
||||||
// Reset the password to abc
|
// Reset the password to abc.
|
||||||
s.doResetPassword(s.T(), s.Context(ctx), "john", "abc", "abc", false)
|
s.doResetPassword(s.T(), s.Context(ctx), "john", "abc", "abc", false)
|
||||||
|
|
||||||
// Try to login with the old password
|
// Try to login with the old password.
|
||||||
s.doLoginOneFactor(s.T(), s.Context(ctx), "john", "password", false, "")
|
s.doLoginOneFactor(s.T(), s.Context(ctx), "john", "password", false, "")
|
||||||
s.verifyNotificationDisplayed(s.T(), s.Context(ctx), "Incorrect username or password.")
|
s.verifyNotificationDisplayed(s.T(), s.Context(ctx), "Incorrect username or password.")
|
||||||
|
|
||||||
// Try to login with the new password
|
// Try to login with the new password.
|
||||||
s.doLoginOneFactor(s.T(), s.Context(ctx), "john", "abc", false, "")
|
s.doLoginOneFactor(s.T(), s.Context(ctx), "john", "abc", false, "")
|
||||||
|
|
||||||
// Logout
|
// Logout.
|
||||||
s.doLogout(s.T(), s.Context(ctx))
|
s.doLogout(s.T(), s.Context(ctx))
|
||||||
|
|
||||||
// Reset the original password
|
// Reset the original password.
|
||||||
s.doResetPassword(s.T(), s.Context(ctx), "john", "password", "password", false)
|
s.doResetPassword(s.T(), s.Context(ctx), "john", "password", "password", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ func (s *ResetPasswordScenario) TestShouldMakeAttackerThinkPasswordResetIsInitia
|
||||||
// Try to initiate a password reset of an nonexistent user.
|
// Try to initiate a password reset of an nonexistent user.
|
||||||
s.doInitiatePasswordReset(s.T(), s.Context(ctx), "i_dont_exist")
|
s.doInitiatePasswordReset(s.T(), s.Context(ctx), "i_dont_exist")
|
||||||
|
|
||||||
// Check that the notification make the attacker thinks the process is initiated
|
// Check that the notification make the attacker thinks the process is initiated.
|
||||||
s.verifyMailNotificationDisplayed(s.T(), s.Context(ctx))
|
s.verifyMailNotificationDisplayed(s.T(), s.Context(ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,18 +58,18 @@ func (s *TwoFactorSuite) TestShouldAuthorizeSecretAfterTwoFactor() {
|
||||||
username := testUsername
|
username := testUsername
|
||||||
password := testPassword
|
password := testPassword
|
||||||
|
|
||||||
// Login and register TOTP, logout and login again with 1FA & 2FA
|
// Login and register TOTP, logout and login again with 1FA & 2FA.
|
||||||
targetURL := fmt.Sprintf("%s/secret.html", AdminBaseURL)
|
targetURL := fmt.Sprintf("%s/secret.html", AdminBaseURL)
|
||||||
_ = s.doRegisterAndLogin2FA(s.T(), s.Context(ctx), username, password, false, targetURL)
|
_ = s.doRegisterAndLogin2FA(s.T(), s.Context(ctx), username, password, false, targetURL)
|
||||||
|
|
||||||
// And check if the user is redirected to the secret.
|
// And check if the user is redirected to the secret.
|
||||||
s.verifySecretAuthorized(s.T(), s.Context(ctx))
|
s.verifySecretAuthorized(s.T(), s.Context(ctx))
|
||||||
|
|
||||||
// Leave the secret
|
// Leave the secret.
|
||||||
s.doVisit(s.T(), s.Context(ctx), HomeBaseURL)
|
s.doVisit(s.T(), s.Context(ctx), HomeBaseURL)
|
||||||
s.verifyIsHome(s.T(), s.Context(ctx))
|
s.verifyIsHome(s.T(), s.Context(ctx))
|
||||||
|
|
||||||
// And try to reload it again to check the session is kept
|
// And try to reload it again to check the session is kept.
|
||||||
s.doVisit(s.T(), s.Context(ctx), targetURL)
|
s.doVisit(s.T(), s.Context(ctx), targetURL)
|
||||||
s.verifySecretAuthorized(s.T(), s.Context(ctx))
|
s.verifySecretAuthorized(s.T(), s.Context(ctx))
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,11 +54,11 @@ func (s *UserPreferencesScenario) TestShouldRememberLastUsed2FAMethod() {
|
||||||
s.collectScreenshot(ctx.Err(), s.Page)
|
s.collectScreenshot(ctx.Err(), s.Page)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Authenticate
|
// Authenticate.
|
||||||
s.doLoginOneFactor(s.T(), s.Context(ctx), "john", "password", false, "")
|
s.doLoginOneFactor(s.T(), s.Context(ctx), "john", "password", false, "")
|
||||||
s.verifyIsSecondFactorPage(s.T(), s.Context(ctx))
|
s.verifyIsSecondFactorPage(s.T(), s.Context(ctx))
|
||||||
|
|
||||||
// Then switch to push notification method
|
// Then switch to push notification method.
|
||||||
s.doChangeMethod(s.T(), s.Context(ctx), "push-notification")
|
s.doChangeMethod(s.T(), s.Context(ctx), "push-notification")
|
||||||
s.WaitElementLocatedByCSSSelector(s.T(), s.Context(ctx), "push-notification-method")
|
s.WaitElementLocatedByCSSSelector(s.T(), s.Context(ctx), "push-notification-method")
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ func (s *UserPreferencesScenario) TestShouldRememberLastUsed2FAMethod() {
|
||||||
s.verifyIsSecondFactorPage(s.T(), s.Context(ctx))
|
s.verifyIsSecondFactorPage(s.T(), s.Context(ctx))
|
||||||
// And check the latest method is still used.
|
// And check the latest method is still used.
|
||||||
s.WaitElementLocatedByCSSSelector(s.T(), s.Context(ctx), "push-notification-method")
|
s.WaitElementLocatedByCSSSelector(s.T(), s.Context(ctx), "push-notification-method")
|
||||||
// Meaning the authentication is successful
|
// Meaning the authentication is successful.
|
||||||
s.verifyIsHome(s.T(), s.Context(ctx))
|
s.verifyIsHome(s.T(), s.Context(ctx))
|
||||||
|
|
||||||
// Logout the user and see what user 'harry' sees.
|
// Logout the user and see what user 'harry' sees.
|
||||||
|
@ -83,7 +83,7 @@ func (s *UserPreferencesScenario) TestShouldRememberLastUsed2FAMethod() {
|
||||||
s.doLogout(s.T(), s.Context(ctx))
|
s.doLogout(s.T(), s.Context(ctx))
|
||||||
s.verifyIsFirstFactorPage(s.T(), s.Context(ctx))
|
s.verifyIsFirstFactorPage(s.T(), s.Context(ctx))
|
||||||
|
|
||||||
// Then log back as previous user and verify the push notification is still the default method
|
// Then log back as previous user and verify the push notification is still the default method.
|
||||||
s.doLoginOneFactor(s.T(), s.Context(ctx), "john", "password", false, "")
|
s.doLoginOneFactor(s.T(), s.Context(ctx), "john", "password", false, "")
|
||||||
s.verifyIsSecondFactorPage(s.T(), s.Context(ctx))
|
s.verifyIsSecondFactorPage(s.T(), s.Context(ctx))
|
||||||
s.WaitElementLocatedByCSSSelector(s.T(), s.Context(ctx), "push-notification-method")
|
s.WaitElementLocatedByCSSSelector(s.T(), s.Context(ctx), "push-notification-method")
|
||||||
|
@ -92,7 +92,7 @@ func (s *UserPreferencesScenario) TestShouldRememberLastUsed2FAMethod() {
|
||||||
s.doLogout(s.T(), s.Context(ctx))
|
s.doLogout(s.T(), s.Context(ctx))
|
||||||
s.doLoginOneFactor(s.T(), s.Context(ctx), "john", "password", false, "")
|
s.doLoginOneFactor(s.T(), s.Context(ctx), "john", "password", false, "")
|
||||||
|
|
||||||
// Eventually restore the default method
|
// Eventually restore the default method.
|
||||||
s.doChangeMethod(s.T(), s.Context(ctx), "one-time-password")
|
s.doChangeMethod(s.T(), s.Context(ctx), "one-time-password")
|
||||||
s.WaitElementLocatedByCSSSelector(s.T(), s.Context(ctx), "one-time-password-method")
|
s.WaitElementLocatedByCSSSelector(s.T(), s.Context(ctx), "one-time-password-method")
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,18 +132,18 @@ func (s *DuoPushWebDriverSuite) TestShouldAutoSelectDevice() {
|
||||||
ConfigureDuoPreAuth(s.T(), PreAuthAPIResponse)
|
ConfigureDuoPreAuth(s.T(), PreAuthAPIResponse)
|
||||||
ConfigureDuo(s.T(), Allow)
|
ConfigureDuo(s.T(), Allow)
|
||||||
|
|
||||||
// Authenticate
|
// Authenticate.
|
||||||
s.doLoginOneFactor(s.T(), s.Context(ctx), "john", "password", false, "")
|
s.doLoginOneFactor(s.T(), s.Context(ctx), "john", "password", false, "")
|
||||||
// Switch Method where single Device should be selected automatically.
|
// Switch Method where single Device should be selected automatically.
|
||||||
s.doChangeMethod(s.T(), s.Context(ctx), "push-notification")
|
s.doChangeMethod(s.T(), s.Context(ctx), "push-notification")
|
||||||
s.verifyIsHome(s.T(), s.Context(ctx))
|
s.verifyIsHome(s.T(), s.Context(ctx))
|
||||||
|
|
||||||
// Re-Login the user
|
// Re-Login the user.
|
||||||
s.doLogout(s.T(), s.Context(ctx))
|
s.doLogout(s.T(), s.Context(ctx))
|
||||||
s.doLoginOneFactor(s.T(), s.Context(ctx), "john", "password", false, "")
|
s.doLoginOneFactor(s.T(), s.Context(ctx), "john", "password", false, "")
|
||||||
// And check the latest method and device is still used.
|
// And check the latest method and device is still used.
|
||||||
s.WaitElementLocatedByCSSSelector(s.T(), s.Context(ctx), "push-notification-method")
|
s.WaitElementLocatedByCSSSelector(s.T(), s.Context(ctx), "push-notification-method")
|
||||||
// Meaning the authentication is successful
|
// Meaning the authentication is successful.
|
||||||
s.verifyIsHome(s.T(), s.Context(ctx))
|
s.verifyIsHome(s.T(), s.Context(ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ func (s *DuoPushWebDriverSuite) TestShouldSelectDevice() {
|
||||||
ConfigureDuoPreAuth(s.T(), PreAuthAPIResponse)
|
ConfigureDuoPreAuth(s.T(), PreAuthAPIResponse)
|
||||||
ConfigureDuo(s.T(), Allow)
|
ConfigureDuo(s.T(), Allow)
|
||||||
|
|
||||||
// Authenticate
|
// Authenticate.
|
||||||
s.doLoginOneFactor(s.T(), s.Context(ctx), "john", "password", false, "")
|
s.doLoginOneFactor(s.T(), s.Context(ctx), "john", "password", false, "")
|
||||||
// Switch Method where Device Selection should open automatically.
|
// Switch Method where Device Selection should open automatically.
|
||||||
s.doChangeMethod(s.T(), s.Context(ctx), "push-notification")
|
s.doChangeMethod(s.T(), s.Context(ctx), "push-notification")
|
||||||
|
@ -183,12 +183,12 @@ func (s *DuoPushWebDriverSuite) TestShouldSelectDevice() {
|
||||||
s.doChangeDevice(s.T(), s.Context(ctx), "1234567890ABCDEFGHIJ")
|
s.doChangeDevice(s.T(), s.Context(ctx), "1234567890ABCDEFGHIJ")
|
||||||
s.verifyIsHome(s.T(), s.Context(ctx))
|
s.verifyIsHome(s.T(), s.Context(ctx))
|
||||||
|
|
||||||
// Re-Login the user
|
// Re-Login the user.
|
||||||
s.doLogout(s.T(), s.Context(ctx))
|
s.doLogout(s.T(), s.Context(ctx))
|
||||||
s.doLoginOneFactor(s.T(), s.Context(ctx), "john", "password", false, "")
|
s.doLoginOneFactor(s.T(), s.Context(ctx), "john", "password", false, "")
|
||||||
// And check the latest method and device is still used.
|
// And check the latest method and device is still used.
|
||||||
s.WaitElementLocatedByCSSSelector(s.T(), s.Context(ctx), "push-notification-method")
|
s.WaitElementLocatedByCSSSelector(s.T(), s.Context(ctx), "push-notification-method")
|
||||||
// Meaning the authentication is successful
|
// Meaning the authentication is successful.
|
||||||
s.verifyIsHome(s.T(), s.Context(ctx))
|
s.verifyIsHome(s.T(), s.Context(ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ func (s *HighAvailabilityWebDriverSuite) TestShouldKeepUserSessionActiveWithPrim
|
||||||
s.doVisit(s.T(), s.Context(ctx), HomeBaseURL)
|
s.doVisit(s.T(), s.Context(ctx), HomeBaseURL)
|
||||||
s.verifyIsHome(s.T(), s.Context(ctx))
|
s.verifyIsHome(s.T(), s.Context(ctx))
|
||||||
|
|
||||||
// Verify the user is still authenticated
|
// Verify the user is still authenticated.
|
||||||
s.doVisit(s.T(), s.Context(ctx), GetLoginBaseURL())
|
s.doVisit(s.T(), s.Context(ctx), GetLoginBaseURL())
|
||||||
s.verifyIsSecondFactorPage(s.T(), s.Context(ctx))
|
s.verifyIsSecondFactorPage(s.T(), s.Context(ctx))
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ func (s *HighAvailabilityWebDriverSuite) TestShouldKeepUserSessionActiveWithPrim
|
||||||
s.doVisit(s.T(), s.Context(ctx), HomeBaseURL)
|
s.doVisit(s.T(), s.Context(ctx), HomeBaseURL)
|
||||||
s.verifyIsHome(s.T(), s.Context(ctx))
|
s.verifyIsHome(s.T(), s.Context(ctx))
|
||||||
|
|
||||||
// Verify the user is still authenticated
|
// Verify the user is still authenticated.
|
||||||
s.doVisit(s.T(), s.Context(ctx), GetLoginBaseURL())
|
s.doVisit(s.T(), s.Context(ctx), GetLoginBaseURL())
|
||||||
s.verifyIsSecondFactorPage(s.T(), s.Context(ctx))
|
s.verifyIsSecondFactorPage(s.T(), s.Context(ctx))
|
||||||
}
|
}
|
||||||
|
@ -170,11 +170,11 @@ func (s *HighAvailabilityWebDriverSuite) TestShouldKeepSessionAfterAutheliaResta
|
||||||
s.doVisit(s.T(), s.Context(ctx), HomeBaseURL)
|
s.doVisit(s.T(), s.Context(ctx), HomeBaseURL)
|
||||||
s.verifyIsHome(s.T(), s.Context(ctx))
|
s.verifyIsHome(s.T(), s.Context(ctx))
|
||||||
|
|
||||||
// Verify the user is still authenticated
|
// Verify the user is still authenticated.
|
||||||
s.doVisit(s.T(), s.Context(ctx), GetLoginBaseURL())
|
s.doVisit(s.T(), s.Context(ctx), GetLoginBaseURL())
|
||||||
s.verifyIsSecondFactorPage(s.T(), s.Context(ctx))
|
s.verifyIsSecondFactorPage(s.T(), s.Context(ctx))
|
||||||
|
|
||||||
// Then logout and login again to check the secret is still there
|
// Then logout and login again to check the secret is still there.
|
||||||
s.doLogout(s.T(), s.Context(ctx))
|
s.doLogout(s.T(), s.Context(ctx))
|
||||||
s.verifyIsFirstFactorPage(s.T(), s.Context(ctx))
|
s.verifyIsFirstFactorPage(s.T(), s.Context(ctx))
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ func init() {
|
||||||
"internal/suites/example/compose/nginx/portal/docker-compose.yml",
|
"internal/suites/example/compose/nginx/portal/docker-compose.yml",
|
||||||
"internal/suites/example/compose/squid/docker-compose.yml",
|
"internal/suites/example/compose/squid/docker-compose.yml",
|
||||||
"internal/suites/example/compose/smtp/docker-compose.yml",
|
"internal/suites/example/compose/smtp/docker-compose.yml",
|
||||||
// To debug headers
|
// To debug headers.
|
||||||
"internal/suites/example/compose/httpbin/docker-compose.yml",
|
"internal/suites/example/compose/httpbin/docker-compose.yml",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,8 @@ var standaloneSuiteName = "Standalone"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
_ = os.MkdirAll("/tmp/authelia/StandaloneSuite/", 0700)
|
_ = os.MkdirAll("/tmp/authelia/StandaloneSuite/", 0700)
|
||||||
_ = os.WriteFile("/tmp/authelia/StandaloneSuite/jwt", []byte("very_important_secret"), 0600)
|
_ = os.WriteFile("/tmp/authelia/StandaloneSuite/jwt", []byte("very_important_secret"), 0600) //nolint:gosec
|
||||||
_ = os.WriteFile("/tmp/authelia/StandaloneSuite/session", []byte("unsecure_session_secret"), 0600)
|
_ = os.WriteFile("/tmp/authelia/StandaloneSuite/session", []byte("unsecure_session_secret"), 0600) //nolint:gosec
|
||||||
|
|
||||||
dockerEnvironment := NewDockerEnvironment([]string{
|
dockerEnvironment := NewDockerEnvironment([]string{
|
||||||
"internal/suites/docker-compose.yml",
|
"internal/suites/docker-compose.yml",
|
||||||
|
|
|
@ -139,7 +139,7 @@ func (s *StandaloneWebDriverSuite) TestShouldCheckUserIsAskedToRegisterDevice()
|
||||||
// Login one factor again.
|
// Login one factor again.
|
||||||
s.doLoginOneFactor(s.T(), s.Context(ctx), username, password, false, "")
|
s.doLoginOneFactor(s.T(), s.Context(ctx), username, password, false, "")
|
||||||
|
|
||||||
// now the user should be asked to perform 2FA
|
// now the user should be asked to perform 2FA.
|
||||||
s.WaitElementLocatedByClassName(s.T(), s.Context(ctx), "state-method")
|
s.WaitElementLocatedByClassName(s.T(), s.Context(ctx), "state-method")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -136,12 +136,12 @@ func RunFuncUntilCtrlC(fn func() error) error {
|
||||||
|
|
||||||
// RunCommandWithTimeout run a command with timeout.
|
// RunCommandWithTimeout run a command with timeout.
|
||||||
func RunCommandWithTimeout(cmd *exec.Cmd, timeout time.Duration) error {
|
func RunCommandWithTimeout(cmd *exec.Cmd, timeout time.Duration) error {
|
||||||
// Start a process:
|
// Start a process.
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for the process to finish or kill it after a timeout (whichever happens first):
|
// Wait for the process to finish or kill it after a timeout (whichever happens first).
|
||||||
done := make(chan error, 1)
|
done := make(chan error, 1)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
|
|
@ -76,7 +76,7 @@ func ParseRsaPublicKeyFromPemStr(pubPEM string) (*rsa.PublicKey, error) {
|
||||||
case *rsa.PublicKey:
|
case *rsa.PublicKey:
|
||||||
return pub, nil
|
return pub, nil
|
||||||
default:
|
default:
|
||||||
break // fall through
|
break // fall through.
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.New("key type is not RSA")
|
return nil, errors.New("key type is not RSA")
|
||||||
|
|
|
@ -43,7 +43,7 @@ func ParseDurationString(input string) (time.Duration, error) {
|
||||||
|
|
||||||
duration = time.Duration(seconds) * time.Second
|
duration = time.Duration(seconds) * time.Second
|
||||||
case input != "":
|
case input != "":
|
||||||
// Throw this error if input is anything other than a blank string, blank string will default to a duration of nothing
|
// Throw this error if input is anything other than a blank string, blank string will default to a duration of nothing.
|
||||||
return 0, fmt.Errorf("could not convert the input string of %s into a duration", input)
|
return 0, fmt.Errorf("could not convert the input string of %s into a duration", input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue