Repository navigation
Commit b6d8cad
authored
Support a caller-supplied redirect on /reset-remember-wayf (#2097)
* Support a caller-supplied redirect on /reset-remember-wayf
Let /reset-remember-wayf accept an optional `redirect` query parameter
so callers such as Profile can send the user back to the page they
came from once their remembered per-SP WAYF choices are cleared,
instead of always sending everyone to the single operator-configured
URL from #2085. Every redirect (whether the caller-supplied target or
the configured fallback) now also carries a `wayfReset=removed|none`
query parameter, so the caller can tell whether a cookie actually
existed and was cleared.
- New config wayf.reset_choice_allowed_redirect_hosts is a host
allowlist (defaulting to profile.dev.openconext.local in dev/CI):
the `redirect` parameter is only honoured when it parses to an
http(s) URL whose host appears in this list, otherwise the endpoint
silently falls back to the existing wayf.reset_choice_per_idp_redirect
target. This mirrors the "parse and check an allowed value" shape of
the existing AllowedSchemeValidator rather than introducing a new
general-purpose URL validation abstraction for a single call site.
- Resolving the redirect target and appending the wayfReset signal are
both extracted into small private methods so the __invoke method
reads as a straight sequence: clear/log the cookie if present,
resolve where to send the user, tell them what happened.
- The entry-count/log-message behaviour from #2085 is unchanged: a
present-but-unparseable cookie is still treated the same as a valid
one for logging and for the wayfReset signal (both are cleared and
reported), since from the caller's perspective the cookie no longer
exists either way.
- Existing unit/functional tests were updated for the new
`?wayfReset=` suffix on every redirect, and new cases cover an
allowed redirect host, a redirect with its own query string, a
disallowed host, a malformed URL, and a disallowed scheme.
Needed by OpenConext/OpenConext-profile#345, which links back to
Profile's "my personal data" page after resetting a user's remembered
WAYF choices.
* Keep the URL fragment after the wayfReset query parameter
# If applied, this commit will
Fix redirects whose target URL contains a fragment so wayfReset
actually reaches the destination app as a real query parameter.
# Why is this change needed?
Prior to this change, appendQueryParameter() always concatenated the
wayfReset parameter onto the end of the URL string. For a target URL
with a fragment, that put the query parameter after the '#', where
it is treated as part of the fragment by browsers and never seen as
a real query parameter.
# How does it address the issue?
This change splits off any fragment before appending the query
parameter, then re-appends the fragment at the very end, producing
the conventional ...?wayfReset=...#fragment shape.
# Provide links to any relevant tickets, articles or other resources
Found during review of PR #2097.
* Document the redirect query parameter of the reset endpoint
# Why is this change needed?
Prior to this change, the redirect query parameter, the allowed redirect hosts
and the wayfReset result parameter of /reset-remember-wayf were only described
in parameters.yml.dist. Operators need to know about the open redirect
protection and integrators about the result parameter.
# How does it address the issue?
This change extends the reset section in docs/wayf_remember_choice.md and adds
an entry to the CHANGELOG.
* Harden the redirect validation of the reset endpoint
Only accept https redirects and reject backslashes, control characters,
whitespace and userinfo in the redirect query parameter.
Prior to this change, the redirect value was only checked with parse_url()
against the host allowlist. Browsers normalise a value such as
https://evil.example.org\@profile.example.org/ differently from parse_url(),
so the host check could pass while the browser navigated to another host
(open redirect). Plain http was also accepted without a need for it.
This change rejects values containing a backslash, control character or
whitespace, values with credentials, and any scheme other than https.
Unit tests cover each of these cases and the docs and changelog describe
the stricter rules.
Review feedback on the redirect parameter pull request.
* Explain what the redirect query parameter is for in the CHANGELOG
# If applied, this commit will...
Reword the CHANGELOG entry for the `redirect` query parameter so it
explains the purpose of the parameter rather than leading with its
https-only validation detail.
# Why is this change needed?
Prior to this change, the entry opened with the fact that only https
URLs with an allowed host are accepted, without saying what the
parameter is actually for. A system operator reading the CHANGELOG had
no indication of why they might want to configure
wayf.reset_choice_allowed_redirect_hosts.
# How does it address the issue?
This change leads with the purpose: callers such as Profile can send
the user back to the page they came from after clearing their
remembered per-SP WAYF choices, instead of always landing on the
operator-configured wayf.reset_choice_per_idp_redirect. The validation
rule and the wayfReset query parameter are kept as supporting detail.
# Provide links to any relevant tickets, articles or other resources
Addresses review comment on PR #2097.
* Use the WHATWG URL parser to validate the reset redirect
Prior to this change, the redirect query parameter of
/reset-remember-wayf was validated with a regular expression and
parse_url(). That meant anticipating every difference between
parse_url() and the way browsers interpret a URL.
This change parses the value with Uri\WhatWg\Url, the same
specification browsers follow, so the host that is checked is the
host the browser navigates to. The validated URL is returned in its
normalised ASCII form and used as the redirect target. Inputs a
browser would also accept, such as a leading space or a tab, are now
accepted and normalised instead of rejected.1 parent 1d22124 commit b6d8cad
7 files changed
Lines changed: 330 additions & 8 deletions
File tree
- config
- packages
- services/controllers
- docs
- src/OpenConext/EngineBlockBundle/Controller
- tests
- functional/OpenConext/EngineBlockBundle/Controller
- unit/OpenConext/EngineBlockBundle/Controller
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
29 | 35 | | |
30 | 36 | | |
31 | 37 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
194 | 194 | | |
195 | 195 | | |
196 | 196 | | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
197 | 204 | | |
198 | 205 | | |
199 | 206 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
79 | 79 | | |
80 | 80 | | |
81 | 81 | | |
| 82 | + | |
82 | 83 | | |
83 | 84 | | |
84 | 85 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
105 | 105 | | |
106 | 106 | | |
107 | 107 | | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
108 | 125 | | |
109 | 126 | | |
110 | 127 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
| 30 | + | |
30 | 31 | | |
31 | 32 | | |
32 | 33 | | |
33 | 34 | | |
34 | 35 | | |
35 | 36 | | |
36 | 37 | | |
| 38 | + | |
37 | 39 | | |
38 | 40 | | |
39 | 41 | | |
| |||
56 | 58 | | |
57 | 59 | | |
58 | 60 | | |
59 | | - | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
60 | 105 | | |
61 | 106 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
46 | 46 | | |
47 | 47 | | |
48 | 48 | | |
49 | | - | |
| 49 | + | |
50 | 50 | | |
51 | 51 | | |
52 | 52 | | |
| |||
61 | 61 | | |
62 | 62 | | |
63 | 63 | | |
64 | | - | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
65 | 103 | | |
66 | 104 | | |
67 | 105 | | |
| |||
0 commit comments