I have written a very simple caddy saml sso module and I’d appreciate feedback from the caddy community.
I am aware we already have the amazing work from Paul but I wanted to have something simpler and more SAML specific.
Here is a Caddyfile example that instantiates the module forces valid SAML sessions on all the requests to https://foo.bar.net:12000 (/ping is open for testing).
The module is pretty simple. While provisioning, we configure the SAML library to create the Service Provider/Identity Provider connection. Then, in the middleware Handler, we either pass the requests (/saml) to the SAML library to handle the SAML flow or we ensure that all the requests are part of a valid SAML session. The SAML library provides two middleware for each purpose. If all goes well, we respond with an OK.
Error: adapting config using caddyfile: parsing caddyfile tokens for 'handle': directive 'saml_sso' is not an ordered HTTP handler, so it cannot be used here
Why is that? What does order mean here? To me I am already defining an order: first the saml_sso plugin and then a respond. Why do I need to add the route and/or order?
I guess this works because route forces the order?
Also, how would you rewrite the Caddyfile to use order instead of route?
You should remove /* as matchers
The reason why I use matchers is because there are a few request that will hit /saml and I want to send all of them to the saml middleware but I don’t have the list of all the possible paths in the requests. If I remove the * I am only handling the / requests.
Assigns an order to HTTP handler directive(s). As HTTP handlers execute in a sequential chain, it is necessary for the handlers to be executed in the right order. Standard directives have a pre-defined order, but if using third-party HTTP handler modules, you’ll need to define the order explicitly by either using this option or placing the directive in a route block. Ordering can be described absolutely (first or last ), or relatively (before or after ) to another directive.
So, that means I have to be explicit on my handler saml_sso, the new Caddyfile reads better:
{
order saml_sso before header
order saml_sso before respond
}
(enable_saml) {
saml_sso {
saml_idp_url {$SAML_IDP_URL}
saml_cert_file {$SAML_CERT_FILE}
saml_key_file {$SAML_KEY_FILE}
saml_root_url {$SAML_ROOT_URL}
}
}
http://:12000 {
handle /* {
import enable_saml
# Respond back to the user printing some of the SAML attributes
header Content-Type text/html
respond `<p> {http.response.header.displayname}, you are authenticated now.</p>`
}
}
Sorry, I should have read the documentation more carefully.
In that particular config, you don’t need handle, it doesn’t do anything for you on its own.
Also like I said, don’t do handle /*, instead just do handle if you need it. The difference is that /* is a path matcher which will always match all requests, but Caddy needs to do a path comparison to figure that out, whereas if you omit it, it avoids having to do that path comparison at all. See Request matchers (Caddyfile) — Caddy Documentation
I don’t think you meant to use a / here. That’s a path matcher which only matches exactly/ and nothing else, so this proxy will only work for requests to the root of your site and nothing else.
It doesn’t make sense to set the order for your module twice. Only the last one you use will apply. It can only have one position in the order.
Gotcha. Yes. The thing is that I have two demo Caddyfiles in my README, one where I “respond” to the client from Caddy directly and the other one (more realistic) where I forward the traffic to another service.
I think I they should both be correct now. Please confirm.