diff --git a/BREAKING.md b/BREAKING.md index 920deb55e..bdeb5d1de 100644 --- a/BREAKING.md +++ b/BREAKING.md @@ -6,6 +6,38 @@ recommended not to use the 'latest' Docker image tag blindly but pick a version and read this documentation before upgrading. This is where you will get information about breaking changes and about what you should do to overcome those changes. +## Breaking in v4.21.0 +* New LDAP attribute `display_name_attribute` has been introduced, defaults to value: `displayname`. +* New key `displayname` has been introduced into the file based user database. + +These are utilised to greet the logged in user. + +If utilising a file based user backend: +* Administrators will need to update users and include the `displayname` key. + +**Before:** +```yaml +users: + john: + password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" + email: john.doe@authelia.com + groups: + - admins + - dev +``` +**After:** +```yaml +users: + john: + displayname: "John Doe" + password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" + email: john.doe@authelia.com + groups: + - admins + - dev +``` +* Users with long-lived sessions will need to recreate the session (logout and login) to propagate the changes. + ## Breaking in v4.20.0 * Authelia's Docker volumes have been refactored. All data should reside within a single volume of `/config`. All examples have been updated to reflect this change. The entrypoint for the container changed from diff --git a/compose/lite/authelia/users_database.yml b/compose/lite/authelia/users_database.yml index b70501484..8f99077b2 100644 --- a/compose/lite/authelia/users_database.yml +++ b/compose/lite/authelia/users_database.yml @@ -7,6 +7,7 @@ # List of users users: authelia: + displayname: "Authelia User" password: "$6$rounds=50000$BpLnfgDsc2WD8F2q$Zis.ixdg9s/UOJYrs56b5QEZFiZECu0qZVNsIYxBaNJ7ucIL.nlxVCT5tqh8KHG8X4tlwCFm5r6NTOZZ5qRFN/" # Password is 'authelia' email: authelia@authelia.com groups: diff --git a/compose/local/authelia/users_database.yml b/compose/local/authelia/users_database.yml index 3feabf738..f50cbf8e5 100644 --- a/compose/local/authelia/users_database.yml +++ b/compose/local/authelia/users_database.yml @@ -7,6 +7,7 @@ # List of users users: : + displayname: "" password: "" email: @example.com groups: diff --git a/compose/local/setup.sh b/compose/local/setup.sh index d9b433ef6..5f5d9fb2b 100755 --- a/compose/local/setup.sh +++ b/compose/local/setup.sh @@ -8,6 +8,10 @@ password(){ read -esp "Enter a password for $USERNAME: " PASSWORD } +displayname(){ + read -ep "Enter your display name for Authelia (eg. John Doe): " DISPLAYNAME +} + echo "Checking for pre-requisites" if [[ ! -x "$(command -v docker)" ]]; then @@ -63,6 +67,19 @@ else username fi +displayname + +if [[ $DISPLAYNAME != "" ]]; then + if [[ $(uname) == "Darwin" ]]; then + sed -i '' "s//$DISPLAYNAME/g" authelia/users_database.yml + else + sed -i "s//$DISPLAYNAME/g" authelia/users_database.yml + fi +else + echo "Display name cannot be empty" + displayname +fi + password if [[ $PASSWORD != "" ]]; then diff --git a/config.template.yml b/config.template.yml index 6025f0666..e132fc89a 100644 --- a/config.template.yml +++ b/config.template.yml @@ -151,6 +151,9 @@ authentication_backend: # one returned by the LDAP server is used. mail_attribute: mail + # The attribute holding the display name of the user. This will be used to greet an authenticated user. + display_name_attribute: displayname + # The username and password of the admin user. user: cn=admin,dc=example,dc=com # Password can also be set using a secret: https://docs.authelia.com/configuration/secrets.html diff --git a/docs/configuration/authentication/file.md b/docs/configuration/authentication/file.md index 72e8718c4..801eb10ba 100644 --- a/docs/configuration/authentication/file.md +++ b/docs/configuration/authentication/file.md @@ -51,21 +51,25 @@ The format of the users file is as follows. ```yaml users: john: + displayname: "John Doe" password: "$argon2id$v=19$m=65536,t=3,p=2$BpLnfgDsc2WD8F2q$o/vzA4myCqZZ36bUGsDY//8mKUYNZZaR0t4MFFSs+iM" email: john.doe@authelia.com groups: - admins - dev harry: + displayname: "Harry Potter" password: "$argon2id$v=19$m=65536,t=3,p=2$BpLnfgDsc2WD8F2q$o/vzA4myCqZZ36bUGsDY//8mKUYNZZaR0t4MFFSs+iM" email: harry.potter@authelia.com groups: [] bob: + displayname: "Bob Dylan" password: "$argon2id$v=19$m=65536,t=3,p=2$BpLnfgDsc2WD8F2q$o/vzA4myCqZZ36bUGsDY//8mKUYNZZaR0t4MFFSs+iM" email: bob.dylan@authelia.com groups: - dev james: + displayname: "James Dean" password: "$argon2id$v=19$m=65536,t=3,p=2$BpLnfgDsc2WD8F2q$o/vzA4myCqZZ36bUGsDY//8mKUYNZZaR0t4MFFSs+iM" email: james.dean@authelia.com ``` diff --git a/docs/configuration/authentication/ldap.md b/docs/configuration/authentication/ldap.md index 488f9a327..ef45523de 100644 --- a/docs/configuration/authentication/ldap.md +++ b/docs/configuration/authentication/ldap.md @@ -88,6 +88,9 @@ authentication_backend: # The attribute holding the mail address of the user mail_attribute: mail + # The attribute holding the display name of the user. This will be used to greet an authenticated user. + display_name_attribute: displayname + # The username and password of the admin user. If multiple email addresses are defined for a user, only the first # one returned by the LDAP server is used. user: cn=admin,dc=example,dc=com diff --git a/internal/authentication/configuration.gen.go b/internal/authentication/configuration.gen.go index 8c526bcab..6429429a3 100644 --- a/internal/authentication/configuration.gen.go +++ b/internal/authentication/configuration.gen.go @@ -2,4 +2,4 @@ package authentication import "aletheia.icu/broccoli/fs" -var cfg = fs.New(false, []byte("\x8b\xa1\x80\r\xff\x83\x02\x01\x02\xff\x84\x00\x01\xff\x82\x00\x00=\xff\x81\x03\x01\x02\xff\x82\x00\x01\x05\x01\x04Data\x01\n\x00\x01\x05Fpath\x01\f\x00\x01\x05Fname\x01\f\x00\x01\x05Fsize\x01\x04\x00\x01\x05Ftime\x01\x04\x00\x00\x00\xff\xf6\xff\x84\x00\x01\x01\xff\xaa\x1b\xe6\x00`\x1c\x87\xb1\xf3\xa4II\xda\xd3]\xbci`\x9e\xa9θ\x13\x91\xe6\x06\xb8A\xc2Z\x14F\x8fNn~P\xeb\xe7nAy@\x10C 7\xecwSb\xed\x15\xee>\x0f\xa3\xbe\x8b\xfc,\xb6\xa3\x98\xfe\xe7\x00Bj²\x90b\x0f\x19\xc4=\x92\x8b\xc2j\xb7\xden\x98Nd\xaa\x1d\xa2?J\xc9\xd3ŗ\xb9\x9cM+\u07bf\xfe\xcf{c\x85H9\xaf\xec97\xa6\xe4o\xeaƘ\xdfO\xf1\xf3\xdd\\\xd2Iٮ\u074b\xaa4i#\x17\xc5w=\x19\xd9\n\x02\xbf3o\xdc\x028\rp:\xf7\x011\x8fY\x88g\x87\x9c\b}\xf8\xa1\xc8mݞ?\x00\x01\x1busers_database.template.yml\x01\x1busers_database.template.yml\x01\xfe\x01\xce\x01\xfc\xbd\xcb\xdc\xf6\x00\x03")) +var cfg = fs.New(false, []byte("\x1b\x8b\x01\x006B\xe6\xf4A<4\x19\x01\x1fdurk\v(@<\x06\xdf\n0L=\x92\xc0\x12\xe5JP:\xc3\x02sv\x9cu\xc2GRQ \n\x92\x06 \x92\x02\x80<\x92\x8c\nQ\x16D\x87h/\xa1\x808\\\x03O\x887\x80\n\xdd \x1a:\xd2\x00\xfc\x87\xf2\xb1\xa7A\xe4\x13-@a\xca+\x13x_\xa6|\xfb\xd6\xf1\x84\xb9ś\xe5~Ҵf\xe1L~@~\x05OՈ\xec\x1c]\x00\xd1\xeer\xd8\xd0\xd3L\x8f\xb7\x16\xae\x94>\xb5\xbd\a\x16\xba\xf44\x9f\x1e\x1e)o\xe4`\xa1\x9e\x88[\rlY\xbaa=I\x13\xda\xc2}X(x2l[\x192\xe7\xf8`\x9b\xba\xdfd!s\xf3u\xf6\xa59'\xda?q\x0e\xa5\xcf1\x01\x96\x9b\xf6\"u@jh\x9cj,,\xed\v\xd6\xfc\xc1\xd3\xda\xf8\x15\x8e\x1f\xfb\xcf\xfc>T\xbc\xbd\u0379*u\x9fi\xa6\xfc\xf9\xfa\xd4d\x90Y\xb6\xdf\xe1\xed\xb3\xb3\x9eC$\xfd\x97\v\xe5\xb9\xec\xf8N\xfc\xb0\xb3\xa0\xa2\xe4\xafz\x8f\a\xf1\x9e\n\xf5\xf1\x06\xe5\u007f\a.\xa6(\t\x1f\x18?t_\xff\xf42aJ\xf6E\xe8\ue7c3\x02\x01\xfc\x8e\xf3\xd8\x0f\fD\x12\xb5h\xbf\v\v\\\x1cB\x85KB\x88\x9b&\xf5]\"\x95Tɿeކ|À\xb4\x8et\xe4\xa1\xc0\xeb\x81@\xb4\xbf_\xb0\xfcGC\x81\u007f\xe7/\x8e\x00\x00")) diff --git a/internal/authentication/file_user_provider.go b/internal/authentication/file_user_provider.go index 32a57cdfd..dc6f46b42 100644 --- a/internal/authentication/file_user_provider.go +++ b/internal/authentication/file_user_provider.go @@ -29,6 +29,7 @@ type FileUserProvider struct { // UserDetailsModel is the model of user details in the file database. type UserDetailsModel struct { HashedPassword string `yaml:"password" valid:"required"` + DisplayName string `yaml:"displayname" valid:"required"` Email string `yaml:"email"` Groups []string `yaml:"groups"` } @@ -183,9 +184,10 @@ func (p *FileUserProvider) CheckUserPassword(username string, password string) ( func (p *FileUserProvider) GetDetails(username string) (*UserDetails, error) { if details, ok := p.database.Users[username]; ok { return &UserDetails{ - Username: username, - Groups: details.Groups, - Emails: []string{details.Email}, + Username: username, + DisplayName: details.DisplayName, + Groups: details.Groups, + Emails: []string{details.Email}, }, nil } diff --git a/internal/authentication/file_user_provider_test.go b/internal/authentication/file_user_provider_test.go index 7ce16def4..2d15c7fbc 100644 --- a/internal/authentication/file_user_provider_test.go +++ b/internal/authentication/file_user_provider_test.go @@ -287,6 +287,7 @@ var ( var UserDatabaseContent = []byte(` users: john: + displayname: "John Doe" password: "{CRYPT}$argon2id$v=19$m=65536,t=3,p=2$BpLnfgDsc2WD8F2q$o/vzA4myCqZZ36bUGsDY//8mKUYNZZaR0t4MFFSs+iM" email: john.doe@authelia.com groups: @@ -294,22 +295,26 @@ users: - dev harry: + displayname: "Harry Potter" password: "{CRYPT}$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: harry.potter@authelia.com groups: [] bob: + displayname: "Bob Dylan" password: "{CRYPT}$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: bob.dylan@authelia.com groups: - dev james: + displayname: "James Dean" password: "{CRYPT}$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: james.dean@authelia.com enumeration: + displayname: "Enumeration" password: "$argon2id$v=19$m=131072,p=8$BpLnfgDsc2WD8F2q$O126GHPeZ5fwj7OLSs7PndXsTbje76R+QW9/EGfhkJg" email: james.dean@authelia.com `) @@ -327,6 +332,7 @@ groups: var BadSchemaUserDatabaseContent = []byte(` user: john: + displayname: "John Doe" password: "{CRYPT}$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: john.doe@authelia.com groups: @@ -337,12 +343,14 @@ user: var UserDatabaseWithoutCryptContent = []byte(` users: john: + displayname: "John Doe" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: john.doe@authelia.com groups: - admins - dev james: + displayname: "James Dean" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: james.dean@authelia.com `) @@ -350,12 +358,14 @@ users: var BadSHA512HashContent = []byte(` users: john: + displayname: "John Doe" password: "$6$rounds00000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: john.doe@authelia.com groups: - admins - dev james: + displayname: "James Dean" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: james.dean@authelia.com `) @@ -363,12 +373,14 @@ users: var BadArgon2idHashSettingsContent = []byte(` users: john: + displayname: "John Doe" password: "$argon2id$v=19$m65536,t3,p2$BpLnfgDsc2WD8F2q$o/vzA4myCqZZ36bUGsDY//8mKUYNZZaR0t4MFFSs+iM" email: john.doe@authelia.com groups: - admins - dev james: + displayname: "James Dean" password: "$argon2id$v=19$m=65536,t=3,p=2$BpLnfgDsc2WD8F2q$o/vzA4myCqZZ36bUGsDY//8mKUYNZZaR0t4MFFSs+iM" email: james.dean@authelia.com `) @@ -376,6 +388,7 @@ users: var BadArgon2idHashKeyContent = []byte(` users: john: + displayname: "John Doe" password: "$argon2id$v=19$m=65536,t=3,p=2$BpLnfgDsc2WD8F2q$^^vzA4myCqZZ36bUGsDY//8mKUYNZZaR0t4MFFSs+iM" email: john.doe@authelia.com groups: @@ -385,6 +398,7 @@ users: var BadArgon2idHashSaltContent = []byte(` users: john: + displayname: "John Doe" password: "$argon2id$v=19$m=65536,t=3,p=2$^^LnfgDsc2WD8F2q$o/vzA4myCqZZ36bUGsDY//8mKUYNZZaR0t4MFFSs+iM" email: john.doe@authelia.com groups: diff --git a/internal/authentication/ldap_user_provider.go b/internal/authentication/ldap_user_provider.go index 9d8baf0dd..c96dde66e 100644 --- a/internal/authentication/ldap_user_provider.go +++ b/internal/authentication/ldap_user_provider.go @@ -108,9 +108,10 @@ func (p *LDAPUserProvider) ldapEscape(inputUsername string) string { } type ldapUserProfile struct { - DN string - Emails []string - Username string + DN string + Emails []string + DisplayName string + Username string } func (p *LDAPUserProvider) resolveUsersFilter(userFilter string, inputUsername string) string { @@ -126,6 +127,7 @@ func (p *LDAPUserProvider) resolveUsersFilter(userFilter string, inputUsername s // in configuration. userFilter = strings.ReplaceAll(userFilter, "{username_attribute}", p.configuration.UsernameAttribute) userFilter = strings.ReplaceAll(userFilter, "{mail_attribute}", p.configuration.MailAttribute) + userFilter = strings.ReplaceAll(userFilter, "{display_name_attribute}", p.configuration.DisplayNameAttribute) return userFilter } @@ -140,6 +142,7 @@ func (p *LDAPUserProvider) getUserProfile(conn LDAPConnection, inputUsername str } attributes := []string{"dn", + p.configuration.DisplayNameAttribute, p.configuration.MailAttribute, p.configuration.UsernameAttribute} @@ -167,6 +170,10 @@ func (p *LDAPUserProvider) getUserProfile(conn LDAPConnection, inputUsername str } for _, attr := range sr.Entries[0].Attributes { + if attr.Name == p.configuration.DisplayNameAttribute { + userProfile.DisplayName = attr.Values[0] + } + if attr.Name == p.configuration.MailAttribute { userProfile.Emails = attr.Values } @@ -254,9 +261,10 @@ func (p *LDAPUserProvider) GetDetails(inputUsername string) (*UserDetails, error } return &UserDetails{ - Username: profile.Username, - Emails: profile.Emails, - Groups: groups, + Username: profile.Username, + DisplayName: profile.DisplayName, + Emails: profile.Emails, + Groups: groups, }, nil } diff --git a/internal/authentication/ldap_user_provider_test.go b/internal/authentication/ldap_user_provider_test.go index b9b9a1218..d831c11aa 100644 --- a/internal/authentication/ldap_user_provider_test.go +++ b/internal/authentication/ldap_user_provider_test.go @@ -97,9 +97,10 @@ func TestEscapeSpecialCharsInGroupsFilter(t *testing.T) { }, mockFactory) profile := ldapUserProfile{ - DN: "cn=john (external),dc=example,dc=com", - Username: "john", - Emails: []string{"john.doe@authelia.com"}, + DN: "cn=john (external),dc=example,dc=com", + Username: "john", + DisplayName: "John Doe", + Emails: []string{"john.doe@authelia.com"}, } filter, _ := ldap.resolveGroupsFilter("john", &profile) @@ -134,14 +135,15 @@ func TestShouldEscapeUserInput(t *testing.T) { mockConn := NewMockLDAPConnection(ctrl) ldapClient := NewLDAPUserProviderWithFactory(schema.LDAPAuthenticationBackendConfiguration{ - URL: "ldap://127.0.0.1:389", - User: "cn=admin,dc=example,dc=com", - UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))", - UsernameAttribute: "uid", - MailAttribute: "mail", - Password: "password", - AdditionalUsersDN: "ou=users", - BaseDN: "dc=example,dc=com", + URL: "ldap://127.0.0.1:389", + User: "cn=admin,dc=example,dc=com", + UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))", + UsernameAttribute: "uid", + MailAttribute: "mail", + DisplayNameAttribute: "displayname", + Password: "password", + AdditionalUsersDN: "ou=users", + BaseDN: "dc=example,dc=com", }, mockFactory) mockConn.EXPECT(). @@ -160,14 +162,15 @@ func TestShouldCombineUsernameFilterAndUsersFilter(t *testing.T) { mockConn := NewMockLDAPConnection(ctrl) ldapClient := NewLDAPUserProviderWithFactory(schema.LDAPAuthenticationBackendConfiguration{ - URL: "ldap://127.0.0.1:389", - User: "cn=admin,dc=example,dc=com", - UsernameAttribute: "uid", - UsersFilter: "(&({username_attribute}={input})(&(objectCategory=person)(objectClass=user)))", - Password: "password", - AdditionalUsersDN: "ou=users", - BaseDN: "dc=example,dc=com", - MailAttribute: "mail", + URL: "ldap://127.0.0.1:389", + User: "cn=admin,dc=example,dc=com", + UsernameAttribute: "uid", + UsersFilter: "(&({username_attribute}={input})(&(objectCategory=person)(objectClass=user)))", + Password: "password", + AdditionalUsersDN: "ou=users", + BaseDN: "dc=example,dc=com", + MailAttribute: "mail", + DisplayNameAttribute: "displayname", }, mockFactory) mockConn.EXPECT(). @@ -199,14 +202,15 @@ func TestShouldNotCrashWhenGroupsAreNotRetrievedFromLDAP(t *testing.T) { mockConn := NewMockLDAPConnection(ctrl) ldapClient := NewLDAPUserProviderWithFactory(schema.LDAPAuthenticationBackendConfiguration{ - URL: "ldap://127.0.0.1:389", - User: "cn=admin,dc=example,dc=com", - Password: "password", - UsernameAttribute: "uid", - MailAttribute: "mail", - UsersFilter: "uid={input}", - AdditionalUsersDN: "ou=users", - BaseDN: "dc=example,dc=com", + URL: "ldap://127.0.0.1:389", + User: "cn=admin,dc=example,dc=com", + Password: "password", + UsernameAttribute: "uid", + MailAttribute: "mail", + DisplayNameAttribute: "displayname", + UsersFilter: "uid={input}", + AdditionalUsersDN: "ou=users", + BaseDN: "dc=example,dc=com", }, mockFactory) mockFactory.EXPECT(). @@ -230,6 +234,10 @@ func TestShouldNotCrashWhenGroupsAreNotRetrievedFromLDAP(t *testing.T) { { DN: "uid=test,dc=example,dc=com", Attributes: []*ldap.EntryAttribute{ + { + Name: "displayname", + Values: []string{"John Doe"}, + }, { Name: "mail", Values: []string{"test@example.com"}, @@ -250,6 +258,7 @@ func TestShouldNotCrashWhenGroupsAreNotRetrievedFromLDAP(t *testing.T) { assert.ElementsMatch(t, details.Groups, []string{}) assert.ElementsMatch(t, details.Emails, []string{"test@example.com"}) + assert.Equal(t, details.DisplayName, "John Doe") assert.Equal(t, details.Username, "john") } @@ -318,14 +327,15 @@ func TestShouldReturnUsernameFromLDAP(t *testing.T) { mockConn := NewMockLDAPConnection(ctrl) ldapClient := NewLDAPUserProviderWithFactory(schema.LDAPAuthenticationBackendConfiguration{ - URL: "ldap://127.0.0.1:389", - User: "cn=admin,dc=example,dc=com", - Password: "password", - UsernameAttribute: "uid", - MailAttribute: "mail", - UsersFilter: "uid={input}", - AdditionalUsersDN: "ou=users", - BaseDN: "dc=example,dc=com", + URL: "ldap://127.0.0.1:389", + User: "cn=admin,dc=example,dc=com", + Password: "password", + UsernameAttribute: "uid", + MailAttribute: "mail", + DisplayNameAttribute: "displayname", + UsersFilter: "uid={input}", + AdditionalUsersDN: "ou=users", + BaseDN: "dc=example,dc=com", }, mockFactory) mockFactory.EXPECT(). @@ -349,6 +359,10 @@ func TestShouldReturnUsernameFromLDAP(t *testing.T) { { DN: "uid=test,dc=example,dc=com", Attributes: []*ldap.EntryAttribute{ + { + Name: "displayname", + Values: []string{"John Doe"}, + }, { Name: "mail", Values: []string{"test@example.com"}, @@ -369,5 +383,6 @@ func TestShouldReturnUsernameFromLDAP(t *testing.T) { assert.ElementsMatch(t, details.Groups, []string{"group1", "group2"}) assert.ElementsMatch(t, details.Emails, []string{"test@example.com"}) + assert.Equal(t, details.DisplayName, "John Doe") assert.Equal(t, details.Username, "John") } diff --git a/internal/authentication/types.go b/internal/authentication/types.go index 5fbfbe7af..d2857ddcb 100644 --- a/internal/authentication/types.go +++ b/internal/authentication/types.go @@ -2,7 +2,8 @@ package authentication // UserDetails represent the details retrieved for a given user. type UserDetails struct { - Username string - Emails []string - Groups []string + Username string + DisplayName string + Emails []string + Groups []string } diff --git a/internal/configuration/schema/authentication.go b/internal/configuration/schema/authentication.go index 65763a99e..fb2da3653 100644 --- a/internal/configuration/schema/authentication.go +++ b/internal/configuration/schema/authentication.go @@ -2,18 +2,19 @@ package schema // LDAPAuthenticationBackendConfiguration represents the configuration related to LDAP server. type LDAPAuthenticationBackendConfiguration struct { - URL string `mapstructure:"url"` - SkipVerify bool `mapstructure:"skip_verify"` - BaseDN string `mapstructure:"base_dn"` - AdditionalUsersDN string `mapstructure:"additional_users_dn"` - UsersFilter string `mapstructure:"users_filter"` - AdditionalGroupsDN string `mapstructure:"additional_groups_dn"` - GroupsFilter string `mapstructure:"groups_filter"` - GroupNameAttribute string `mapstructure:"group_name_attribute"` - UsernameAttribute string `mapstructure:"username_attribute"` - MailAttribute string `mapstructure:"mail_attribute"` - User string `mapstructure:"user"` - Password string `mapstructure:"password"` + URL string `mapstructure:"url"` + SkipVerify bool `mapstructure:"skip_verify"` + BaseDN string `mapstructure:"base_dn"` + AdditionalUsersDN string `mapstructure:"additional_users_dn"` + UsersFilter string `mapstructure:"users_filter"` + AdditionalGroupsDN string `mapstructure:"additional_groups_dn"` + GroupsFilter string `mapstructure:"groups_filter"` + GroupNameAttribute string `mapstructure:"group_name_attribute"` + UsernameAttribute string `mapstructure:"username_attribute"` + MailAttribute string `mapstructure:"mail_attribute"` + DisplayNameAttribute string `mapstructure:"display_name_attribute"` + User string `mapstructure:"user"` + Password string `mapstructure:"password"` } // FileAuthenticationBackendConfiguration represents the configuration related to file-based backend. @@ -69,6 +70,7 @@ var DefaultPasswordSHA512Configuration = PasswordConfiguration{ // DefaultLDAPAuthenticationBackendConfiguration represents the default LDAP config. var DefaultLDAPAuthenticationBackendConfiguration = LDAPAuthenticationBackendConfiguration{ - MailAttribute: "mail", - GroupNameAttribute: "cn", + MailAttribute: "mail", + DisplayNameAttribute: "displayname", + GroupNameAttribute: "cn", } diff --git a/internal/configuration/validator/authentication.go b/internal/configuration/validator/authentication.go index ef6eac53c..3c5584c80 100644 --- a/internal/configuration/validator/authentication.go +++ b/internal/configuration/validator/authentication.go @@ -151,6 +151,10 @@ func validateLdapAuthenticationBackend(configuration *schema.LDAPAuthenticationB if configuration.MailAttribute == "" { configuration.MailAttribute = schema.DefaultLDAPAuthenticationBackendConfiguration.MailAttribute } + + if configuration.DisplayNameAttribute == "" { + configuration.DisplayNameAttribute = schema.DefaultLDAPAuthenticationBackendConfiguration.DisplayNameAttribute + } } // ValidateAuthenticationBackend validates and update authentication backend configuration. diff --git a/internal/configuration/validator/const.go b/internal/configuration/validator/const.go index f58836024..94f25e221 100644 --- a/internal/configuration/validator/const.go +++ b/internal/configuration/validator/const.go @@ -98,6 +98,7 @@ var validKeys = []string{ "authentication_backend.ldap.groups_filter", "authentication_backend.ldap.group_name_attribute", "authentication_backend.ldap.mail_attribute", + "authentication_backend.ldap.display_name_attribute", "authentication_backend.ldap.user", "authentication_backend.ldap.password", diff --git a/internal/handlers/handler_extended_configuration.go b/internal/handlers/handler_extended_configuration.go index 852de58e8..2a06f3e90 100644 --- a/internal/handlers/handler_extended_configuration.go +++ b/internal/handlers/handler_extended_configuration.go @@ -8,6 +8,7 @@ import ( // ExtendedConfigurationBody the content returned by extended configuration endpoint. type ExtendedConfigurationBody struct { AvailableMethods MethodList `json:"available_methods"` + DisplayName string `json:"display_name"` SecondFactorEnabled bool `json:"second_factor_enabled"` // whether second factor is enabled or not. TOTPPeriod int `json:"totp_period"` } @@ -16,6 +17,7 @@ type ExtendedConfigurationBody struct { func ExtendedConfigurationGet(ctx *middlewares.AutheliaCtx) { body := ExtendedConfigurationBody{} body.AvailableMethods = MethodList{authentication.TOTP, authentication.U2F} + body.DisplayName = ctx.GetSession().DisplayName body.TOTPPeriod = ctx.Configuration.TOTP.Period if ctx.Configuration.DuoAPI != nil { diff --git a/internal/handlers/handler_firstfactor.go b/internal/handlers/handler_firstfactor.go index 978cb8a66..fb1c3932e 100644 --- a/internal/handlers/handler_firstfactor.go +++ b/internal/handlers/handler_firstfactor.go @@ -163,6 +163,7 @@ func FirstFactorPost(msInitialDelay time.Duration, delayEnabled bool) middleware // And set those information in the new session. userSession := ctx.GetSession() userSession.Username = userDetails.Username + userSession.DisplayName = userDetails.DisplayName userSession.Groups = userDetails.Groups userSession.Emails = userDetails.Emails userSession.AuthenticationLevel = authentication.OneFactor diff --git a/internal/handlers/handler_verify.go b/internal/handlers/handler_verify.go index f42815493..8c936c2d2 100644 --- a/internal/handlers/handler_verify.go +++ b/internal/handlers/handler_verify.go @@ -268,6 +268,7 @@ func generateVerifySessionHasUpToDateProfileTraceLogs(ctx *middlewares.AutheliaC details *authentication.UserDetails) { groupsAdded, groupsRemoved := utils.StringSlicesDelta(userSession.Groups, details.Groups) emailsAdded, emailsRemoved := utils.StringSlicesDelta(userSession.Emails, details.Emails) + nameDelta := userSession.DisplayName != details.DisplayName // Check Groups. var groupsDelta []string @@ -300,6 +301,13 @@ func generateVerifySessionHasUpToDateProfileTraceLogs(ctx *middlewares.AutheliaC } else { ctx.Logger.Tracef("No updated emails detected for %s", userSession.Username) } + + // Check Name. + if nameDelta { + ctx.Logger.Tracef("Updated display name detected for %s. Added: %s. Removed: %s.", userSession.Username, details.DisplayName, userSession.DisplayName) + } else { + ctx.Logger.Tracef("No updated display name detected for %s", userSession.Username) + } } func verifySessionHasUpToDateProfile(ctx *middlewares.AutheliaCtx, targetURL *url.URL, userSession *session.UserSession, @@ -318,10 +326,11 @@ func verifySessionHasUpToDateProfile(ctx *middlewares.AutheliaCtx, targetURL *ur return err } - groupsDiff := utils.IsStringSlicesDifferent(userSession.Groups, details.Groups) emailsDiff := utils.IsStringSlicesDifferent(userSession.Emails, details.Emails) + groupsDiff := utils.IsStringSlicesDifferent(userSession.Groups, details.Groups) + nameDiff := userSession.DisplayName != details.DisplayName - if !groupsDiff && !emailsDiff { + if !groupsDiff && !emailsDiff && !nameDiff { ctx.Logger.Tracef("Updated profile not detected for %s.", userSession.Username) // Only update TTL if the user has a interval set. // We get to this check when there were no changes. @@ -334,11 +343,12 @@ func verifySessionHasUpToDateProfile(ctx *middlewares.AutheliaCtx, targetURL *ur } } else { ctx.Logger.Debugf("Updated profile detected for %s.", userSession.Username) - if ctx.Logger.Level.String() == "trace" { + if ctx.Configuration.LogLevel == "trace" { generateVerifySessionHasUpToDateProfileTraceLogs(ctx, userSession, details) } - userSession.Groups = details.Groups userSession.Emails = details.Emails + userSession.Groups = details.Groups + userSession.DisplayName = details.DisplayName // Only update TTL if the user has a interval set. if refreshProfileInterval != schema.RefreshIntervalAlways { diff --git a/internal/session/types.go b/internal/session/types.go index 45a4cdf22..a7f3ce880 100644 --- a/internal/session/types.go +++ b/internal/session/types.go @@ -5,7 +5,6 @@ import ( "github.com/fasthttp/session/v2" "github.com/fasthttp/session/v2/providers/redis" - "github.com/tstranex/u2f" "github.com/authelia/authelia/internal/authentication" @@ -26,7 +25,8 @@ type U2FRegistration struct { // UserSession is the structure representing the session of a user. type UserSession struct { - Username string + Username string + DisplayName string // TODO(c.michaud): move groups out of the session. Groups []string Emails []string diff --git a/internal/suites/BypassAll/users.yml b/internal/suites/BypassAll/users.yml index 4f1a7e4e8..475800c0f 100644 --- a/internal/suites/BypassAll/users.yml +++ b/internal/suites/BypassAll/users.yml @@ -7,6 +7,7 @@ # List of users users: john: + displayname: "John Doe" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: john.doe@authelia.com groups: @@ -14,16 +15,19 @@ users: - dev harry: + displayname: "Harry Potter" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: harry.potter@authelia.com groups: [] bob: + displayname: "Bob Dylan" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: bob.dylan@authelia.com groups: - dev james: + displayname: "James Dean" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: james.dean@authelia.com \ No newline at end of file diff --git a/internal/suites/Docker/users.yml b/internal/suites/Docker/users.yml index a372d30c9..475800c0f 100644 --- a/internal/suites/Docker/users.yml +++ b/internal/suites/Docker/users.yml @@ -1,20 +1,33 @@ +############################################################### +# Users Database # +############################################################### + +# This file can be used if you do not have an LDAP set up. + +# List of users users: - bob: - password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" - email: bob.dylan@authelia.com - groups: - - dev - harry: - password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" - email: harry.potter@authelia.com - groups: [] - james: - password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" - email: james.dean@authelia.com - groups: [] john: - password: "$6$rounds=50000$LnfgDsc2WD8F2qNf$0gcCt8jlqAGZRv2ee3mCFsfAr1P4N7kESWEf36Xtw6OjkhAcQuGVOBHXp0lFuZbppa7YlgHk3VD28aSQu9U9S1" + displayname: "John Doe" + password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: john.doe@authelia.com groups: - admins - dev + + harry: + displayname: "Harry Potter" + password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" + email: harry.potter@authelia.com + groups: [] + + bob: + displayname: "Bob Dylan" + password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" + email: bob.dylan@authelia.com + groups: + - dev + + james: + displayname: "James Dean" + password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" + email: james.dean@authelia.com \ No newline at end of file diff --git a/internal/suites/DuoPush/users.yml b/internal/suites/DuoPush/users.yml index 4f1a7e4e8..475800c0f 100644 --- a/internal/suites/DuoPush/users.yml +++ b/internal/suites/DuoPush/users.yml @@ -7,6 +7,7 @@ # List of users users: john: + displayname: "John Doe" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: john.doe@authelia.com groups: @@ -14,16 +15,19 @@ users: - dev harry: + displayname: "Harry Potter" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: harry.potter@authelia.com groups: [] bob: + displayname: "Bob Dylan" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: bob.dylan@authelia.com groups: - dev james: + displayname: "James Dean" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: james.dean@authelia.com \ No newline at end of file diff --git a/internal/suites/HAProxy/users.yml b/internal/suites/HAProxy/users.yml index 4f1a7e4e8..475800c0f 100644 --- a/internal/suites/HAProxy/users.yml +++ b/internal/suites/HAProxy/users.yml @@ -7,6 +7,7 @@ # List of users users: john: + displayname: "John Doe" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: john.doe@authelia.com groups: @@ -14,16 +15,19 @@ users: - dev harry: + displayname: "Harry Potter" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: harry.potter@authelia.com groups: [] bob: + displayname: "Bob Dylan" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: bob.dylan@authelia.com groups: - dev james: + displayname: "James Dean" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: james.dean@authelia.com \ No newline at end of file diff --git a/internal/suites/Mariadb/users.yml b/internal/suites/Mariadb/users.yml index 4f1a7e4e8..475800c0f 100644 --- a/internal/suites/Mariadb/users.yml +++ b/internal/suites/Mariadb/users.yml @@ -7,6 +7,7 @@ # List of users users: john: + displayname: "John Doe" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: john.doe@authelia.com groups: @@ -14,16 +15,19 @@ users: - dev harry: + displayname: "Harry Potter" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: harry.potter@authelia.com groups: [] bob: + displayname: "Bob Dylan" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: bob.dylan@authelia.com groups: - dev james: + displayname: "James Dean" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: james.dean@authelia.com \ No newline at end of file diff --git a/internal/suites/MySQL/users.yml b/internal/suites/MySQL/users.yml index 4f1a7e4e8..475800c0f 100644 --- a/internal/suites/MySQL/users.yml +++ b/internal/suites/MySQL/users.yml @@ -7,6 +7,7 @@ # List of users users: john: + displayname: "John Doe" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: john.doe@authelia.com groups: @@ -14,16 +15,19 @@ users: - dev harry: + displayname: "Harry Potter" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: harry.potter@authelia.com groups: [] bob: + displayname: "Bob Dylan" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: bob.dylan@authelia.com groups: - dev james: + displayname: "James Dean" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: james.dean@authelia.com \ No newline at end of file diff --git a/internal/suites/NetworkACL/users.yml b/internal/suites/NetworkACL/users.yml index 4f1a7e4e8..475800c0f 100644 --- a/internal/suites/NetworkACL/users.yml +++ b/internal/suites/NetworkACL/users.yml @@ -7,6 +7,7 @@ # List of users users: john: + displayname: "John Doe" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: john.doe@authelia.com groups: @@ -14,16 +15,19 @@ users: - dev harry: + displayname: "Harry Potter" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: harry.potter@authelia.com groups: [] bob: + displayname: "Bob Dylan" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: bob.dylan@authelia.com groups: - dev james: + displayname: "James Dean" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: james.dean@authelia.com \ No newline at end of file diff --git a/internal/suites/OneFactorOnly/users.yml b/internal/suites/OneFactorOnly/users.yml index 4f1a7e4e8..475800c0f 100644 --- a/internal/suites/OneFactorOnly/users.yml +++ b/internal/suites/OneFactorOnly/users.yml @@ -7,6 +7,7 @@ # List of users users: john: + displayname: "John Doe" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: john.doe@authelia.com groups: @@ -14,16 +15,19 @@ users: - dev harry: + displayname: "Harry Potter" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: harry.potter@authelia.com groups: [] bob: + displayname: "Bob Dylan" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: bob.dylan@authelia.com groups: - dev james: + displayname: "James Dean" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: james.dean@authelia.com \ No newline at end of file diff --git a/internal/suites/PathPrefix/users.yml b/internal/suites/PathPrefix/users.yml index 4f1a7e4e8..475800c0f 100644 --- a/internal/suites/PathPrefix/users.yml +++ b/internal/suites/PathPrefix/users.yml @@ -7,6 +7,7 @@ # List of users users: john: + displayname: "John Doe" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: john.doe@authelia.com groups: @@ -14,16 +15,19 @@ users: - dev harry: + displayname: "Harry Potter" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: harry.potter@authelia.com groups: [] bob: + displayname: "Bob Dylan" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: bob.dylan@authelia.com groups: - dev james: + displayname: "James Dean" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: james.dean@authelia.com \ No newline at end of file diff --git a/internal/suites/Postgres/users.yml b/internal/suites/Postgres/users.yml index 4f1a7e4e8..475800c0f 100644 --- a/internal/suites/Postgres/users.yml +++ b/internal/suites/Postgres/users.yml @@ -7,6 +7,7 @@ # List of users users: john: + displayname: "John Doe" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: john.doe@authelia.com groups: @@ -14,16 +15,19 @@ users: - dev harry: + displayname: "Harry Potter" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: harry.potter@authelia.com groups: [] bob: + displayname: "Bob Dylan" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: bob.dylan@authelia.com groups: - dev james: + displayname: "James Dean" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: james.dean@authelia.com \ No newline at end of file diff --git a/internal/suites/ShortTimeouts/users.yml b/internal/suites/ShortTimeouts/users.yml index 4f1a7e4e8..475800c0f 100644 --- a/internal/suites/ShortTimeouts/users.yml +++ b/internal/suites/ShortTimeouts/users.yml @@ -7,6 +7,7 @@ # List of users users: john: + displayname: "John Doe" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: john.doe@authelia.com groups: @@ -14,16 +15,19 @@ users: - dev harry: + displayname: "Harry Potter" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: harry.potter@authelia.com groups: [] bob: + displayname: "Bob Dylan" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: bob.dylan@authelia.com groups: - dev james: + displayname: "James Dean" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: james.dean@authelia.com \ No newline at end of file diff --git a/internal/suites/Standalone/users.yml b/internal/suites/Standalone/users.yml index 5ce676efc..475800c0f 100644 --- a/internal/suites/Standalone/users.yml +++ b/internal/suites/Standalone/users.yml @@ -1,20 +1,33 @@ +############################################################### +# Users Database # +############################################################### + +# This file can be used if you do not have an LDAP set up. + +# List of users users: - bob: - password: $6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/ - email: bob.dylan@authelia.com - groups: - - dev - harry: - password: $6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/ - email: harry.potter@authelia.com - groups: [] - james: - password: $6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/ - email: james.dean@authelia.com - groups: [] john: - password: $6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/ + displayname: "John Doe" + password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: john.doe@authelia.com groups: - - admins - - dev + - admins + - dev + + harry: + displayname: "Harry Potter" + password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" + email: harry.potter@authelia.com + groups: [] + + bob: + displayname: "Bob Dylan" + password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" + email: bob.dylan@authelia.com + groups: + - dev + + james: + displayname: "James Dean" + password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" + email: james.dean@authelia.com \ No newline at end of file diff --git a/internal/suites/Traefik/users.yml b/internal/suites/Traefik/users.yml index 4f1a7e4e8..475800c0f 100644 --- a/internal/suites/Traefik/users.yml +++ b/internal/suites/Traefik/users.yml @@ -7,6 +7,7 @@ # List of users users: john: + displayname: "John Doe" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: john.doe@authelia.com groups: @@ -14,16 +15,19 @@ users: - dev harry: + displayname: "Harry Potter" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: harry.potter@authelia.com groups: [] bob: + displayname: "Bob Dylan" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: bob.dylan@authelia.com groups: - dev james: + displayname: "James Dean" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: james.dean@authelia.com \ No newline at end of file diff --git a/internal/suites/Traefik2/users.yml b/internal/suites/Traefik2/users.yml index 4f1a7e4e8..475800c0f 100644 --- a/internal/suites/Traefik2/users.yml +++ b/internal/suites/Traefik2/users.yml @@ -7,6 +7,7 @@ # List of users users: john: + displayname: "John Doe" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: john.doe@authelia.com groups: @@ -14,16 +15,19 @@ users: - dev harry: + displayname: "Harry Potter" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: harry.potter@authelia.com groups: [] bob: + displayname: "Bob Dylan" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: bob.dylan@authelia.com groups: - dev james: + displayname: "James Dean" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" email: james.dean@authelia.com \ No newline at end of file diff --git a/internal/suites/example/compose/ldap/ldif/base.ldif b/internal/suites/example/compose/ldap/ldif/base.ldif index 40174f198..5e267486a 100644 --- a/internal/suites/example/compose/ldap/ldif/base.ldif +++ b/internal/suites/example/compose/ldap/ldif/base.ldif @@ -23,6 +23,7 @@ objectclass: top dn: cn=John Doe (external),ou=users,dc=example,dc=com cn: John Doe (external) +displayname: John Doe givenName: John objectclass: inetOrgPerson objectclass: top @@ -33,6 +34,7 @@ userpassword: {CRYPT}$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQ dn: cn=Harry Potter,ou=users,dc=example,dc=com cn: Harry Potter +displayname: Harry Potter givenName: Harry objectclass: inetOrgPerson objectclass: top @@ -43,6 +45,7 @@ userpassword: {CRYPT}$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQ dn: cn=Bob Dylan,ou=users,dc=example,dc=com cn: Bob Dylan +displayname: Bob Dylan givenName: Bob objectclass: inetOrgPerson objectclass: top @@ -53,6 +56,7 @@ userpassword: {CRYPT}$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQ dn: cn=James Dean,ou=users,dc=example,dc=com cn: James Dean +displayname: James Dean givenName: James objectclass: inetOrgPerson objectclass: top @@ -63,6 +67,7 @@ userpassword: {CRYPT}$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQ dn: cn=Billy Blackhat,ou=users,dc=example,dc=com cn: Billy Blackhat +displayname: Billy Blackhat givenName: Billy objectclass: inetOrgPerson objectclass: top diff --git a/web/src/models/Configuration.ts b/web/src/models/Configuration.ts index da022563a..56b452979 100644 --- a/web/src/models/Configuration.ts +++ b/web/src/models/Configuration.ts @@ -7,6 +7,7 @@ export interface Configuration { export interface ExtendedConfiguration { available_methods: Set; + display_name: string; second_factor_enabled: boolean; totp_period: number; } \ No newline at end of file diff --git a/web/src/services/Configuration.ts b/web/src/services/Configuration.ts index a0c7530d2..eb0dd002e 100644 --- a/web/src/services/Configuration.ts +++ b/web/src/services/Configuration.ts @@ -9,6 +9,7 @@ export async function getConfiguration(): Promise { interface ExtendedConfigurationPayload { available_methods: Method2FA[]; + display_name: string; second_factor_enabled: boolean; totp_period: number; } diff --git a/web/src/views/LoginPortal/AuthenticatedView/AuthenticatedView.tsx b/web/src/views/LoginPortal/AuthenticatedView/AuthenticatedView.tsx index 44e33ffe9..dc6ee2672 100644 --- a/web/src/views/LoginPortal/AuthenticatedView/AuthenticatedView.tsx +++ b/web/src/views/LoginPortal/AuthenticatedView/AuthenticatedView.tsx @@ -6,7 +6,7 @@ import { LogoutRoute as SignOutRoute } from "../../../Routes"; import Authenticated from "../Authenticated"; export interface Props { - username: string; + name: string; } export default function (props: Props) { @@ -20,7 +20,7 @@ export default function (props: Props) { return ( diff --git a/web/src/views/LoginPortal/LoginPortal.tsx b/web/src/views/LoginPortal/LoginPortal.tsx index 04bd565fa..e309055db 100644 --- a/web/src/views/LoginPortal/LoginPortal.tsx +++ b/web/src/views/LoginPortal/LoginPortal.tsx @@ -128,7 +128,6 @@ export default function (props: Props) { {state && userInfo && configuration ? : null} - {state ? : null} + {configuration ? : null} diff --git a/web/src/views/LoginPortal/SecondFactor/SecondFactorForm.tsx b/web/src/views/LoginPortal/SecondFactor/SecondFactorForm.tsx index d26f2cc62..bc2e0ef63 100644 --- a/web/src/views/LoginPortal/SecondFactor/SecondFactorForm.tsx +++ b/web/src/views/LoginPortal/SecondFactor/SecondFactorForm.tsx @@ -25,7 +25,6 @@ import { AuthenticationLevel } from "../../../services/State"; const EMAIL_SENT_NOTIFICATION = "An email has been sent to your address to complete the process."; export interface Props { - username: string; authenticationLevel: AuthenticationLevel; userInfo: UserInfo; @@ -89,7 +88,7 @@ export default function (props: Props) { return (