1
1
mirror of https://github.com/docker-mailserver/docker-mailserver synced 2024-12-18 14:04:17 +01:00
docker-mailserver/test/config/oauth2/Caddyfile
Brennan Kinney 611a66bf98
fix: Correctly support multiple Dovecot PassDBs (#3812)
* fix: Dovecot PassDB should restrict allowed auth mechanisms

This prevents PassDBs incompatible with certain auth mechanisms from logging failures which accidentally triggers Fail2Ban.

Instead only allow the PassDB to be authenticated against when it's compatible with the auth mechanism used.

* tests: Use `curl` for OAuth2 login test-cases instead of netcat

`curl` provides this capability for both IMAP and SMTP authentication with a bearer token. It supports both `XOAUTH2` and `OAUTHBEARER` mechanisms, as these updated test-cases demonstrate.

* chore: Add entry to `CHANGELOG.md`
2024-01-23 19:11:05 +01:00

92 lines
4.3 KiB
Caddyfile

# Mocked OAuth2 /userinfo endpoint normally provided via an Authorization Server (AS) / Identity Provider (IdP)
#
# Dovecot will query the mocked `/userinfo` endpoint with the OAuth2 bearer token it was provided during login.
# If the session for the token is valid, a response returns an attribute to perform a UserDB lookup on (default: email).
# `DMS_YWNjZXNzX3Rva2Vu` is the access token our OAuth2 tests expect for an authorization request to be successful.
# - The token was created by base64 encoding the string `access_token`, followed by adding `DMS_` as a prefix.
# - Normally an access token is a short-lived value associated to a login session. The value does not encode any real data.
# It is an opaque token: https://oauth.net/2/bearer-tokens/
# NOTE: The main server config is at the end within the `:80 { ... }` block.
# This is because the endpoints are extracted out into Caddy snippets, which must be defined before they're referenced.
# /userinfo
(route-userinfo) {
vars token "DMS_YWNjZXNzX3Rva2Vu"
# Expects to match an authorization header with a specific bearer token:
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#authentication_schemes
@auth header Authorization "Bearer {vars.token}"
# If the provided authorization header has the expected value (bearer token), respond with this JSON payload:
handle @auth {
# JSON inlined via HereDoc string feature:
# Dovecot OAuth2 defaults to `username_attribute = email`, which must be returned in the response to match
# with the `user` credentials field that Dovecot received via base64 encoded IMAP `AUTHENTICATE` value.
respond <<EOF
{
"email": "user1@localhost.localdomain",
"email_verified": true
}
EOF
}
# Failed to authorize, close connection and send a 401 status (unauthorized):
respond 401 {
close
}
}
# NOTE: This portion of config is only relevant for understanding what happens seamlesssly,
# DMS tests no longer use raw IMAP commands with netcat, thus none of this is relevant beyond reference for troubleshooting.
#
# /imap/xoauth2
# Generate IMAP commands for authentication testing
# Base64 encoded credentials can alternative be done via CLI with:
# echo -en 'user=${USERNAME}\001auth=Bearer ${ACCESS_TOKEN}\001\001' | base64 -w0; echo
#
# Provide `user` and `access_token` values via query string parameters:
# curl 'http://auth.example.test/imap/xoauth2?user=user1@localhost.localdomain&access_token=DMS_YWNjZXNzX3Rva2Vu'
# curl 'http://auth.example.test/imap/oauthbearer?user=user1@localhost.localdomain&access_token=DMS_YWNjZXNzX3Rva2Vu'
#
# Example Response:
# a0 AUTHENTICATE XOAUTH2 dXNlcj11c2VyMUBsb2NhbGhvc3QubG9jYWxkb21haW4BYXV0aD1CZWFyZXIgRE1TX1lXTmpaWE56WDNSdmEyVnUBAQ==
# a1 EXAMINE INBOX
# a2 LOGOUT
#
# When Dovecot queries /userinfo endpoint, it will be after base64 decoding the IMAP `AUTHENTICATE` value,
# and sending the `auth` value from the `credentials` variable as an HTTP Authorization header.
(route-imap) {
# The login username + OAuth2 access token prior to Base64 encoding, as per the XOAUTH2 spec:
# https://developers.google.com/gmail/imap/xoauth2-protocol#the_sasl_xoauth2_mechanism
# For OAUTHBEARER `host` and `port` do not appear to affect authentication with Dovecot
map {path} {sasl_mechanism} {credentials} {
/xoauth2 XOAUTH2 "user={query.user}\001auth=Bearer {query.access_token}\001\001"
/oauthbearer OAUTHBEARER "n,a={query.user},\001host=localhost\001port=143\001auth=Bearer {query.access_token}\001\001"
}
# Responds with the raw IMAP commands for testing XOAUTH2 authentication.
# Uses the `b64enc` template function to encode credentials as required for `IMAP AUTHENTICATE`:
templates
respond <<EOF
a0 AUTHENTICATE {sasl_mechanism} {{b64enc "{credentials}"}}
a1 EXAMINE INBOX
a2 LOGOUT
EOF
}
# Routes the endpoints to the logical blocks extracted out as snippets above
:80 {
# This is the `/userinfo` endpoint that Dovecot connects to with the OAuth2 setting (default: `introspection_mode = auth`).
# Example: curl http://auth.example.test/userinfo -H 'Authorization: Bearer DMS_YWNjZXNzX3Rva2Vu'
handle_path /userinfo {
import route-userinfo
}
# An additional endpoint for maintainers to generate `test/files/auth/imap-oauth2-auth.txt`
handle_path /imap/* {
import route-imap
}
}