@mholt has announced that Caddy 2 may hit stable by early next year. Based on a quick glance at the new docs, there are lots of changes to how plugins (soon to be called modules) work, and it will likely require a complete rewrite to support JWT auth in Caddy 2. I plan to post a deprecation notice on the readme so people know that no further development will happen on this plugin unless it's to address a security vulnerability.
I haven't decided whether I'll port this to the new module system as I rarely use JWT anymore. I think paseto has a better design and less foot guns if you are starting from scratch on a new application.
This issue is meant as a discussion area for a potential port to Caddy v2. For anyone considering an auth module for Caddy, I'd offer the following ideas based on several years of experience hearing about various use cases.
Eliminate all Caddyfile-style configuration directives that express auth logic
One of the major drawbacks of v1-style plugins was the use of the Caddyfile for expressing auth logic. While the system of allow user bob worked, it's awkward to use a configuration language to express logic. This is a recurring problem with projects that use config files to express branching logic that depends on external state (e.g., Ansible, Kubernetes Helm templates, etc.) where if-then-else logic is bolted on to a declarative config file format. This can be solved by using Starlark as suggested below, but there may be other ways to move this logic outside Caddy configuration and into an environment that is more suitable to scripting. One option is to delegate auth decisions to a separate microservice as in caddy-extauth, so that authorization can be controlled by the user in any language, but easily integrated as a middleware-type plugin.
The new module should take advantage of the integrated Starlark scripting capability to provide a platform for users to express advanced auth flows.
Starlark has a python-like syntax that would allow someone to express all kinds of auth flows and special cases that are awkwardly handled as edge cases in this plugin. Things like extracting tokens from oddly named cookies, stripping claim prefixes, and returning non-standard HTTP responses would be relatively easy in Starlark and keep these edge cases out of the module code.
token = token_from_cookie("my-auth-token")
secret = secret_from_env("JWT_SECRET")
if claim(token, "user") == "bob" and valid(token, HS256, secret):
return ok()
else:
return redirect(301, "https://mysite.com/login")
The starlark runtime can be injected with custom functions (implemented in Go), such as valid(token, algorithm, secret) and claim(token, field), that would extract claims and validate tokens, return various HTTP responses, set headers, allow fine grained auth rules for different paths, etc. so that nearly any use case can be under the control of the user while keeping the module code free of special cases.
Address drawbacks of delegating auth decisions to user scripts
One downside of the ideas above is that it would be a lot easier for a user to shoot themselves in the foot unless they are familiar with the design errors in JWT. There are several known vulnerabilities that arise from the JWT specification, like attacks based on monkeying with the alg header field in order to control how JWT validation is applied.
Care should be taken in what functions are supplied to the user so that the design of the API prevents them from insecurely validating tokens.
@mholt has announced that Caddy 2 may hit stable by early next year. Based on a quick glance at the new docs, there are lots of changes to how plugins (soon to be called modules) work, and it will likely require a complete rewrite to support JWT auth in Caddy 2. I plan to post a deprecation notice on the readme so people know that no further development will happen on this plugin unless it's to address a security vulnerability.
I haven't decided whether I'll port this to the new module system as I rarely use JWT anymore. I think paseto has a better design and less foot guns if you are starting from scratch on a new application.
This issue is meant as a discussion area for a potential port to Caddy v2. For anyone considering an auth module for Caddy, I'd offer the following ideas based on several years of experience hearing about various use cases.
Eliminate all Caddyfile-style configuration directives that express auth logic
One of the major drawbacks of v1-style plugins was the use of the Caddyfile for expressing auth logic. While the system of
allow user bobworked, it's awkward to use a configuration language to express logic. This is a recurring problem with projects that use config files to express branching logic that depends on external state (e.g., Ansible, Kubernetes Helm templates, etc.) where if-then-else logic is bolted on to a declarative config file format. This can be solved by using Starlark as suggested below, but there may be other ways to move this logic outside Caddy configuration and into an environment that is more suitable to scripting. One option is to delegate auth decisions to a separate microservice as in caddy-extauth, so that authorization can be controlled by the user in any language, but easily integrated as a middleware-type plugin.The new module should take advantage of the integrated Starlark scripting capability to provide a platform for users to express advanced auth flows.
Starlark has a python-like syntax that would allow someone to express all kinds of auth flows and special cases that are awkwardly handled as edge cases in this plugin. Things like extracting tokens from oddly named cookies, stripping claim prefixes, and returning non-standard HTTP responses would be relatively easy in Starlark and keep these edge cases out of the module code.
The starlark runtime can be injected with custom functions (implemented in Go), such as
valid(token, algorithm, secret)andclaim(token, field), that would extract claims and validate tokens, return various HTTP responses, set headers, allow fine grained auth rules for different paths, etc. so that nearly any use case can be under the control of the user while keeping the module code free of special cases.Address drawbacks of delegating auth decisions to user scripts
One downside of the ideas above is that it would be a lot easier for a user to shoot themselves in the foot unless they are familiar with the design errors in JWT. There are several known vulnerabilities that arise from the JWT specification, like attacks based on monkeying with the
algheader field in order to control how JWT validation is applied.Care should be taken in what functions are supplied to the user so that the design of the API prevents them from insecurely validating tokens.