Skip to content

Commit

Permalink
feat: allow disabling password check for delegated authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
hacdias committed Aug 1, 2024
1 parent 373b2ec commit 36cdc81
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 7 deletions.
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion lib/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type Config struct {
Key string
Prefix string
NoSniff bool
NoPassword bool
Log Log
CORS CORS
Users []User
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
}
Expand Down
12 changes: 9 additions & 3 deletions lib/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
}

Expand All @@ -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
Expand Down
24 changes: 24 additions & 0 deletions lib/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,30 @@ 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))

client := gowebdav.NewClient(srv.URL, "basic", "")

files, err := client.ReadDir("/")
require.NoError(t, err)
require.Len(t, files, 2)
}

func TestServerRules(t *testing.T) {
t.Parallel()

Expand Down
4 changes: 2 additions & 2 deletions lib/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -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}") {

Expand Down

0 comments on commit 36cdc81

Please sign in to comment.