feat: allow disabling password check for delegated authentication

This commit is contained in:
Henrique Dias
2024-08-01 21:53:58 +02:00
parent 373b2ec931
commit d3bee98000
5 changed files with 56 additions and 7 deletions
+8 -1
View File
@@ -106,7 +106,14 @@ cors:
- Content-Length
- Content-Range
# The list of users. If users is empty, then there will be no authentication.
# The list of users. If the list is empty, then there will be no authentication.
# Otherwise, basic authentication will automatically be configured.
#
# If you're delegating the authentication to a different service, you can proxy
# the username using basic authentication, and then disable webdav's password
# check using the option:
#
# noPassword: true
users:
# Example 'admin' user with plaintext password.
- username: admin
+3 -1
View File
@@ -32,6 +32,7 @@ type Config struct {
Key string
Prefix string
NoSniff bool
NoPassword bool
Log Log
CORS CORS
Users []User
@@ -77,6 +78,7 @@ func ParseConfig(filename string, flags *pflag.FlagSet) (*Config, error) {
v.SetDefault("Permissions", "R")
v.SetDefault("Debug", false)
v.SetDefault("NoSniff", false)
v.SetDefault("NoPassword", false)
v.SetDefault("Log.Format", "console")
v.SetDefault("Log.Outputs", []string{"stderr"})
v.SetDefault("Log.Colors", true)
@@ -159,7 +161,7 @@ func (c *Config) Validate() error {
}
for _, u := range c.Users {
err := u.Validate()
err := u.Validate(c.NoPassword)
if err != nil {
return fmt.Errorf("invalid config: %w", err)
}
+9 -3
View File
@@ -17,12 +17,14 @@ type handlerUser struct {
}
type Handler struct {
user *handlerUser
users map[string]*handlerUser
noPassword bool
user *handlerUser
users map[string]*handlerUser
}
func NewHandler(c *Config) (http.Handler, error) {
h := &Handler{
noPassword: c.NoPassword,
user: &handlerUser{
User: User{
UserPermissions: c.UserPermissions,
@@ -67,6 +69,10 @@ func NewHandler(c *Config) (http.Handler, error) {
zap.L().Warn("unprotected config: no users have been set, so no authentication will be used")
}
if c.NoPassword {
zap.L().Warn("unprotected config: password check is disabled, only intended when delegating authentication to another service")
}
return h, nil
}
@@ -92,7 +98,7 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}
if !user.checkPassword(password) {
if !h.noPassword && !user.checkPassword(password) {
zap.L().Info("invalid password", zap.String("username", username), zap.String("remote_address", r.RemoteAddr))
http.Error(w, "Not authorized", http.StatusUnauthorized)
return
+34
View File
@@ -183,6 +183,40 @@ users:
})
}
func TestServerAuthenticationNoPassword(t *testing.T) {
t.Parallel()
dir := makeTestDirectory(t, map[string][]byte{
"foo.txt": []byte("foo"),
"sub/bar.txt": []byte("bar"),
})
srv := makeTestServer(t, fmt.Sprintf(`
directory: %s
noPassword: true
permissions: CRUD
users:
- username: basic
`, dir))
t.Run("Basic Auth", func(t *testing.T) {
t.Parallel()
client := gowebdav.NewClient(srv.URL, "basic", "")
files, err := client.ReadDir("/")
require.NoError(t, err)
require.Len(t, files, 2)
})
t.Run("Unauthorized Wrong User", func(t *testing.T) {
t.Parallel()
client := gowebdav.NewClient(srv.URL, "wrong", "")
_, err := client.ReadDir("/")
require.ErrorContains(t, err, "401")
})
}
func TestServerRules(t *testing.T) {
t.Parallel()
+2 -2
View File
@@ -24,12 +24,12 @@ func (u User) checkPassword(input string) bool {
return u.Password == input
}
func (u *User) Validate() error {
func (u *User) Validate(noPassword bool) error {
if u.Username == "" {
return errors.New("invalid user: username must be set")
}
if u.Password == "" {
if u.Password == "" && !noPassword {
return fmt.Errorf("invalid user %q: password must be set", u.Username)
} else if strings.HasPrefix(u.Password, "{env}") {