SSO authentication for proxies, with OAuth 2.0 + OIDC!
You should use the included Dockerfile (and images generated by it) to run the application.
The following environment variables must be set:
CLIENT_ID
andCLIENT_SECRET
should be set to this API's credentials.AUTH_ENDPOINT
should be set to the URL of your IdP's authorization endpoint, for example:https://id.ctf.mcgill.ca/oauth/v1/authorize
.TOKEN_ENDPOINT
should be set to the URL of your IdP's token endpoint, for example:https://id.ctf.mcgill.ca/oauth/v1/token
.USER_INFO_ENDPOINT
should be set to the URL of your IdP's token endpoint, for example:https://identity.ctf.mcgill.ca/userinfo
.SCOPES
should be set to a space-delimited list of scopes that will be requested with the authorization grant, for example:email
.BASE_URL
should be set to the base URL this service (and the backend it protects) will be externally reachable at, for example:https://docs.int.ctf.mcgill.ca
.PRIVATE_KEY_PATH
should be set to a path on the filesystem to a PEM-encoded RSA key for encrypting session cookies, for example:/frontier/key.pem
.
The application will expose an HTTP service on TCP port 8000 on all interfaces.
This application is designed to be used with the nginx auth_request
module.
When a request reaches nginx to access a backend, nginx should be configured to use auth_request
to first send the headers for that request (with the original URL sent in Frontier-Original-URL
) to this application.
This application will check whether the received headers suggest that a user has already authenticated to visit that backend (by inspecting the existence/contents of a Frontier-Session
cookie in the request).
If the request is properly authenticated, this service will return 200 OK
, which nginx's auth_request
module can interpret as meaning it should proxy the original request to the backend. Alongside the 200 OK
, a Frontier-Subject
header will be present in the response containing the subject of the user that authenticated, which can be forwarded to the backend if needed. Note that if you use this header, you should make sure it can only be set by this application, for example by clearing it before the auth_request
).
If the request is not properly authenticated, this service will return 401 Unauthorized
with Frontier-Redirect
in the WWW-Authenticate
header. nginx should not proxy the original request to the backend, but instead redirect the requestor to the URI in the Frontier-Location
header from the 401 response.
This will direct the user to the IdP to confirm authentication and authorization. If all goes well, after the authentication/authorization action, the IdP will redirect the user back to this application. After verifying that the authentication was valid, this application will generate a session cookie and send it with a 303 See Other
for the original location the user was trying to access (back to nginx).
This time, when nginx checks the request, the session cookie will be valid, and the user will pass through to the backend.
The service exposes the following routes
GET /frontier/checkAuth
GET /frontier/oauth/callback
server {
listen 80;
location /frontier/checkAuth {
internal;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header Frontier-Original-Url $request_uri;
proxy_pass http://frontier-service:8000;
}
location @frontier-redirect {
return 303 $frontier_location;
}
location /frontier/oauth/callback {
proxy_pass http://frontier-service:8000;
}
location / {
auth_request /frontier/checkAuth;
auth_request_set $frontier_location "$upstream_http_frontier_location";
auth_request_set $frontier_subject "$upstream_http_frontier_subject";
error_page 401 @frontier-redirect;
add_header Frontier-Subject $frontier_subject;
proxy_pass http://protected-backend-service:80;
}
}
This application is licensed under the MIT license.