Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Commit

Permalink
Put OIDC callback URI under /_synapse/client. (#9288)
Browse files Browse the repository at this point in the history
  • Loading branch information
richvdh authored Feb 1, 2021
1 parent d1f13c7 commit 846b9d3
Show file tree
Hide file tree
Showing 11 changed files with 46 additions and 28 deletions.
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ Unreleased

Note that this release includes a change in Synapse to use Redis as a cache ─ as well as a pub/sub mechanism ─ if Redis support is enabled. No action is needed by server administrators, and we do not expect resource usage of the Redis instance to change dramatically.

This release also changes the callback URI for OpenID Connect (OIDC) identity
providers. If your server is configured to use single sign-on via an
OIDC/OAuth2 IdP, you may need to make configuration changes. Please review
[UPGRADE.rst](UPGRADE.rst) for more details on these changes.

Synapse 1.26.0 (2021-01-27)
===========================
Expand Down
13 changes: 12 additions & 1 deletion UPGRADE.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,17 @@ for example:
Upgrading to v1.27.0
====================

Changes to callback URI for OAuth2 / OpenID Connect
---------------------------------------------------

This version changes the URI used for callbacks from OAuth2 identity providers. If
your server is configured for single sign-on via an OpenID Connect or OAuth2 identity
provider, you will need to add ``[synapse public baseurl]/_synapse/client/oidc/callback``
to the list of permitted "redirect URIs" at the identity provider.

See `docs/openid.md <docs/openid.md>`_ for more information on setting up OpenID
Connect.

Changes to HTML templates
-------------------------

Expand Down Expand Up @@ -235,7 +246,7 @@ shown below:
return {"localpart": localpart}
Removal historical Synapse Admin API
Removal historical Synapse Admin API
------------------------------------

Historically, the Synapse Admin API has been accessible under:
Expand Down
1 change: 1 addition & 0 deletions changelog.d/9288.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Update the redirect URI for OIDC authentication.
19 changes: 10 additions & 9 deletions docs/openid.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ Here are a few configs for providers that should work with Synapse.
### Microsoft Azure Active Directory
Azure AD can act as an OpenID Connect Provider. Register a new application under
*App registrations* in the Azure AD management console. The RedirectURI for your
application should point to your matrix server: `[synapse public baseurl]/_synapse/oidc/callback`
application should point to your matrix server:
`[synapse public baseurl]/_synapse/client/oidc/callback`

Go to *Certificates & secrets* and register a new client secret. Make note of your
Directory (tenant) ID as it will be used in the Azure links.
Expand Down Expand Up @@ -94,7 +95,7 @@ staticClients:
- id: synapse
secret: secret
redirectURIs:
- '[synapse public baseurl]/_synapse/oidc/callback'
- '[synapse public baseurl]/_synapse/client/oidc/callback'
name: 'Synapse'
```

Expand Down Expand Up @@ -140,7 +141,7 @@ Follow the [Getting Started Guide](https://www.keycloak.org/getting-started) to
| Enabled | `On` |
| Client Protocol | `openid-connect` |
| Access Type | `confidential` |
| Valid Redirect URIs | `[synapse public baseurl]/_synapse/oidc/callback` |
| Valid Redirect URIs | `[synapse public baseurl]/_synapse/client/oidc/callback` |

5. Click `Save`
6. On the Credentials tab, update the fields:
Expand Down Expand Up @@ -168,7 +169,7 @@ oidc_providers:
### [Auth0][auth0]

1. Create a regular web application for Synapse
2. Set the Allowed Callback URLs to `[synapse public baseurl]/_synapse/oidc/callback`
2. Set the Allowed Callback URLs to `[synapse public baseurl]/_synapse/client/oidc/callback`
3. Add a rule to add the `preferred_username` claim.
<details>
<summary>Code sample</summary>
Expand Down Expand Up @@ -217,7 +218,7 @@ login mechanism needs an attribute to uniquely identify users, and that endpoint
does not return a `sub` property, an alternative `subject_claim` has to be set.

1. Create a new OAuth application: https://github.com/settings/applications/new.
2. Set the callback URL to `[synapse public baseurl]/_synapse/oidc/callback`.
2. Set the callback URL to `[synapse public baseurl]/_synapse/client/oidc/callback`.

Synapse config:

Expand Down Expand Up @@ -262,13 +263,13 @@ oidc_providers:
display_name_template: "{{ user.name }}"
```
4. Back in the Google console, add this Authorized redirect URI: `[synapse
public baseurl]/_synapse/oidc/callback`.
public baseurl]/_synapse/client/oidc/callback`.

### Twitch

1. Setup a developer account on [Twitch](https://dev.twitch.tv/)
2. Obtain the OAuth 2.0 credentials by [creating an app](https://dev.twitch.tv/console/apps/)
3. Add this OAuth Redirect URL: `[synapse public baseurl]/_synapse/oidc/callback`
3. Add this OAuth Redirect URL: `[synapse public baseurl]/_synapse/client/oidc/callback`

Synapse config:

Expand All @@ -290,7 +291,7 @@ oidc_providers:

1. Create a [new application](https://gitlab.com/profile/applications).
2. Add the `read_user` and `openid` scopes.
3. Add this Callback URL: `[synapse public baseurl]/_synapse/oidc/callback`
3. Add this Callback URL: `[synapse public baseurl]/_synapse/client/oidc/callback`

Synapse config:

Expand Down Expand Up @@ -323,7 +324,7 @@ one so requires a little more configuration.
2. Once the app is created, add "Facebook Login" and choose "Web". You don't
need to go through the whole form here.
3. In the left-hand menu, open "Products"/"Facebook Login"/"Settings".
* Add `[synapse public baseurl]/_synapse/oidc/callback` as an OAuth Redirect
* Add `[synapse public baseurl]/_synapse/client/oidc/callback` as an OAuth Redirect
URL.
4. In the left-hand menu, open "Settings/Basic". Here you can copy the "App ID"
and "App Secret" for use below.
Expand Down
2 changes: 1 addition & 1 deletion docs/workers.md
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ using):
^/_synapse/client/sso_register$

# OpenID Connect requests.
^/_synapse/oidc/callback$
^/_synapse/client/oidc/callback$

# SAML requests.
^/_matrix/saml2/authn_response$
Expand Down
2 changes: 1 addition & 1 deletion synapse/config/oidc_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def read_config(self, config, **kwargs):
"Multiple OIDC providers have the idp_id %r." % idp_id
)

self.oidc_callback_url = self.public_baseurl + "_synapse/oidc/callback"
self.oidc_callback_url = self.public_baseurl + "_synapse/client/oidc/callback"

@property
def oidc_enabled(self) -> bool:
Expand Down
8 changes: 4 additions & 4 deletions synapse/handlers/oidc_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ async def load_metadata(self) -> None:
) from e

async def handle_oidc_callback(self, request: SynapseRequest) -> None:
"""Handle an incoming request to /_synapse/oidc/callback
"""Handle an incoming request to /_synapse/client/oidc/callback
Since we might want to display OIDC-related errors in a user-friendly
way, we don't raise SynapseError from here. Instead, we call
Expand Down Expand Up @@ -643,7 +643,7 @@ async def handle_redirect_request(
- ``client_id``: the client ID set in ``oidc_config.client_id``
- ``response_type``: ``code``
- ``redirect_uri``: the callback URL ; ``{base url}/_synapse/oidc/callback``
- ``redirect_uri``: the callback URL ; ``{base url}/_synapse/client/oidc/callback``
- ``scope``: the list of scopes set in ``oidc_config.scopes``
- ``state``: a random string
- ``nonce``: a random string
Expand Down Expand Up @@ -684,7 +684,7 @@ async def handle_redirect_request(
request.addCookie(
SESSION_COOKIE_NAME,
cookie,
path="/_synapse/oidc",
path="/_synapse/client/oidc",
max_age="3600",
httpOnly=True,
sameSite="lax",
Expand All @@ -705,7 +705,7 @@ async def handle_redirect_request(
async def handle_oidc_callback(
self, request: SynapseRequest, session_data: "OidcSessionData", code: str
) -> None:
"""Handle an incoming request to /_synapse/oidc/callback
"""Handle an incoming request to /_synapse/client/oidc/callback
By this time we have already validated the session on the synapse side, and
now need to do the provider-specific operations. This includes:
Expand Down
4 changes: 2 additions & 2 deletions synapse/rest/synapse/client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ def build_synapse_client_resource_tree(hs: "HomeServer") -> Mapping[str, Resourc
# provider-specific SSO bits. Only load these if they are enabled, since they
# rely on optional dependencies.
if hs.config.oidc_enabled:
from synapse.rest.oidc import OIDCResource
from synapse.rest.synapse.client.oidc import OIDCResource

resources["/_synapse/oidc"] = OIDCResource(hs)
resources["/_synapse/client/oidc"] = OIDCResource(hs)

if hs.config.saml2_enabled:
from synapse.rest.saml2 import SAML2Resource
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging

from twisted.web.resource import Resource

from synapse.rest.oidc.callback_resource import OIDCCallbackResource
from synapse.rest.synapse.client.oidc.callback_resource import OIDCCallbackResource

logger = logging.getLogger(__name__)

Expand All @@ -25,3 +26,6 @@ class OIDCResource(Resource):
def __init__(self, hs):
Resource.__init__(self)
self.putChild(b"callback", OIDCCallbackResource(hs))


__all__ = ["OIDCResource"]
15 changes: 6 additions & 9 deletions tests/handlers/test_oidc.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
CLIENT_ID = "test-client-id"
CLIENT_SECRET = "test-client-secret"
BASE_URL = "https://synapse/"
CALLBACK_URL = BASE_URL + "_synapse/oidc/callback"
CALLBACK_URL = BASE_URL + "_synapse/client/oidc/callback"
SCOPES = ["openid"]

AUTHORIZATION_ENDPOINT = ISSUER + "authorize"
Expand All @@ -58,12 +58,6 @@
}


# The cookie name and path don't really matter, just that it has to be coherent
# between the callback & redirect handlers.
COOKIE_NAME = b"oidc_session"
COOKIE_PATH = "/_synapse/oidc"


class TestMappingProvider:
@staticmethod
def parse_config(config):
Expand Down Expand Up @@ -340,8 +334,11 @@ def test_redirect_request(self):
# For some reason, call.args does not work with python3.5
args = calls[0][0]
kwargs = calls[0][1]
self.assertEqual(args[0], COOKIE_NAME)
self.assertEqual(kwargs["path"], COOKIE_PATH)

# The cookie name and path don't really matter, just that it has to be coherent
# between the callback & redirect handlers.
self.assertEqual(args[0], b"oidc_session")
self.assertEqual(kwargs["path"], "/_synapse/client/oidc")
cookie = args[1]

macaroon = pymacaroons.Macaroon.deserialize(cookie)
Expand Down

0 comments on commit 846b9d3

Please sign in to comment.