Browse Source

Put OIDC callback URI under /_synapse/client. (#9288)

tags/v1.27.0rc1
Richard van der Hoff 3 years ago
committed by GitHub
parent
commit
846b9d3df0
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 46 additions and 28 deletions
  1. +4
    -0
      CHANGES.md
  2. +12
    -1
      UPGRADE.rst
  3. +1
    -0
      changelog.d/9288.feature
  4. +10
    -9
      docs/openid.md
  5. +1
    -1
      docs/workers.md
  6. +1
    -1
      synapse/config/oidc_config.py
  7. +4
    -4
      synapse/handlers/oidc_handler.py
  8. +2
    -2
      synapse/rest/synapse/client/__init__.py
  9. +5
    -1
      synapse/rest/synapse/client/oidc/__init__.py
  10. +0
    -0
      synapse/rest/synapse/client/oidc/callback_resource.py
  11. +6
    -9
      tests/handlers/test_oidc.py

+ 4
- 0
CHANGES.md View File

@@ -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)
===========================


+ 12
- 1
UPGRADE.rst View File

@@ -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
-------------------------

@@ -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:


+ 1
- 0
changelog.d/9288.feature View File

@@ -0,0 +1 @@
Update the redirect URI for OIDC authentication.

+ 10
- 9
docs/openid.md View File

@@ -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.
@@ -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'
```

@@ -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:
@@ -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>
@@ -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:

@@ -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:

@@ -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:

@@ -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.


+ 1
- 1
docs/workers.md View File

@@ -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$


+ 1
- 1
synapse/config/oidc_config.py View File

@@ -53,7 +53,7 @@ class OIDCConfig(Config):
"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:


+ 4
- 4
synapse/handlers/oidc_handler.py View File

@@ -102,7 +102,7 @@ class OidcHandler:
) 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
@@ -643,7 +643,7 @@ class OidcProvider:

- ``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
@@ -684,7 +684,7 @@ class OidcProvider:
request.addCookie(
SESSION_COOKIE_NAME,
cookie,
path="/_synapse/oidc",
path="/_synapse/client/oidc",
max_age="3600",
httpOnly=True,
sameSite="lax",
@@ -705,7 +705,7 @@ class OidcProvider:
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:


+ 2
- 2
synapse/rest/synapse/client/__init__.py View File

@@ -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


synapse/rest/oidc/__init__.py → synapse/rest/synapse/client/oidc/__init__.py View File

@@ -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__)

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


__all__ = ["OIDCResource"]

synapse/rest/oidc/callback_resource.py → synapse/rest/synapse/client/oidc/callback_resource.py View File


+ 6
- 9
tests/handlers/test_oidc.py View File

@@ -40,7 +40,7 @@ ISSUER = "https://issuer/"
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"
@@ -58,12 +58,6 @@ COMMON_CONFIG = {
}


# 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):
@@ -340,8 +334,11 @@ class OidcHandlerTestCase(HomeserverTestCase):
# 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)


Loading…
Cancel
Save