This is a copy of issue 1863, moved here for discussion.
Authentication in Caddy currently seems to be a bit of a mess. I would like to introduce you to a concept of how Caddy could improve this situation drastically:
The Caddy core is responsible for checking permissions on requests, plugins provide user authentication and authorization.
The basicauth plugin may for example authenticate a user and then save that a certain request is made by a particular user. Another plugin (e.g. providing a static list of permissions) is then queried for the permissions that this user has. Permission could look like this:
auth_users {
# Alice is allowed to access anything (explicit allow default rule), but is
# only allowed to use GET and HEAD HTTP methods on paths starting with /api
Alice {
default allow
GET,HEAD /api
}
# Bob is allowed to access anything (allow default rule from default user),
# and is allowed to use GET, HEAD, POST, PUT and DELETE HTTP methods on
# paths starting with /api
Bob {
rw /api # rw is a shortcut for GET,HEAD,POST,PUT,DELETE
}
# Charlie is only allowed to access his own space in /charlie and nothing else.
Charlie {
default deny
* /charlie
}
# * specifies default rules for all authenticated users. If omitted,
# default rule is "deny". If no path of an authenticated user matches,
# these paths will be checked before reverting to their own or this
# default rule.
* {
default allow
- /api
}
# - specifies the rules if authentication failed / the user did not
# provide authentication.
- {
default deny
ro /public # ro is a shortcut for GET,HEAD
}
}
Methods are HTTP methods and HTTP commands:
GET, POST, HEAD, PUT, MOVE, DELETE, WEBSOCKET (the permission to initiate a websocket upgrade), etc…
Added/Changed Caddyfile directives:
-
auth
defines a plugin that both handles user authentication and authorization -
auth_users
defines a list of plugins and their order in which they are tried to authenticate a user -
auth_perms
either defines a static list of permissions (as above) or defines a plugin that handles user authorization
There may be only one list/plugin defining permissions per vhost, but many plugins doing authorization.
There numerous great use cases for such a system:
# use TLS client certificates for authentication (CN=username),
# then ask a backend service for permissions of that user
auth_users tls
auth_perms request {
10.0.0.1/auth/{username}
}
# use a backend service for both authentication and authorization
auth request {
# note: both HTTP basic auth and cookies are forwarded
10.0.0.1/auth
}
# or completely defined inside the Caddy config file
auth_users basicauth {
Alice [password]
Bob [password]
Charlie [password]
}
auth_perms {
Alice {
rw /api
}
* {
default allow
r /api
}
- {
default deny
r /public
}
}
Such a system would really bring much more flexibility and power to Caddy, as it the can integrate seamlessly into any existing environment for handling authentication and authorization, making it easy to extend existing web applications with powerful Caddy plugins. This is a big thing and something I think a lot of people would love to have.
I hope I have explained the concept enough to make sense, I will of course try to explain further if that is not the case.
The challenge in creating such a central authentication management is to keep the system as simple as possible. That was my aim for this concept, but I am pretty sure that I missed something.
Keep up the great work!