[MISC] Implement golint recommendations (#885)

Co-authored-by: Clément Michaud <clement.michaud34@gmail.com>
pull/822/head
Amir Zarrinkafsh 2020-04-21 07:03:38 +10:00 committed by GitHub
parent a6b7a8632b
commit 2e784084c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 111 additions and 70 deletions

View File

@ -1,4 +1,7 @@
package main
// BuildTag tag used to bootstrap Authelia binary.
var BuildTag = "__BUILD_TAG__"
// BuildCommit commit used to bootstrap Authelia binary.
var BuildCommit = "__BUILD_COMMIT__"

4
go.mod
View File

@ -19,7 +19,7 @@ require (
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/kr/pty v1.1.8 // indirect
github.com/lib/pq v1.3.0
github.com/mattn/go-sqlite3 v1.13.0
github.com/mattn/go-sqlite3 v2.0.3+incompatible
github.com/ogier/pflag v0.0.1 // indirect
github.com/onsi/ginkgo v1.10.3 // indirect
github.com/onsi/gomega v1.7.1 // indirect
@ -32,7 +32,7 @@ require (
github.com/stretchr/testify v1.5.1
github.com/tebeka/selenium v0.9.9
github.com/tstranex/u2f v1.0.0
github.com/valyala/fasthttp v1.10.0
github.com/valyala/fasthttp v1.11.0
github.com/xdg/stringprep v1.0.0 // indirect
go.mongodb.org/mongo-driver v1.3.2
google.golang.org/appengine v1.6.5 // indirect

3
go.sum
View File

@ -89,6 +89,7 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-redis/redis v6.15.2+incompatible h1:9SpNVG76gr6InJGxoZ6IuuxaCOQwDAhzyXg+Bs+0Sb4=
github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-redis/redis/v7 v7.2.0 h1:CrCexy/jYWZjW0AyVoHlcJUeZN19VWlbepTh1Vq6dJs=
github.com/go-redis/redis/v7 v7.2.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg=
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
@ -212,6 +213,7 @@ github.com/mattn/go-sqlite3 v1.11.0 h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v1.13.0 h1:LnJI81JidiW9r7pS/hXe6cFeO5EXNq7KbfvoJLRI69c=
github.com/mattn/go-sqlite3 v1.13.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
@ -447,6 +449,7 @@ golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0 h1:HyfiK1WMnHj5FXFXatD+Qs1A/xC2Run6RzeW1SyHxpc=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY=
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=

View File

@ -1,23 +1,23 @@
package authentication
// Level is the type representing a level of authentication
// Level is the type representing a level of authentication.
type Level int
const (
// NotAuthenticated if the user is not authenticated yet
// NotAuthenticated if the user is not authenticated yet.
NotAuthenticated Level = iota
// OneFactor if the user has passed first factor only
// OneFactor if the user has passed first factor only.
OneFactor Level = iota
// TwoFactor if the user has passed two factors
// TwoFactor if the user has passed two factors.
TwoFactor Level = iota
)
const (
// TOTP Method using Time-Based One-Time Password applications like Google Authenticator
// TOTP Method using Time-Based One-Time Password applications like Google Authenticator.
TOTP = "totp"
// U2F Method using U2F devices like Yubikeys
// U2F Method using U2F devices like Yubikeys.
U2F = "u2f"
// Push Method using Duo application to receive push notifications
// Push Method using Duo application to receive push notifications.
Push = "mobile_push"
)
@ -25,13 +25,14 @@ const (
var PossibleMethods = []string{TOTP, U2F, Push}
const (
//Argon2id Hash Identifier
// HashingAlgorithmArgon2id Argon2id hash identifier.
HashingAlgorithmArgon2id = "argon2id"
//SHA512 Hash Identifier
// HashingAlgorithmSHA512 SHA512 hash identifier.
HashingAlgorithmSHA512 = "6"
)
// These are the default values from the upstream crypt module, we use them to for GetInt, and they need to be checked when updating github.com/simia-tech/crypt
// These are the default values from the upstream crypt module we use them to for GetInt
// and they need to be checked when updating github.com/simia-tech/crypt.
const (
HashingDefaultArgon2idTime = 1
HashingDefaultArgon2idMemory = 32 * 1024
@ -40,5 +41,5 @@ const (
HashingDefaultSHA512Iterations = 5000
)
// HashingPossibleSaltCharacters represents valid hashing runes
// HashingPossibleSaltCharacters represents valid hashing runes.
var HashingPossibleSaltCharacters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/")

View File

@ -17,35 +17,39 @@ type LDAPConnection interface {
Modify(modifyRequest *ldap.ModifyRequest) error
}
// LDAPConnectionImpl the production implementation of an ldap connection
// LDAPConnectionImpl the production implementation of an ldap connection.
type LDAPConnectionImpl struct {
conn *ldap.Conn
}
// NewLDAPConnectionImpl create a new ldap connection
// NewLDAPConnectionImpl create a new ldap connection.
func NewLDAPConnectionImpl(conn *ldap.Conn) *LDAPConnectionImpl {
return &LDAPConnectionImpl{conn}
}
// Bind binds ldap connection to a username/password.
func (lc *LDAPConnectionImpl) Bind(username, password string) error {
return lc.conn.Bind(username, password)
}
// Close closes a ldap connection.
func (lc *LDAPConnectionImpl) Close() {
lc.conn.Close()
}
// Search searches a ldap server.
func (lc *LDAPConnectionImpl) Search(searchRequest *ldap.SearchRequest) (*ldap.SearchResult, error) {
return lc.conn.Search(searchRequest)
}
// Modify modifies an ldap object.
func (lc *LDAPConnectionImpl) Modify(modifyRequest *ldap.ModifyRequest) error {
return lc.conn.Modify(modifyRequest)
}
// ********************* FACTORY ***********************
// LDAPConnectionFactory an interface of factory of ldap connections
// LDAPConnectionFactory an interface of factory of ldap connections.
type LDAPConnectionFactory interface {
DialTLS(network, addr string, config *tls.Config) (LDAPConnection, error)
Dial(network, addr string) (LDAPConnection, error)
@ -54,7 +58,7 @@ type LDAPConnectionFactory interface {
// LDAPConnectionFactoryImpl the production implementation of an ldap connection factory.
type LDAPConnectionFactoryImpl struct{}
// NewLDAPConnectionFactoryImpl create a concrete ldap connection factory
// NewLDAPConnectionFactoryImpl create a concrete ldap connection factory.
func NewLDAPConnectionFactoryImpl() *LDAPConnectionFactoryImpl {
return &LDAPConnectionFactoryImpl{}
}

View File

@ -27,6 +27,7 @@ func NewLDAPUserProvider(configuration schema.LDAPAuthenticationBackendConfigura
}
}
// NewLDAPUserProviderWithFactory creates a new instance of LDAPUserProvider with existing factory.
func NewLDAPUserProviderWithFactory(configuration schema.LDAPAuthenticationBackendConfiguration,
connectionFactory LDAPConnectionFactory) *LDAPUserProvider {
return &LDAPUserProvider{
@ -90,7 +91,7 @@ func (p *LDAPUserProvider) CheckUserPassword(inputUsername string, password stri
return true, nil
}
// OWASP recommends to escape some special characters
// OWASP recommends to escape some special characters.
// https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.md
const specialLDAPRunes = ",#+<>;\"="
@ -111,7 +112,7 @@ type ldapUserProfile struct {
func (p *LDAPUserProvider) resolveUsersFilter(userFilter string, inputUsername string) string {
inputUsername = p.ldapEscape(inputUsername)
// We temporarily keep placeholder {0} for backward compatibility
// We temporarily keep placeholder {0} for backward compatibility.
userFilter = strings.ReplaceAll(userFilter, "{0}", inputUsername)
// The {username} placeholder is equivalent to {0}, it's the new way, a named placeholder.
@ -137,7 +138,7 @@ func (p *LDAPUserProvider) getUserProfile(conn LDAPConnection, inputUsername str
p.configuration.MailAttribute,
p.configuration.UsernameAttribute}
// Search for the given username
// Search for the given username.
searchRequest := ldap.NewSearchRequest(
baseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases,
1, 0, false, userFilter, attributes, nil,
@ -182,11 +183,11 @@ func (p *LDAPUserProvider) getUserProfile(conn LDAPConnection, inputUsername str
func (p *LDAPUserProvider) resolveGroupsFilter(inputUsername string, profile *ldapUserProfile) (string, error) { //nolint:unparam
inputUsername = p.ldapEscape(inputUsername)
// We temporarily keep placeholder {0} for backward compatibility
// We temporarily keep placeholder {0} for backward compatibility.
groupFilter := strings.ReplaceAll(p.configuration.GroupsFilter, "{0}", inputUsername)
groupFilter = strings.ReplaceAll(groupFilter, "{input}", inputUsername)
if profile != nil {
// We temporarily keep placeholder {1} for backward compatibility
// We temporarily keep placeholder {1} for backward compatibility.
groupFilter = strings.ReplaceAll(groupFilter, "{1}", ldap.EscapeFilter(profile.Username))
groupFilter = strings.ReplaceAll(groupFilter, "{username}", ldap.EscapeFilter(profile.Username))
groupFilter = strings.ReplaceAll(groupFilter, "{dn}", ldap.EscapeFilter(profile.DN))
@ -219,7 +220,7 @@ func (p *LDAPUserProvider) GetDetails(inputUsername string) (*UserDetails, error
groupBaseDN = p.configuration.AdditionalGroupsDN + "," + groupBaseDN
}
// Search for the given username
// Search for the given username.
searchGroupRequest := ldap.NewSearchRequest(
groupBaseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases,
0, 0, false, groupsFilter, []string{p.configuration.GroupNameAttribute}, nil,
@ -237,7 +238,7 @@ func (p *LDAPUserProvider) GetDetails(inputUsername string) (*UserDetails, error
logging.Logger().Warningf("No groups retrieved from LDAP for user %s", inputUsername)
break
}
// append all values of the document. Normally there should be only one per document.
// Append all values of the document. Normally there should be only one per document.
groups = append(groups, res.Attributes[0].Values...)
}

View File

@ -82,6 +82,7 @@ func selectMatchingRules(rules []schema.ACLRule, subject Subject, object Object)
return selectMatchingObjectRules(matchingRules, object)
}
// PolicyToLevel converts a string policy to int authorization level.
func PolicyToLevel(policy string) Level {
switch policy {
case "bypass":

View File

@ -171,11 +171,13 @@ func generateSelfSignedCertificate(cmd *cobra.Command, args []string) {
log.Printf("wrote %s\n", keyPath)
}
// CertificatesCmd certificate helper command.
var CertificatesCmd = &cobra.Command{
Use: "certificates",
Short: "Commands related to certificate generation",
}
// CertificatesGenerateCmd certificate generation command.
var CertificatesGenerateCmd = &cobra.Command{
Use: "generate",
Short: "Generate a self-signed certificate",

View File

@ -19,6 +19,7 @@ func init() {
HashPasswordCmd.Flags().IntP("salt-length", "l", schema.DefaultPasswordConfiguration.SaltLength, "set the auto-generated salt length")
}
// HashPasswordCmd password hashing command.
var HashPasswordCmd = &cobra.Command{
Use: "hash-password [password]",
Short: "Hash a password to be used in file-based users database. Default algorithm is argon2id.",

View File

@ -10,6 +10,7 @@ import (
"github.com/authelia/authelia/internal/storage"
)
// MigrateCmd migration helper command.
var MigrateCmd *cobra.Command
func init() {
@ -20,7 +21,7 @@ func init() {
MigrateCmd.AddCommand(MigrateLocalCmd, MigrateMongoCmd)
}
// TOTPSecretsV3 one entry of TOTP secrets in v3
// TOTPSecretsV3 one entry of TOTP secrets in v3.
type TOTPSecretsV3 struct {
UserID string `json:"userId"`
Secret struct {
@ -28,7 +29,7 @@ type TOTPSecretsV3 struct {
} `json:"secret"`
}
// U2FDeviceHandleV3 one entry of U2F device handle in v3
// U2FDeviceHandleV3 one entry of U2F device handle in v3.
type U2FDeviceHandleV3 struct {
UserID string `json:"userId"`
Registration struct {
@ -37,13 +38,13 @@ type U2FDeviceHandleV3 struct {
} `json:"registration"`
}
// PreferencesV3 one entry of preferences in v3
// PreferencesV3 one entry of preferences in v3.
type PreferencesV3 struct {
UserID string `json:"userId"`
Method string `json:"method"`
}
// AuthenticationTraceV3 one authentication trace in v3
// AuthenticationTraceV3 one authentication trace in v3.
type AuthenticationTraceV3 struct {
UserID string `json:"userId"`
Successful bool `json:"isAuthenticationSuccessful"`

View File

@ -17,7 +17,7 @@ import (
var configurationPath string
var localDatabasePath string
// MigrateLocalCmd migration command
// MigrateLocalCmd migration command.
var MigrateLocalCmd = &cobra.Command{
Use: "localdb",
Short: "Migrate data from v3 local database into database configured in v4 configuration file",
@ -32,7 +32,7 @@ func init() {
MigrateLocalCmd.MarkPersistentFlagRequired("config")
}
// migrateLocal data from v3 to v4
// migrateLocal data from v3 to v4.
func migrateLocal(cmd *cobra.Command, args []string) {
dbProvider := createDBProvider(configurationPath)

View File

@ -17,7 +17,7 @@ import (
var mongoURL string
var mongoDatabase string
// MigrateMongoCmd migration command
// MigrateMongoCmd migration command.
var MigrateMongoCmd = &cobra.Command{
Use: "mongo",
Short: "Migrate data from v3 mongo database into database configured in v4 configuration file",

View File

@ -6,8 +6,7 @@ import (
"strings"
)
// ACLRule represent one ACL rule
// "weak" coerces a single value into string slice
// ACLRule represent one ACL rule "weak" coerces a single value into string slice.
type ACLRule struct {
Domains []string `mapstructure:"domain,weak"`
Policy string `mapstructure:"policy"`
@ -16,25 +15,24 @@ type ACLRule struct {
Resources []string `mapstructure:"resources"`
}
// IsPolicyValid check if policy is valid
// IsPolicyValid check if policy is valid.
func IsPolicyValid(policy string) bool {
return policy == "deny" || policy == "one_factor" || policy == "two_factor" || policy == "bypass"
}
// IsSubjectValid check if a subject is valid
// IsSubjectValid check if a subject is valid.
func IsSubjectValid(subject string) bool {
return subject == "" || strings.HasPrefix(subject, "user:") || strings.HasPrefix(subject, "group:")
}
// IsNetworkValid check if a network is valid
// IsNetworkValid check if a network is valid.
func IsNetworkValid(network string) bool {
_, _, err := net.ParseCIDR(network)
return err == nil
}
// Validate validate an ACL Rule
// Validate validate an ACL Rule.
func (r *ACLRule) Validate(validator *StructValidator) {
if len(r.Domains) == 0 {
validator.Push(fmt.Errorf("Domain must be provided"))
}
@ -62,7 +60,7 @@ type AccessControlConfiguration struct {
Rules []ACLRule `mapstructure:"rules"`
}
// Validate validate the access control configuration
// Validate validate the access control configuration.
func (acc *AccessControlConfiguration) Validate(validator *StructValidator) {
if acc.DefaultPolicy == "" {
acc.DefaultPolicy = "deny"

View File

@ -1,6 +1,6 @@
package schema
// LDAPAuthenticationBackendConfiguration represents the configuration related to LDAP server
// LDAPAuthenticationBackendConfiguration represents the configuration related to LDAP server.
type LDAPAuthenticationBackendConfiguration struct {
URL string `mapstructure:"url"`
SkipVerify bool `mapstructure:"skip_verify"`
@ -16,12 +16,13 @@ type LDAPAuthenticationBackendConfiguration struct {
Password string `mapstructure:"password"`
}
// FileAuthenticationBackendConfiguration represents the configuration related to file-based backend
// FileAuthenticationBackendConfiguration represents the configuration related to file-based backend.
type FileAuthenticationBackendConfiguration struct {
Path string `mapstructure:"path"`
Password *PasswordConfiguration `mapstructure:"password"`
}
// PasswordConfiguration represents the configuration related to password hashing.
type PasswordConfiguration struct {
Iterations int `mapstructure:"iterations"`
KeyLength int `mapstructure:"key_length"`
@ -31,7 +32,7 @@ type PasswordConfiguration struct {
Parallelism int `mapstructure:"parallelism"`
}
// DefaultPasswordConfiguration represents the default configuration related to Argon2id hashing
// DefaultPasswordConfiguration represents the default configuration related to Argon2id hashing.
var DefaultPasswordConfiguration = PasswordConfiguration{
Iterations: 1,
KeyLength: 32,
@ -41,7 +42,7 @@ var DefaultPasswordConfiguration = PasswordConfiguration{
Parallelism: 8,
}
// DefaultCIPasswordConfiguration represents the default configuration related to Argon2id hashing for CI
// DefaultCIPasswordConfiguration represents the default configuration related to Argon2id hashing for CI.
var DefaultCIPasswordConfiguration = PasswordConfiguration{
Iterations: 1,
KeyLength: 32,
@ -51,14 +52,14 @@ var DefaultCIPasswordConfiguration = PasswordConfiguration{
Parallelism: 8,
}
// DefaultPasswordSHA512Configuration represents the default configuration related to SHA512 hashing
// DefaultPasswordSHA512Configuration represents the default configuration related to SHA512 hashing.
var DefaultPasswordSHA512Configuration = PasswordConfiguration{
Iterations: 50000,
SaltLength: 16,
Algorithm: "sha512",
}
// AuthenticationBackendConfiguration represents the configuration related to the authentication backend
// AuthenticationBackendConfiguration represents the configuration related to the authentication backend.
type AuthenticationBackendConfiguration struct {
DisableResetPassword bool `mapstructure:"disable_reset_password"`
Ldap *LDAPAuthenticationBackendConfiguration `mapstructure:"ldap"`

View File

@ -24,6 +24,7 @@ type NotifierConfiguration struct {
SMTP *SMTPNotifierConfiguration `mapstructure:"smtp"`
}
// DefaultSMTPNotifierConfiguration represents default configuration parameters for the SMTP notifier.
var DefaultSMTPNotifierConfiguration = SMTPNotifierConfiguration{
Subject: "[Authelia] {title}",
}

View File

@ -7,6 +7,7 @@ type RegulationConfiguration struct {
BanTime string `mapstructure:"ban_time"`
}
// DefaultRegulationConfiguration represents default configuration parameters for the regulator.
var DefaultRegulationConfiguration = RegulationConfiguration{
MaxRetries: 3,
FindTime: "2m",

View File

@ -8,6 +8,8 @@ type TOTPConfiguration struct {
}
var defaultOtpSkew = 1
// DefaultTOTPConfiguration represents default configuration parameters for TOTP generation.
var DefaultTOTPConfiguration = TOTPConfiguration{
Issuer: "Authelia",
Period: 30,

View File

@ -6,7 +6,7 @@ import (
"github.com/authelia/authelia/internal/configuration/schema"
)
// ValidateSession validates and update session configuration.
// ValidateNotifier validates and update notifier configuration.
func ValidateNotifier(configuration *schema.NotifierConfiguration, validator *schema.StructValidator) {
if configuration.SMTP == nil && configuration.FileSystem == nil {
validator.Push(fmt.Errorf("Notifier should be either `smtp` or `filesystem`"))

View File

@ -7,7 +7,7 @@ import (
"github.com/authelia/authelia/internal/utils"
)
// ValidateSession validates and update session configuration.
// ValidateRegulation validates and update regulator configuration.
func ValidateRegulation(configuration *schema.RegulationConfiguration, validator *schema.StructValidator) {
if configuration.FindTime == "" {
configuration.FindTime = schema.DefaultRegulationConfiguration.FindTime // 2 min

View File

@ -6,7 +6,7 @@ import (
"github.com/authelia/authelia/internal/configuration/schema"
)
// ValidateSQLStorage validates storage configuration.
// ValidateStorage validates storage configuration.
func ValidateStorage(configuration schema.StorageConfiguration, validator *schema.StructValidator) {
if configuration.Local == nil && configuration.MySQL == nil && configuration.PostgreSQL == nil {
validator.Push(errors.New("A storage configuration must be provided. It could be 'local', 'mysql' or 'postgres'"))

View File

@ -11,6 +11,7 @@ const ResetPasswordAction = "ResetPassword"
const authPrefix = "Basic "
// AuthorizationHeader is the basic-auth HTTP header Authelia utilises.
const AuthorizationHeader = "Proxy-Authorization"
const remoteUserHeader = "Remote-User"
const remoteGroupsHeader = "Remote-Groups"
@ -18,7 +19,7 @@ const remoteGroupsHeader = "Remote-Groups"
var protoHostSeparator = []byte("://")
const (
// Forbidden means the user is forbidden the access to a resource
// Forbidden means the user is forbidden the access to a resource.
Forbidden authorizationMatching = iota
// NotAuthorized means the user can access the resource with more permissions.
NotAuthorized authorizationMatching = iota

View File

@ -2,12 +2,14 @@ package handlers
import "github.com/authelia/authelia/internal/middlewares"
// ConfigurationBody configuration parameters exposed to the frontend.
type ConfigurationBody struct {
GoogleAnalyticsTrackingID string `json:"ga_tracking_id,omitempty"`
RememberMe bool `json:"remember_me"` // whether remember me is enabled or not
ResetPassword bool `json:"reset_password"`
}
// ConfigurationGet fetches configuration parameters for frontend mutation.
func ConfigurationGet(ctx *middlewares.AutheliaCtx) {
body := ConfigurationBody{
GoogleAnalyticsTrackingID: ctx.Configuration.GoogleAnalyticsTrackingID,

View File

@ -79,6 +79,7 @@ func UserInfoGet(ctx *middlewares.AutheliaCtx) {
ctx.SetJSONBody(preferences)
}
// MethodBody the selected 2FA method.
type MethodBody struct {
Method string `json:"method" valid:"required"`
}

View File

@ -7,15 +7,18 @@ import (
"github.com/pquerna/otp/totp"
)
// TOTPVerifier is the interface for verifying TOTPs.
type TOTPVerifier interface {
Verify(token, secret string) (bool, error)
}
// TOTPVerifierImpl the production implementation for TOTP verification.
type TOTPVerifierImpl struct {
Period uint
Skew uint
}
// Verify verifies TOTPs.
func (tv *TOTPVerifierImpl) Verify(token, secret string) (bool, error) {
opts := totp.ValidateOpts{
Period: tv.Period,

View File

@ -11,15 +11,15 @@ type MethodList = []string
type authorizationMatching int
// UserInfo is the model of user second factor preferences
// UserInfo is the model of user second factor preferences.
type UserPreferences struct {
// The preferred 2FA method.
Method string `json:"method" valid:"required"`
// True if a security key has been registered
// True if a security key has been registered.
HasU2F bool `json:"has_u2f" valid:"required"`
// True if a TOTP device has been registered
// True if a TOTP device has been registered.
HasTOTP bool `json:"has_totp" valid:"required"`
}
@ -68,12 +68,12 @@ type StateResponse struct {
DefaultRedirectionURL string `json:"default_redirection_url"`
}
// resetPasswordStep1RequestBody model of the reset password (step1) request body
// resetPasswordStep1RequestBody model of the reset password (step1) request body.
type resetPasswordStep1RequestBody struct {
Username string `json:"username"`
}
// resetPasswordStep2RequestBody model of the reset password (step2) request body
// resetPasswordStep2RequestBody model of the reset password (step2) request body.
type resetPasswordStep2RequestBody struct {
Password string `json:"password"`
}

View File

@ -6,12 +6,15 @@ import (
"github.com/tstranex/u2f"
)
// U2FVerifier is the interface for verifying U2F keys.
type U2FVerifier interface {
Verify(keyHandle []byte, publicKey []byte, signResponse u2f.SignResponse, challenge u2f.Challenge) error
}
// U2FVerifierImpl the production implementation for U2F key verification.
type U2FVerifierImpl struct{}
// Verify verifies U2F keys.
func (uv *U2FVerifierImpl) Verify(keyHandle []byte, publicKey []byte,
signResponse u2f.SignResponse, challenge u2f.Challenge) error {
var registration u2f.Registration

View File

@ -23,14 +23,14 @@ import (
"github.com/authelia/authelia/internal/session"
)
// MockAutheliaCtx a mock of AutheliaCtx
// MockAutheliaCtx a mock of AutheliaCtx.
type MockAutheliaCtx struct {
// Logger hook
// Logger hook.
Hook *test.Hook
Ctx *middlewares.AutheliaCtx
Ctrl *gomock.Controller
// Providers
// Providers.
UserProviderMock *MockUserProvider
StorageProviderMock *storage.MockProvider
NotifierMock *MockNotifier
@ -40,27 +40,27 @@ type MockAutheliaCtx struct {
Clock TestingClock
}
// TestingClock implementation of clock for tests
// TestingClock implementation of clock for tests.
type TestingClock struct {
now time.Time
}
// Now return the stored clock
// Now return the stored clock.
func (dc *TestingClock) Now() time.Time {
return dc.now
}
// After return a channel receiving the time after duration has elapsed
// After return a channel receiving the time after duration has elapsed.
func (dc *TestingClock) After(d time.Duration) <-chan time.Time {
return time.After(d)
}
// Set set the time of the clock
// Set set the time of the clock.
func (dc *TestingClock) Set(now time.Time) {
dc.now = now
}
// NewMockAutheliaCtx create an instance of AutheliaCtx mock
// NewMockAutheliaCtx create an instance of AutheliaCtx mock.
func NewMockAutheliaCtx(t *testing.T) *MockAutheliaCtx {
mockAuthelia := new(MockAutheliaCtx)
mockAuthelia.Clock = TestingClock{}
@ -107,7 +107,7 @@ func NewMockAutheliaCtx(t *testing.T) *MockAutheliaCtx {
providers.Regulator = regulation.NewRegulator(configuration.Regulation, providers.StorageProvider, &mockAuthelia.Clock)
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")
autheliaCtx, _ := middlewares.NewAutheliaCtx(request, configuration, providers)
@ -120,7 +120,7 @@ func NewMockAutheliaCtx(t *testing.T) *MockAutheliaCtx {
return mockAuthelia
}
// Close close the mock
// Close close the mock.
func (m *MockAutheliaCtx) Close() {
m.Hook.Reset()
m.Ctrl.Finish()
@ -146,6 +146,7 @@ func (m *MockAutheliaCtx) Assert200OK(t *testing.T, data interface{}) {
assert.Equal(t, string(b), string(m.Ctx.Response.Body()))
}
// GetResponseData retrieves a response from the service.
func (m *MockAutheliaCtx) GetResponseData(t *testing.T, data interface{}) {
okResponse := middlewares.OKResponse{}
okResponse.Data = data

View File

@ -2,7 +2,7 @@ package models
import "time"
// Attempt represent an authentication attempt.
// AuthenticationAttempt represent an authentication attempt.
type AuthenticationAttempt struct {
// The user who tried to authenticate.
Username string

View File

@ -6,12 +6,21 @@ import (
"time"
)
// ErrTimeoutReached error thrown when a timeout is reached
// ErrTimeoutReached error thrown when a timeout is reached.
var ErrTimeoutReached = errors.New("timeout reached")
var parseDurationRegexp = regexp.MustCompile(`^(?P<Duration>[1-9]\d*?)(?P<Unit>[smhdwMy])?$`)
// Hour is an int based representation of the time unit
const Hour = time.Minute * 60
// Day is an int based representation of the time unit
const Day = Hour * 24
// Week is an int based representation of the time unit
const Week = Day * 7
// Year is an int based representation of the time unit
const Year = Day * 365
// Month is an int based representation of the time unit
const Month = Year / 12

View File

@ -5,6 +5,7 @@ import (
"strings"
)
// IsRedirectionSafe determines if a redirection URL is secured.
func IsRedirectionSafe(url url.URL, protectedDomain string) bool {
if url.Scheme != "https" {
return false

View File

@ -5,7 +5,7 @@ import (
"time"
)
// Checks if a single string is in an array of strings
// IsStringInSlice checks if a single string is in an array of strings.
func IsStringInSlice(a string, list []string) (inSlice bool) {
for _, b := range list {
if b == a {
@ -15,8 +15,8 @@ func IsStringInSlice(a string, list []string) (inSlice bool) {
return false
}
// Splits a string s into an array with each item being a max of int d
// d = denominator, n = numerator, q = quotient, r = remainder
// SliceString splits a string s into an array with each item being a max of int d
// d = denominator, n = numerator, q = quotient, r = remainder.
func SliceString(s string, d int) (array []string) {
n := len(s)
q := n / d
@ -30,7 +30,7 @@ func SliceString(s string, d int) (array []string) {
return
}
// RandomString generate a random string of n characters
// RandomString generate a random string of n characters.
func RandomString(n int, characters []rune) (randomString string) {
rand.Seed(time.Now().UnixNano())
b := make([]rune, n)