From 7eb3fc6de0f912fe5388ce90243d72fc1508cc39 Mon Sep 17 00:00:00 2001 From: polarathene <5098581+polarathene@users.noreply.github.com> Date: Fri, 19 Jan 2024 16:56:12 +1300 Subject: [PATCH 01/10] tests: OAuth2 - Replace Python `/userinfo` endpoint with Caddy Better documented, easier flow and separation of concerns via Caddy. The python code had additional noise related to setting up a basic API which is abstracted away via `Caddyfile` config that's dedicated to this task. --- test/config/oauth2/Caddyfile | 67 +++++++++++++++++++++++++ test/config/oauth2/provider.py | 56 --------------------- test/tests/serial/mail_with_oauth2.bats | 7 ++- 3 files changed, 70 insertions(+), 60 deletions(-) create mode 100644 test/config/oauth2/Caddyfile delete mode 100644 test/config/oauth2/provider.py diff --git a/test/config/oauth2/Caddyfile b/test/config/oauth2/Caddyfile new file mode 100644 index 00000000..5e3ebc58 --- /dev/null +++ b/test/config/oauth2/Caddyfile @@ -0,0 +1,67 @@ +# 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). + +: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 ' + handle_path /userinfo { + reverse_proxy localhost:2000 + } + + # An additional endpoint for maintainers to generate `test/files/auth/imap-oauth2-auth.txt` + handle_path /imap/xoauth2 { + reverse_proxy localhost:3000 + } +} + +# +# Internal blocks below provide actual endpoint logic +# + +# /userinfo +:2000 { + # OAuth2.0 Bearer token (paste into https://jwt.io/ to check it's contents). + # You should never need to edit this unless you REALLY need to change the issuer. + vars token "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwOi8vcHJvdmlkZXIuZXhhbXBsZS50ZXN0OjgwMDAvIiwic3ViIjoiODJjMWMzMzRkY2M2ZTMxMWFlNGFhZWJmZTk0NmM1ZTg1OGYwNTVhZmYxY2U1YTM3YWE3Y2M5MWFhYjE3ZTM1YyIsImF1ZCI6Im1haWxzZXJ2ZXIiLCJ1aWQiOiI4OU4zR0NuN1M1Y090WkZNRTVBeVhNbmxURFdVcnEzRmd4YWlyWWhFIn0.zuCytArbphhJn9XT_y9cBdGqDCNo68tBrtOwPIsuKNyF340SaOuZa0xarZofygytdDpLtYr56QlPTKImi-n1ZWrHkRZkwrQi5jQ-j_n2hEAL0vUToLbDnXYfc5q2w7z7X0aoCmiK8-fV7Kx4CVTM7riBgpElf6F3wNAIcX6R1ijUh6ISCL0XYsdogf8WUNZipXY-O4R7YHXdOENuOp3G48hWhxuUh9PsUqE5yxDwLsOVzCTqg9S5gxPQzF2eCN9J0I2XiIlLKvLQPIZ2Y_K7iYvVwjpNdgb4xhm9wuKoIVinYkF_6CwIzAawBWIDJAbix1IslkUPQMGbupTDtOgTiQ" + + # 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 <&1 | grep 'Starting server'" + _run_until_success_or_timeout 20 sh -c "docker logs ${CONTAINER2_NAME} 2>&1 | grep 'serving initial configuration'" # # Setup DMS container From c050c7290ca740f85bbdcf5a4cac66429185e838 Mon Sep 17 00:00:00 2001 From: polarathene <5098581+polarathene@users.noreply.github.com> Date: Fri, 19 Jan 2024 17:23:47 +1300 Subject: [PATCH 02/10] tests: OAuth2 - Minimize noise + Improve test assertion Caddyfile can use an Access Token instead of a JWT. Much smaller and correct for this OAuth2 configuration. This new value has been documented inline. Likewise the `sub` field returned is not important to this test. `email_verified` is kept as it may be helpful for further coverage testing. The actual test-case has better assertions for success and failure by checking for Dovecot logs we expect instead of netcat response. `oauth2` to `auth` for the Caddy container hostname is not necessary, just a more generic subdomain choice. --- test/config/oauth2/Caddyfile | 13 +++++++------ test/files/auth/imap-oauth2-auth.txt | 4 ++-- test/tests/serial/mail_with_oauth2.bats | 10 +++++++--- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/test/config/oauth2/Caddyfile b/test/config/oauth2/Caddyfile index 5e3ebc58..68d059ce 100644 --- a/test/config/oauth2/Caddyfile +++ b/test/config/oauth2/Caddyfile @@ -3,6 +3,10 @@ # 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. + :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 ' @@ -22,9 +26,7 @@ # /userinfo :2000 { - # OAuth2.0 Bearer token (paste into https://jwt.io/ to check it's contents). - # You should never need to edit this unless you REALLY need to change the issuer. - vars token "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwOi8vcHJvdmlkZXIuZXhhbXBsZS50ZXN0OjgwMDAvIiwic3ViIjoiODJjMWMzMzRkY2M2ZTMxMWFlNGFhZWJmZTk0NmM1ZTg1OGYwNTVhZmYxY2U1YTM3YWE3Y2M5MWFhYjE3ZTM1YyIsImF1ZCI6Im1haWxzZXJ2ZXIiLCJ1aWQiOiI4OU4zR0NuN1M1Y090WkZNRTVBeVhNbmxURFdVcnEzRmd4YWlyWWhFIn0.zuCytArbphhJn9XT_y9cBdGqDCNo68tBrtOwPIsuKNyF340SaOuZa0xarZofygytdDpLtYr56QlPTKImi-n1ZWrHkRZkwrQi5jQ-j_n2hEAL0vUToLbDnXYfc5q2w7z7X0aoCmiK8-fV7Kx4CVTM7riBgpElf6F3wNAIcX6R1ijUh6ISCL0XYsdogf8WUNZipXY-O4R7YHXdOENuOp3G48hWhxuUh9PsUqE5yxDwLsOVzCTqg9S5gxPQzF2eCN9J0I2XiIlLKvLQPIZ2Y_K7iYvVwjpNdgb4xhm9wuKoIVinYkF_6CwIzAawBWIDJAbix1IslkUPQMGbupTDtOgTiQ" + 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 @@ -38,8 +40,7 @@ respond <, method=XOAUTH2' } From 2b102097fd702afb85575b3aea0b91b3ee24b953 Mon Sep 17 00:00:00 2001 From: polarathene <5098581+polarathene@users.noreply.github.com> Date: Fri, 19 Jan 2024 17:34:32 +1300 Subject: [PATCH 03/10] tests: OAuth2 - Caddyfile `imap/xoauth2` route dynamic via query string This way is more flexible and doesn't require modifying the `Caddyfile` directly, while still easy to use. Additionally simplifies understanding the Caddyfile to maintainers by removing the `route` directive that was required to ensure a deterministic order of vars. --- test/config/oauth2/Caddyfile | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/test/config/oauth2/Caddyfile b/test/config/oauth2/Caddyfile index 68d059ce..56a009d4 100644 --- a/test/config/oauth2/Caddyfile +++ b/test/config/oauth2/Caddyfile @@ -52,16 +52,20 @@ } # /imap/xoauth2 -# Responds with the auth string (base64 encoded) for use with the IMAP `AUTHENTICATE` command: -# curl http://auth.example.test/imap/xoauth2 +# 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' +# # 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. :3000 { - route { - vars token "DMS_YWNjZXNzX3Rva2Vu" - vars user "user1@localhost.localdomain" - vars credentials "user={vars.user}\001auth=Bearer {vars.token}\001\001" - } + # 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 + vars credentials "user={query.user}\001auth=Bearer {query.access_token}\001\001" + + # Responds with the auth string (base64 encoded) for use with the IMAP `AUTHENTICATE` command: + templates + respond "{{b64enc \"{vars.credentials}\"}}" +} templates respond "{{b64enc \"{vars.credentials}\"}}" From 74ead6a83ae2704a87aeedb5b5978cea7876ea73 Mon Sep 17 00:00:00 2001 From: polarathene <5098581+polarathene@users.noreply.github.com> Date: Fri, 19 Jan 2024 17:40:31 +1300 Subject: [PATCH 04/10] tests: OAuth2 - `/imap/xoauth2` respond with IMAP commands for netcat Since this is the only intended usage, might as well have it respond with the full file content. --- test/config/oauth2/Caddyfile | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/test/config/oauth2/Caddyfile b/test/config/oauth2/Caddyfile index 56a009d4..4f683e4f 100644 --- a/test/config/oauth2/Caddyfile +++ b/test/config/oauth2/Caddyfile @@ -52,9 +52,15 @@ } # /imap/xoauth2 +# Generate IMAP commands for authentication testing # 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' # +# 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. :3000 { @@ -62,11 +68,12 @@ # https://developers.google.com/gmail/imap/xoauth2-protocol#the_sasl_xoauth2_mechanism vars credentials "user={query.user}\001auth=Bearer {query.access_token}\001\001" - # Responds with the auth string (base64 encoded) for use with the IMAP `AUTHENTICATE` command: + # 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 "{{b64enc \"{vars.credentials}\"}}" -} - - templates - respond "{{b64enc \"{vars.credentials}\"}}" + respond < Date: Fri, 19 Jan 2024 18:08:44 +1300 Subject: [PATCH 05/10] tests: OAuth2 - Implement coverage for `OAUTHBEARER` Caddyfile route for `/imap/` now accepts any subpath to support handling both `xoauth2` and `oauthbearer` subpaths. Both SASL mechanisms represent the same information, with `XOAUTH2` being a common mechanism to encounter defined by Google, whilst `OAUTHBEARER` is the newer variant standardized by RFC 7628 but not yet as widely adopted. The request to `/userinfo` endpoint will be the same, only the `credentials` value to be encoded differs. Instead of repeating the block for a similar route, this difference is handled via the Caddyfile `map` directive. We match the path context (_`/xoauth2` or `/oauthbearer`, the `/imap` prefix was stripped by `handle_path` earlier_), when there is a valid match, `sasl_mechanism` and `credentials` map vars are created and assigned to be referenced by the later `respond` directive. --- Repeat the same test-case logic, DRY with log asserts extracted to a common function call. This should be fine as the auth method will be sufficient to match against or a common failure caught. --- test/config/oauth2/Caddyfile | 11 ++++++++--- test/files/auth/imap-oauth2-oauthbearer.txt | 4 ++++ ...imap-oauth2-auth.txt => imap-oauth2-xoauth2.txt} | 0 test/tests/serial/mail_with_oauth2.bats | 13 ++++++++++--- 4 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 test/files/auth/imap-oauth2-oauthbearer.txt rename test/files/auth/{imap-oauth2-auth.txt => imap-oauth2-xoauth2.txt} (100%) diff --git a/test/config/oauth2/Caddyfile b/test/config/oauth2/Caddyfile index 4f683e4f..63cb4f5e 100644 --- a/test/config/oauth2/Caddyfile +++ b/test/config/oauth2/Caddyfile @@ -15,7 +15,7 @@ } # An additional endpoint for maintainers to generate `test/files/auth/imap-oauth2-auth.txt` - handle_path /imap/xoauth2 { + handle_path /imap/* { reverse_proxy localhost:3000 } } @@ -55,6 +55,7 @@ # Generate IMAP commands for authentication testing # 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== @@ -66,13 +67,17 @@ :3000 { # 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 - vars credentials "user={query.user}\001auth=Bearer {query.access_token}\001\001" + # 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 <, method=XOAUTH2' + assert_output --partial "dovecot: imap-login: Login: user=, method=${AUTH_METHOD}" } From 9a80059e496acbea4c6e4566ac3e2a522e5b879d Mon Sep 17 00:00:00 2001 From: polarathene <5098581+polarathene@users.noreply.github.com> Date: Fri, 19 Jan 2024 18:31:05 +1300 Subject: [PATCH 06/10] tests: OAuth2 - Minor revisions Separate test cases and additional comment on creating the same base64 encoded credentials via CLI as an alternative to running Caddy. Added a simple `compose.yaml` for troubleshooting or running the container for the `/imap/xoauth2` / `/imap/oauthbearer` endpoints. --- test/config/oauth2/Caddyfile | 5 ++++- test/config/oauth2/compose.yaml | 9 +++++++++ test/tests/serial/mail_with_oauth2.bats | 12 +++++++----- 3 files changed, 20 insertions(+), 6 deletions(-) create mode 100644 test/config/oauth2/compose.yaml diff --git a/test/config/oauth2/Caddyfile b/test/config/oauth2/Caddyfile index 63cb4f5e..a63c8bf8 100644 --- a/test/config/oauth2/Caddyfile +++ b/test/config/oauth2/Caddyfile @@ -9,7 +9,7 @@ :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 ' + # Example: curl http://auth.example.test/userinfo -H 'Authorization: Bearer DMS_YWNjZXNzX3Rva2Vu' handle_path /userinfo { reverse_proxy localhost:2000 } @@ -53,6 +53,9 @@ # /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' diff --git a/test/config/oauth2/compose.yaml b/test/config/oauth2/compose.yaml new file mode 100644 index 00000000..b6ed2181 --- /dev/null +++ b/test/config/oauth2/compose.yaml @@ -0,0 +1,9 @@ +# Run this with `docker compose up` if needing to use the container outside of tests +services: + caddy-oauth2: + image: caddy:2.7 + container_name: dms-oauth2 + ports: + - "80:80" + volumes: + - ./Caddyfile:/etc/caddy/Caddyfile:ro diff --git a/test/tests/serial/mail_with_oauth2.bats b/test/tests/serial/mail_with_oauth2.bats index 373825a0..1aab71dd 100644 --- a/test/tests/serial/mail_with_oauth2.bats +++ b/test/tests/serial/mail_with_oauth2.bats @@ -28,7 +28,7 @@ function setup_file() { # Setup DMS container # - # Add OAUTH2 configuration so that Dovecot can reach out to our mock provider (CONTAINER2) + # Add OAuth2 configuration so that Dovecot can query our mocked identity provider (CONTAINER2) local ENV_OAUTH2_CONFIG=( --env ENABLE_OAUTH2=1 --env OAUTH2_INTROSPECTION_URL=http://auth.example.test/userinfo @@ -48,6 +48,9 @@ function setup_file() { # Set default implicit container fallback for helpers: export CONTAINER_NAME=${CONTAINER1_NAME} + + # An initial connection needs to be made first, otherwise the auth attempts fail + _run_in_container_bash 'nc -vz 0.0.0.0 143' } function teardown_file() { @@ -55,13 +58,12 @@ function teardown_file() { docker network rm "${DMS_TEST_NETWORK}" } -@test "oauth2: imap connect and authentication works" { - # An initial connection needs to be made first, otherwise the auth attempt fails - _run_in_container_bash 'nc -vz 0.0.0.0 143' - +@test "should authenticate with XOAUTH2 over IMAP" { _nc_wrapper 'auth/imap-oauth2-xoauth2.txt' '-w 1 0.0.0.0 143' __verify_successful_login 'XOAUTH2' +} +@test "should authenticate with OAUTHBEARER over IMAP" { _nc_wrapper 'auth/imap-oauth2-oauthbearer.txt' '-w 1 0.0.0.0 143' __verify_successful_login 'OAUTHBEARER' } From ba5047e64db1021e5861a6467fce09e520c6cec1 Mon Sep 17 00:00:00 2001 From: polarathene <5098581+polarathene@users.noreply.github.com> Date: Fri, 19 Jan 2024 19:52:32 +1300 Subject: [PATCH 07/10] tests: OAuth2 - Route endpoints in Caddyfile with snippets instead `reverse_proxy` was a bit more convenient, but the additional internal ports weren't really relevant. It also added noise to logging when troubleshooting. The `import` directive with Snippet blocks instead is a bit cleaner, but when used in a single file snippets must be defined prior to referencing them with the `import` directive. --- `compose.yaml` inlines the examples, with slight modification to `localhost:80`, since the Caddyfile examples `auth.example.test` is more relevant to the tests which can use it, and not applicable to troubleshooting locally outside of tests. --- test/config/oauth2/Caddyfile | 36 ++++++++++++++++----------------- test/config/oauth2/compose.yaml | 8 +++++++- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/test/config/oauth2/Caddyfile b/test/config/oauth2/Caddyfile index a63c8bf8..b0e17587 100644 --- a/test/config/oauth2/Caddyfile +++ b/test/config/oauth2/Caddyfile @@ -7,25 +7,11 @@ # - 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. -: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 { - reverse_proxy localhost:2000 - } - - # An additional endpoint for maintainers to generate `test/files/auth/imap-oauth2-auth.txt` - handle_path /imap/* { - reverse_proxy localhost:3000 - } -} - -# -# Internal blocks below provide actual endpoint logic -# +# 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 -:2000 { +(route-userinfo) { vars token "DMS_YWNjZXNzX3Rva2Vu" # Expects to match an authorization header with a specific bearer token: @@ -67,7 +53,7 @@ # # 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. -:3000 { +(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 @@ -85,3 +71,17 @@ 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 + } +} diff --git a/test/config/oauth2/compose.yaml b/test/config/oauth2/compose.yaml index b6ed2181..6aa955c2 100644 --- a/test/config/oauth2/compose.yaml +++ b/test/config/oauth2/compose.yaml @@ -1,4 +1,5 @@ -# Run this with `docker compose up` if needing to use the container outside of tests +# Provides support for running this container outside of tests +# Run this with `docker compose up` services: caddy-oauth2: image: caddy:2.7 @@ -7,3 +8,8 @@ services: - "80:80" volumes: - ./Caddyfile:/etc/caddy/Caddyfile:ro + +# Examples: +# curl http://localhost:80/userinfo -H 'Authorization: Bearer DMS_YWNjZXNzX3Rva2Vu' +# curl 'http://localhost:80/imap/xoauth2?user=user1@localhost.localdomain&access_token=DMS_YWNjZXNzX3Rva2Vu' +# curl 'http://localhost:80/imap/oauthbearer?user=user1@localhost.localdomain&access_token=DMS_YWNjZXNzX3Rva2Vu' From 83f7a437053c2da3f15f0cc0a32901a1cf16e4cb Mon Sep 17 00:00:00 2001 From: Brennan Kinney <5098581+polarathene@users.noreply.github.com> Date: Fri, 19 Jan 2024 20:15:10 +1300 Subject: [PATCH 08/10] chore: Add entry to `CHANGELOG.md` --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b6126956..90a905f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ All notable changes to this project will be documented in this file. The format ### Updates - **Tests**: + - Revised OAuth2 test ([#3795](https://github.com/docker-mailserver/docker-mailserver/pull/3795)) - Replace `wc -l` with `grep -c` ([#3752](https://github.com/docker-mailserver/docker-mailserver/pull/3752)) - Revised testing of service process management (supervisord) to be more robust ([#3780](https://github.com/docker-mailserver/docker-mailserver/pull/3780)) - Refactored mail sending ([#3747](https://github.com/docker-mailserver/docker-mailserver/pull/3747) & [#3772](https://github.com/docker-mailserver/docker-mailserver/pull/3772)): From 6a55286e3b343f4c27d10274ae4fd01c314e181b Mon Sep 17 00:00:00 2001 From: Brennan Kinney <5098581+polarathene@users.noreply.github.com> Date: Fri, 19 Jan 2024 21:11:25 +1300 Subject: [PATCH 09/10] chore: Additional context on access token --- test/config/oauth2/Caddyfile | 1 + 1 file changed, 1 insertion(+) diff --git a/test/config/oauth2/Caddyfile b/test/config/oauth2/Caddyfile index b0e17587..e116aa55 100644 --- a/test/config/oauth2/Caddyfile +++ b/test/config/oauth2/Caddyfile @@ -6,6 +6,7 @@ # `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. From 7e14df3d9900f4b3d0558d03bc0a453d3417d8b8 Mon Sep 17 00:00:00 2001 From: Brennan Kinney <5098581+polarathene@users.noreply.github.com> Date: Sat, 20 Jan 2024 21:10:11 +1300 Subject: [PATCH 10/10] Update test/tests/serial/mail_with_oauth2.bats Co-authored-by: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com> --- test/tests/serial/mail_with_oauth2.bats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/tests/serial/mail_with_oauth2.bats b/test/tests/serial/mail_with_oauth2.bats index 1aab71dd..0cc34a01 100644 --- a/test/tests/serial/mail_with_oauth2.bats +++ b/test/tests/serial/mail_with_oauth2.bats @@ -22,7 +22,7 @@ function setup_file() { --volume "${REPOSITORY_ROOT}/test/config/oauth2/Caddyfile:/etc/caddy/Caddyfile:ro" \ caddy:2.7 - _run_until_success_or_timeout 20 sh -c "docker logs ${CONTAINER2_NAME} 2>&1 | grep 'serving initial configuration'" + _run_until_success_or_timeout 20 bash -c "docker logs ${CONTAINER2_NAME} 2>&1 | grep 'serving initial configuration'" # # Setup DMS container