Update default redirect url matching to be more secure#3913
Conversation
We are changing the default value of uaa.oauth.redirect_uri.allow_unsafe_matching from true to false to make UAA secure by default. When uaa.oauth.redirect_uri.allow_unsafe_matching is true, UAA uses the LegacyRedirectResolver, which performs permissive subdomain matching when validating OAuth2 redirect URIs. This means that a redirect URI registered as https://app.example.com/callback will also match https://evil.app.example.com/callback. This behavior poses a security risk. Exact URI matching (the behavior when allow_unsafe_matching is false) is the correct and safe default.
Test Updates: - Updated RedirectResolverFactoryBeanTest to expect NormalizedRedirectResolver - Added allow_unsafe_matching=true to test classes requiring legacy behavior: * UaaAuthorizationEndpointMockMvc*Test (legacy behavior testing) * TokenMvcMock*Tests (wildcard redirect URI tests) * AuthorizationPromptNoneEntryPointMockMvcTests (silent auth tests) * InvitationsEndpointMockMvc*Tests (zone creation flows) - Updated MockMvcUtils redirect URI to match test client configuration - Added exact redirect URI to identity client for utility method compatibility
- Added `@SuppressWarnings("rule:java:S5810")` to test classes where public access was necessary for subclass usage.
- Removed redundant test methods and code blocks for cleaner test implementation.
- Renamed parameters (e.g., `REDIRECT_URI` to `redirectUri`) for consistent style.
- Cleaned up unused imports and methods for improved readability.
Enable allow_unsafe_matching=true in scripts/boot/uaa.yml to allow integration tests to use wildcard redirect URI patterns while maintaining secure defaults for production deployments.
There was a problem hiding this comment.
Pull request overview
Flips the default value of the uaa.oauth.redirect_uri.allow_unsafe_matching property from true to false, so UAA defaults to the safer NormalizedRedirectResolver (exact-match, no permissive subdomain wildcarding) instead of the LegacyRedirectResolver. Tests and helpers that depended on the previous lenient matching behavior are updated to either explicitly opt back in via @TestPropertySource or to use redirect URIs that satisfy strict matching. scripts/boot/uaa.yml is updated to keep allow_unsafe_matching: true so the local boot configuration retains existing behavior (matching uaa-release's current override).
Changes:
- Change the
@Valuedefault inRedirectResolverFactoryBeanfromtruetofalse, and update the corresponding unit test to assertNormalizedRedirectResolver. - Add
@TestPropertySourceoverrides (with newMockMvcautowires for nested test classes) in tests that exercise legacy unsafe matching; updateMockMvcUtilsredirect URIs tohttp://localhost:8080/testso they match the registered client redirect URI exactly. - Set
allow_unsafe_matching: trueinscripts/boot/uaa.ymlto preserve current boot behavior.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| server/src/main/java/org/cloudfoundry/identity/uaa/oauth/beans/RedirectResolverFactoryBean.java | Flip default of allow_unsafe_matching to false. |
| server/src/test/java/org/cloudfoundry/identity/uaa/oauth/beans/RedirectResolverFactoryBeanTest.java | Update test to expect NormalizedRedirectResolver and rename method accordingly. |
| scripts/boot/uaa.yml | Add explicit allow_unsafe_matching: true for local boot. |
| uaa/src/test/java/.../oauth/UaaAuthorizationEndpointMockMvcTest.java | Add @TestPropertySource + MockMvc to legacy-matching nested class; remove a redundant exact-match test under the wildcard-config block. |
| uaa/src/test/java/.../oauth/UaaAuthorizationEndpointMockMvcZonePathTest.java | Same updates as above; also clean up a stale comment. |
| uaa/src/test/java/.../mock/oauth/AuthorizationPromptNoneEntryPointMockMvcTests.java | Annotate the class with @TestPropertySource to enable legacy matching; add @Override. |
| uaa/src/test/java/.../invitations/InvitationsEndpointMockMvcTests.java | Add @TestPropertySource and re-autowire MockMvc for the nested zone test class. |
| uaa/src/test/java/.../invitations/InvitationsEndpointMockMvcZonePathTests.java | Same, plus remove an unused helper and tidy imports. |
| uaa/src/test/java/.../mock/util/MockMvcUtils.java | Rename REDIRECT_URI parameter to redirectUri and change hard-coded redirect URI to http://localhost:8080/test to satisfy strict matching. |
| uaa/src/test/java/.../mock/token/TokenMvcMockTests.java | Add allow_unsafe_matching=true property; reformat class declaration with // NOSONAR (and a @SuppressWarnings that uses an invalid Sonar key). |
| uaa/src/test/java/.../mock/token/TokenMvcMockZonePathTests.java | Add allow_unsafe_matching=true property; reformat class declaration with // NOSONAR. |
both files have the allow_unsafe_matching: true setting: integration_test_properties.yml - Used by unit tests via @DefaultTestContext scripts/boot/uaa.yml - Used by the spawned UAA server for integration tests
Changing the default value of uaa.oauth.redirect_uri.allow_unsafe_matching from true to false to make UAA use the more secure setting by default.
When uaa.oauth.redirect_uri.allow_unsafe_matching is true, UAA uses the LegacyRedirectResolver, which performs permissive subdomain matching when validating OAuth2 redirect URIs. This means that a redirect URI registered as https://app.example.com/callback will also match https://evil.app.example.com/callback.
This behavior could pose a security risk. Exact URI matching (the behavior when allow_unsafe_matching is false) is the correct and safe default.
This setting is overridden in uaa-release. So deployments using the uaa-release will notice no effect, until it also changes.
Implements #3883