An OIDC Reverse Proxy, Written in Anger#
What is it?#
It's a multi-tentant non-caching tls-terminating reverse proxy that can terminate a hybrid of OpenID Connect Core v1.0 with errata 2 1 and OAuth 2.1 2. It also generally reverse proxies HTTP 1.x, h2, websocket, and grpc traffic, as it's built (right now) on pingora.
... what?#
You stick in front of webapps that need either tls added or don't support checking oauth2 state themselves, and it does that for you.
Think oauth2-proxy, but with proper multitenancy support and significantly less battle-tested.
whyyyy????#
I was frustrated with the state of oauth2/oidc-terminating proxies.
Particularly, at the time of writing, oauth2-proxy does not support multitenancy properly (it encourages the insecure practice of sharing client_ids if you use it for forward auth).
Other things, like caddy-security, felt overcomplicated for what i needed to do, and tbh i don't trust security tools that feel like they have everything and the the kitchen sink shoved in, unless they've been written by experts and/or extensively auditted.
how do i use it?#
The configuration is done in textproto format 3. The format is in <src/config/format.proto>, and the inline docs serve as the documentation, so i'd suggest starting there.
Here's a quick example config:
# bind on ipv6
bind_to_tcp {
addr: '[::]:8443'
}
# serve these domains
# serve copyparty w/ oidc termination on
domains {
key: "files.example.com"
value: {
# serve to a (single, here, but this is a `repeated` field)
# uds backend, without tls
uds {
path: "/run/copyparty/party.sock"
}
# enable oidc termination on this domain
oidc_auth {
# standard oidc/oauth stuff
discovery_url_base: "https://sso.example.com/oauth2/openid/files/"
client_id: "files"
# this is where we redirect after logout
logout_url: "https://sso.example.com/"
# put your client secret here
client_secret_path: '/var/lib/secrets/files.client-secret'
# these scopes are required, and sent in the request
scopes {
required: "profile"
required: "group_names"
required: "party"
}
# these claims are mapped to headers
claims {
claim_to_header {
claim: "files_groups"
header: "X-Idp-Groups"
# since this is an array, concatenate it with commans
# before sending it to fileparty
serialize_as {
join_array_items_with: ","
}
}
claim_to_header {
claim: "name"
header: "X-Idp-User"
}
},
}
# serve tls with the following certs
tls {
cert_path: "/var/lib/secrets/serving1.cert"
key_path: "/var/lib/secrets/serving1.key"
}
}
}
# serve your sso server, with oidc termination off
domains {
key: "sso.example.com"
value: {
# your sso server might have it's own tls termination too, so
# connect to it with tls
https {
addr: "127.0.0.1:1309"
}
}
# serve tls with the following certs
tls {
cert_path: "/var/lib/secrets/serving2.cert"
key_path: "/var/lib/secrets/serving2.key"
}
}
should i trust this?#
no, probably not.
consider the following points if you chose to run this:
-
i make no claims about it's security.
-
i'm not a security professional, just a dev with a hobby of writing oauth implementations in anger, apparently 4.
-
if you're often targetted by script kiddies or nation-state actors, or you're working for a company or organization, please don't use this.
-
it'll probably be fine for low-stress homelab situations? that's what i'm using it for.
but does it support...#
- ...serving forward auth?
-
no, not right now. forward auth is an underspecified mess, so it's unlikely that i'll add support.
- ...authorization?
-
nope, this was written for reverse-proxying apps that either
a) can make their own auth decisions (like copyparty), or b) don't need to make complex auth decisions
- ...other types of authn?
-
nope, and it's unlikely that it will -- i prefer to keep things well-scoped. unless it's something odic/oauth2-adjacent, in which case i'd consider it.
For anything else, check the issue tracker and/or file an issue.
omg the code is messsyyyyyy!#
yeah, it probably needs further refactoring.
Contributing#
On the off-chance that you'd like to submit code, i'll take a look at it and review it, but i'm likely going to be picky about what new features i accept. it's probably worth filing an issue to discuss first.
any code submitted should be your own, and you should understand it fully.
-
the uuuh... reasonable parts? yeesh, there's a lotta junk in oidc core v1 ↩︎
-
specifically, the authorization code grant flow ↩︎
-
Q: wait, seriously? A: yes, seriously. i'm putting my money where my mouth is, so to speak, when i say that textproto is nice, actually. ↩︎
-
last year i wrote (but haven't published yet) a cute little oauth server that uses exclusively passkeys from scratch. ↩︎