diff --git a/docs/backends/openid.rst b/docs/backends/openid.rst index 3139795b..b1c8870a 100644 --- a/docs/backends/openid.rst +++ b/docs/backends/openid.rst @@ -36,9 +36,11 @@ the first transaction; the earlier callback is rejected. Unsolicited assertions are rejected, including for anonymous users. Always use the normal backend initiation path. -When the framework supports restoring sessions, only a session identifier carried -by the provider-signed ``openid.return_to`` can select that session. Missing or -mismatched state requires the user to restart authentication. +The signed ``openid.return_to`` cannot select a session. OpenID callbacks use +the browser's current session and reject the former session identifier in the +return URL or callback. Missing or mismatched state requires the user to +restart authentication. In-progress logins started before this change must +also restart. The generic ``openid`` backend remains provider-selectable because the application user supplies its provider URL. Backends configured for one @@ -51,9 +53,9 @@ Custom backends with a fixed ``URL`` receive provider binding automatically. A custom backend that computes a fixed-provider URL in ``openid_url()`` must override ``requires_openid_provider_binding()`` to return ``True``. Provider discovery URLs and discovered provider endpoints must use HTTPS; there is no -setting to disable this validation. Custom strategies that implement session -restoration must restore the complete OpenID session state and update -session-derived pipeline arguments, including the authenticated user. +setting to disable this validation. Custom backends must validate callbacks +against the initiating browser session. The old strategy session-restoration +methods have been removed; custom backends that used them must migrate. Custom backends overriding authorization URL or HTML generation must include the transaction value in the provider-signed return URL, for example by calling diff --git a/docs/backends/saml.rst b/docs/backends/saml.rst index a51ec838..9c70de96 100644 --- a/docs/backends/saml.rst +++ b/docs/backends/saml.rst @@ -306,32 +306,32 @@ usually return the response with a cross-site POST request. Django's default ``SESSION_COOKIE_SAMESITE = "Lax"`` setting prevents the session cookie from being sent with that request. -``social-auth-app-django`` preserves the server-side session identifier in -SAML ``RelayState`` and restores the session before validating the response. -The restored session key is rotated before continued use; do not override -restoration in a way that retains the old key or changes the initiating user. -Use a current ``social-auth-app-django`` release and a server-side Django -session engine. In multi-instance deployments, every instance that can handle -the login or callback must use the same session storage. Database and cached -database engines meet this requirement when configured with shared services. -The cache engine must use a shared backend, and the file engine is suitable -only for a single instance or a shared filesystem. The signed-cookie session -backend cannot restore session changes through this mechanism. - -Also verify that the login was initiated by the same browser, that the Identity -Provider returns ``RelayState`` unchanged, and that only one SAML login is -active for the Identity Provider in that browser session. - -If the callback carries an authenticated Django session for a different user -than the session restored from ``RelayState``, ``social-auth-app-django`` -rejects it with a ``user_mismatch`` error and preserves the current session. -Restart the SAML login while signed in as the account that should receive the -association. - -As a workaround, ``SESSION_COOKIE_SAMESITE`` can be set to ``"None"`` so the -cookie is sent with the cross-site POST. This requires secure HTTPS cookies and -reduces the protection provided by the SameSite policy, so prefer server-side -session restoration. +``social-auth-core`` first returns a short page on the application origin. +That page automatically reposts the SAML response to the completion endpoint; +the browser's SameSite=Lax session cookie accompanies the second POST. If +automatic submission is blocked, the user can select **Continue signing in**. +The backend then checks the signed response against the AuthnRequest in that +browser session. Use ``social-auth-core`` 7.0.0 or later. Integrations with +custom strategy responses must support the headers described in +:doc:`Strategies <../strategies>`. The older session identifier in +``RelayState`` is ignored. In-progress SAML logins started before upgrading +must restart. + +Verify that login was initiated by the same browser and that only one SAML +login is active for the Identity Provider in that browser session. Browser +policies blocking automatic form submission may require the user to select +the continuation button. + +SAML responses without a matching SP AuthnRequest are rejected by default. +Deployments that require IdP-initiated SSO can set +``SOCIAL_AUTH_SAML_ALLOW_IDP_INITIATED = True``. This accepts unsolicited +signed responses for anonymous browsers and therefore permits login CSRF: +someone with a trusted IdP account can cause another anonymous browser to +sign in as them. Do not enable it where browser-bound login is required. + +``SESSION_COOKIE_SAMESITE = "None"`` also sends the cookie with the initial +cross-site POST, but requires secure HTTPS cookies and reduces SameSite +protection. The browser return page works with the default ``"Lax"`` setting. **Error: "Missing needed parameter first_name (configured by attr_first_name)"** diff --git a/docs/security.rst b/docs/security.rst index 688a75a6..8f5667f6 100644 --- a/docs/security.rst +++ b/docs/security.rst @@ -63,7 +63,7 @@ Review the selected backend's limits, especially :doc:`backends/telegram`, :doc:`backends/vk` and :doc:`backends/odnoklassnikiru`. For Django, see :doc:`configuration/django` for protected routes and launch -bridges, :doc:`backends/saml` for cross-site session restoration, and +bridges, :doc:`backends/saml` for the SAML browser return flow, and :ref:`partial-pipeline` for confirmation and template requirements. .. _oauth2-transaction-state: diff --git a/docs/strategies.rst b/docs/strategies.rst index bc4fe3f9..0fbcf24b 100644 --- a/docs/strategies.rst +++ b/docs/strategies.rst @@ -54,6 +54,11 @@ Session:: """Pop session value for given key""" raise NotImplementedError('Implement in subclass') +``get_session_id()`` and ``restore_session()`` have been removed from the +strategy interface. Callbacks must use the initiating browser's session; +custom backends that used these methods need to migrate to browser-bound +correlation. + Settings:: @@ -76,6 +81,12 @@ Responses:: """Render given template or raw html with given context""" raise NotImplementedError('Implement in subclass') +``BaseStrategy.html_with_headers(content, headers)`` is a required strategy +hook for returning HTML with the specified HTTP headers. SAML POST callbacks +use it for a protected browser return page. Integrations must implement this +hook using their framework's response API. A custom strategy without the hook +fails closed during SAML completion. The Django strategy implements it. + Effective pipeline request data -------------------------------