It is already possible to show a checkbox in the WAYF that allows users to save this IdP-choice for future logins. If they select this, then future WAYFs in which their preferred IdP is present are skipped and the user is redirected to the preferred IdP without interaction.
We now want to able to specifiy this behaviour per SP. So when a users enabled the checkbox, this only applies when logging in to this specific SP. When the user logs in to a different SP, they still get the WAYF.
The following changes are required:
-
Add the following extra controls to parameters.yml:
- introduce feature-toggle
wayf.remember_choice_per_idp. All of the below should only be active if both wayf.remember_choice and wayf.remember_choice_per_idp are active.
- If
wayf.remember_choice is true and wayf.remember_choice_per_idp is false, we keep the current global memory feature.
- If
wayf.remember_choice is false, we disable all remember-my-choice features (both global and per-sp).
- If
wayf.remember_choice_per_idp is not defined, act as if it were set to false
- a parameter to control the life-time of the remembered IdP:
wayf.remember_choice_per_idp_lifetime. Typically this would be something like 3 months, but it would be nice to be able to set it to (e.g.) 60 seconds for easy debugging.
- a parameter to control how many SP-IdP pairs we can store in the cookie
wayf.remember_choice_per_idp_lifetime. This defaults to 16. For the logic what to do if we exceed this limit, see below.
-
support new coin:wayf_remember_choice metadata parameter for SPs. If this is not present in the metadata, it defaults to false.
-
if feature is enabled, read and set a cookie rememberedidps with content like this:
{
"https://sp_entityid_1": { "idp": "https://idp_entityid_1", "expires": 1784534287 },
"https://sp_entityid_2": { "idp": "https://idp_entityid_2", "expires": 1784512345 }
}
- Ideally, we would like this cookie to be user-readable (for power users and privacy nerds), but cookies are limited to 4kB so that probably won't work. So the safe way to handle this is to deflate and base64-encode the json, en put that in the cookie.
- To make sure the structure fits in the cookie, limit this to max 32 entries.
- If there are more, or a new one needs to be added, drop the oldest ones until there are 32 left.
- I've run a simulation with current production entities: for 32 entries, we never exceed 2800 bytes. For 64 entries, we sometimes hit 4500 bytes. For unencoded json, we cannot store more than 20 reliably within 4k bytes.
- It probably makes sense to parametrize this limit, so add a
wayf.remember_choice_per_idp_max parameter which defaults to 16 to be on the safe side.
- if the cookie content is in any way invalid (invalid base64 encoding, invalid json, etc), log a warning and simply ignore it and remove it from the response.
- The cookie's domain is set to Engineblock's host name
- The
Max-Age or Expires property of the cookie need to be set in accordance with the wayf.remember_choice_per_idp_lifetime setting. To reduce complexity, it is not dependent on the actual expires values in the cookie, so in cornercases (e.g., if the wayf.remember_choice_per_idp_lifetime is reduced) it might occur that the cookie expires earlier than the individual entries in the cookie. That is acceptable behavior.
- The cookie must have
Secure and HttpOnly properties (same as all other EB cookies). SameSite should probably be set to None because we support both Redirect and POST bindings for SAMLRequests.
-
If this feature is enabled (wayf.remember_choice_per_idp is set) then do the following when determining whether to show the WAYF:
- check if this SP has
coin:wayf_remember_choice set in the metadata
- check If the cookie is present and valid, and if the user is logging in to an SP that is present in the cookie
- check that the SP's
expiry entry is in the future
- check that this SP has set
coin:wayf_remember_choice in the metadata
- check that this IdP is available for this SP (i.e., it should never be possible for a user to get redirected to an IdP that is not available for this SP based on this cookie only; the cookie only allows a selection for IdPs that are already available).
- if so, then skip the WAYF (like the existing
rememberchoice cookie does). Log if this occurs with level INFO and message "WAYF-remember-my-choice WAYF skipped for because of preselected "
- if any of the above checks fail, show the regular WAYF
-
Only update the cookie if the user set a new "remember my choice" checkbox. If changes are made, always update the cookie at the client like this:
- remove all expired entries (
time is older than current time)
- remove any entries above the maximum number we support (see above). Drop the oldest ones until we are at the limit. Log if this occurs with level WARNING and message "WAYF-remember-my-choice entities dropped from cookie"
- if no SPs are left in the cookie, remove the cookie altogether
-
If the cookie is only read and no changes are made by the user, the cookie does not need to be updated.
-
If the users gets the regular WAYF and selects the "remember my choice" checkbox, then do the following if per-SP remembering is enabled (if global remembering is enabled, the behaviour doesn't change):
- Add the selected (SP,IdP) pair the to the cookie with the
expires field set to now + wayf.remember_choice_per_idp_lifetime
- Run the checks as specified above
- Set the updated cookie in the response.
- Output a log line with level INFO and message "WAYF-remember-my-choice set for SP and IdP and expiry "
It is already possible to show a checkbox in the WAYF that allows users to save this IdP-choice for future logins. If they select this, then future WAYFs in which their preferred IdP is present are skipped and the user is redirected to the preferred IdP without interaction.
We now want to able to specifiy this behaviour per SP. So when a users enabled the checkbox, this only applies when logging in to this specific SP. When the user logs in to a different SP, they still get the WAYF.
The following changes are required:
Add the following extra controls to
parameters.yml:wayf.remember_choice_per_idp. All of the below should only be active if bothwayf.remember_choiceandwayf.remember_choice_per_idpare active.wayf.remember_choiceis true andwayf.remember_choice_per_idpis false, we keep the current global memory feature.wayf.remember_choiceis false, we disable all remember-my-choice features (both global and per-sp).wayf.remember_choice_per_idpis not defined, act as if it were set tofalsewayf.remember_choice_per_idp_lifetime. Typically this would be something like 3 months, but it would be nice to be able to set it to (e.g.) 60 seconds for easy debugging.wayf.remember_choice_per_idp_lifetime. This defaults to16. For the logic what to do if we exceed this limit, see below.support new
coin:wayf_remember_choicemetadata parameter for SPs. If this is not present in the metadata, it defaults tofalse.if feature is enabled, read and set a cookie
rememberedidpswith content like this:{ "https://sp_entityid_1": { "idp": "https://idp_entityid_1", "expires": 1784534287 }, "https://sp_entityid_2": { "idp": "https://idp_entityid_2", "expires": 1784512345 } }wayf.remember_choice_per_idp_maxparameter which defaults to 16 to be on the safe side.Max-AgeorExpiresproperty of the cookie need to be set in accordance with thewayf.remember_choice_per_idp_lifetimesetting. To reduce complexity, it is not dependent on the actualexpiresvalues in the cookie, so in cornercases (e.g., if thewayf.remember_choice_per_idp_lifetimeis reduced) it might occur that the cookie expires earlier than the individual entries in the cookie. That is acceptable behavior.SecureandHttpOnlyproperties (same as all other EB cookies).SameSiteshould probably be set toNonebecause we support both Redirect and POST bindings for SAMLRequests.If this feature is enabled (
wayf.remember_choice_per_idpis set) then do the following when determining whether to show the WAYF:coin:wayf_remember_choiceset in the metadataexpiryentry is in the futurecoin:wayf_remember_choicein the metadatarememberchoicecookie does). Log if this occurs with level INFO and message "WAYF-remember-my-choice WAYF skipped for because of preselected "Only update the cookie if the user set a new "remember my choice" checkbox. If changes are made, always update the cookie at the client like this:
timeis older than current time)If the cookie is only read and no changes are made by the user, the cookie does not need to be updated.
If the users gets the regular WAYF and selects the "remember my choice" checkbox, then do the following if per-SP remembering is enabled (if global remembering is enabled, the behaviour doesn't change):
expiresfield set tonow + wayf.remember_choice_per_idp_lifetime