This repository has been archived by the owner on Apr 26, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Support for form_post in OIDC responses #9376
Merged
Merged
Changes from 5 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
91bfc69
OIDC: support receiving data from the auth endpoint via form_post
richvdh 93e0349
Set SameSite=None on oidc cookie
richvdh 4e7f8c5
changelog
richvdh 3b5ac3a
set two cookies
richvdh 1102094
fiddle with cookie options to pacify Safari
richvdh 14c24d7
Factor session cookie options out to a constant
richvdh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Add support for receiving OpenID Connect authentication responses via form `POST`s rather than `GET`s. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,6 +48,7 @@ | |
logger = logging.getLogger(__name__) | ||
|
||
SESSION_COOKIE_NAME = b"oidc_session" | ||
SESSION_COOKIE_NAME_IOS_HACK = b"oidc_session_no_samesite" | ||
|
||
#: A token exchanged from the token endpoint, as per RFC6749 sec 5.1. and | ||
#: OpenID.Core sec 3.1.3.3. | ||
|
@@ -149,26 +150,29 @@ async def handle_oidc_callback(self, request: SynapseRequest) -> None: | |
# otherwise, it is presumably a successful response. see: | ||
# https://tools.ietf.org/html/rfc6749#section-4.1.2 | ||
|
||
# Fetch the session cookie | ||
# Fetch the session cookie. See notes in handle_redirect_request about why | ||
# we have two of these. | ||
session = request.getCookie(SESSION_COOKIE_NAME) # type: Optional[bytes] | ||
if session is None: | ||
session = request.getCookie(SESSION_COOKIE_NAME_IOS_HACK) | ||
if session is None: | ||
logger.info("Received OIDC callback, with no session cookie") | ||
self._sso_handler.render_error( | ||
request, "missing_session", "No session cookie found" | ||
) | ||
return | ||
|
||
# Remove the cookie. There is a good chance that if the callback failed | ||
# Remove the cookies. There is a good chance that if the callback failed | ||
# once, it will fail next time and the code will already be exchanged. | ||
# Removing it early avoids spamming the provider with token requests. | ||
request.addCookie( | ||
SESSION_COOKIE_NAME, | ||
b"", | ||
path="/_synapse/oidc", | ||
expires="Thu, Jan 01 1970 00:00:00 UTC", | ||
httpOnly=True, | ||
sameSite="lax", | ||
) | ||
# Removing the cookies early avoids spamming the provider with token requests. | ||
for cookie_name, options in [ | ||
(SESSION_COOKIE_NAME, b"; SameSite=None"), | ||
(SESSION_COOKIE_NAME_IOS_HACK, b""), | ||
]: | ||
request.cookies.append( | ||
b"%s=; Path=/_synapse/client/oidc; Expires=Thu, Jan 01 1970 00:00:00 UTC; " | ||
b"HttpOnly; Secure%s" % (cookie_name, options) | ||
) | ||
|
||
# Check for the state query parameter | ||
if b"state" not in request.args: | ||
|
@@ -693,14 +697,33 @@ async def handle_redirect_request( | |
ui_auth_session_id=ui_auth_session_id, | ||
), | ||
) | ||
request.addCookie( | ||
SESSION_COOKIE_NAME, | ||
cookie, | ||
path="/_synapse/client/oidc", | ||
max_age="3600", | ||
httpOnly=True, | ||
sameSite="lax", | ||
) | ||
|
||
# we want the cookie to be returned to us even when the request is the POSTed | ||
# result of a form on another domain, as is used with `response_mode=form_post`. | ||
# | ||
# Modern browsers will not do so unless we set SameSite=None; however *older* | ||
# browsers (including all versions of Safari on iOS 12?) don't support | ||
# SameSite=None, and interpret it as SameSite=Strict: | ||
# https://bugs.webkit.org/show_bug.cgi?id=198181 | ||
# | ||
# As a rather painful workaround, we set *two* cookies, one with SameSite=None | ||
# and one with no SameSite, in the hope that at least one of them will get | ||
# back to us. | ||
# | ||
# Secure is necessary for SameSite=None (and, empirically, also breaks things | ||
# on iOS 12.) | ||
# | ||
# we have to build the cookie by hand rather than calling request.addCookie | ||
# to work around https://twistedmatrix.com/trac/ticket/10088 | ||
# | ||
for cookie_name, options in [ | ||
(SESSION_COOKIE_NAME, b"; Secure; SameSite=None"), | ||
(SESSION_COOKIE_NAME_IOS_HACK, b""), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These don't seem to match above where we clear out the cookies. In that case both are set to We should probably pull these out to constants. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ooops. fair. |
||
]: | ||
request.cookies.append( | ||
b"%s=%s; Path=/_synapse/client/oidc; Max-Age=3600; HttpOnly%s" | ||
% (cookie_name, cookie.encode("utf-8"), options) | ||
) | ||
|
||
metadata = await self.load_metadata() | ||
authorization_endpoint = metadata.get("authorization_endpoint") | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is to get around Twisted not supporting setting
SameSite=None
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes.