matrix-org / synapse

Synapse: Matrix homeserver written in Python/Twisted.
https://matrix-org.github.io/synapse
Apache License 2.0
11.82k stars 2.13k forks source link

Support unsigned id_tokens for OIDC providers #9250

Open tmortagne opened 3 years ago

tmortagne commented 3 years ago

Description

I enable OpenID Connect in Synapse to login with user accounts located in an OpenID Connect provider.

I'm testing my server configuration using the client on https://app.element.io.

The following happen:

 There was an error during authentication:
unsupported_algorithm:

If you are seeing this page after clicking a link sent to you via email, make sure you only click the confirmation link once, and that you open the validation link in the same client you're logging in from.

Try logging in again from your Matrix client and if the problem persists please contact the server's administrator.

Error: invalid_token

in the following in the log:

2021-01-28 14:10:36,898 - synapse.http.client - 429 - INFO - GET-7 - Received response to POST https://intra.atelier-medias.org:443/xwiki/oidc/token: 200
2021-01-28 14:10:36,899 - synapse.handlers.oidc_handler - 671 - ERROR - GET-7 - Invalid id_token
Traceback (most recent call last):
  File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/synapse/handlers/oidc_handler.py", line 669, in handle_oidc_callback
    userinfo = await self._parse_id_token(token, nonce=nonce)
  File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/synapse/handlers/oidc_handler.py", line 459, in _parse_id_token
    claims_params=claims_params,
  File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/authlib/jose/rfc7519/jwt.py", line 99, in decode
    data = self._jws.deserialize_compact(s, load_key, decode_payload)
  File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/authlib/jose/rfc7515/jws.py", line 102, in deserialize_compact
    algorithm, key = self._prepare_algorithm_key(jws_header, payload, key)
  File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/authlib/jose/rfc7515/jws.py", line 249, in _prepare_algorithm_key
    raise UnsupportedAlgorithmError()
authlib.jose.errors.UnsupportedAlgorithmError: unsupported_algorithm: 

I'm not fully sure what it exactly means by "unsupported_algorithm" but this OpenID Connect provider returns plain tokens (not encrypted or signed tokens) which is perfectly valid from OpenID Connect protocol point of view, but maybe it's related ? Just in case, I tried to set skip_verification: true but it does not seems to help.

Version information

Synapse 1.26 installed with matrix-synapse-py3 on Debian Stretch. Python 3.5 (I noticed a warning about the Python version but that's the version I got on Debian Stretch, so I hope it's not related...)

richvdh commented 3 years ago

Synapse 1.26 installed with matrix-synapse-py3 on Debian Stretch.

are you sure?

 File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/synapse/handlers/oidc_handler.py", line 459, in _parse_id_token
   claims_params=claims_params,

that is not what line 459 of that file looks like in 1.26.0.

I'm not fully sure what it exactly means by "unsupported_algorithm" but this OpenID Connect provider returns plain tokens (not encrypted or signed tokens) which is perfectly valid from OpenID Connect protocol point of view, but maybe it's related ?

yes, this does sound related. I might be misunderstanding, but https://openid.net/specs/openid-connect-core-1_0.html#IDToken says: "ID Tokens MUST be signed using JWS...", so I'm not entirely sure that it is valid?

Perhaps you could explain a little more about the format of the response you're getting back from the token endpoint?

tmortagne commented 3 years ago

Synapse 1.26 installed with matrix-synapse-py3 on Debian Stretch.

are you sure?

Indeed, I just checked what was the last version assuming that's what I had but seems the Debian repository was not fully up to date back then. So my exact version according to apt is 1.25.0+stretch1

I might be misunderstanding, but openid.net/specs/openid-connect-core-1_0.html#IDToken says: "ID Tokens MUST be signed using JWS...", so I'm not entirely sure that it is valid?

Indeed, that line is pretty explicit. Yet I never had this issue before. On Open Source side I tested it with Discourse and Weblate OpenID Connect support for example and I also implemented an OpenID Connect authenticator using oauth2-oidc-sdk (a Java framework to deal with OIDC protocol) and when I take a look at their source code they are doing the following (that part is actually in nimbus-jose-jwt project):

        if (alg.equals(Algorithm.NONE)) {
            return PlainJWT.parse(s);
        } else if (alg instanceof JWSAlgorithm) {
            return SignedJWT.parse(s);
        } else if (alg instanceof JWEAlgorithm) {
            return EncryptedJWT.parse(s);
        } else {
            throw new AssertionError("Unexpected algorithm type: " + alg);
        }

It seems that what I assumed to be "perfectly valid from OpenID Connect protocol point of view" (never do a grand claim like this unless you really are an expert in the field...) is actually client's bulletproofing for OAuth2 (the reference documentation suggests that signing the token is an OIDC specific extension) and lazy OpenID Connect providers.

Looks like the OIDC provider I'm using would need some improvement but would you consider adding the same kind of bulletproofing on Synapse OIDC support side than the one above ?

richvdh commented 3 years ago

In principle I think that would be fine (I'm not really sure what benefit signing the token gives, given that the signing key is retrieved from the same place as the token).

However, I don't think it's something we're likely to work on in the team for a while.

tmortagne commented 3 years ago

OK thanks @richvdh, I might try to take a look at it but might take a while to get started given my poor experience of Python.

gabrc52 commented 1 year ago

image

It looks like the signature verification for tokens can be disabled (as a hack/workaround) by commenting out this part of the code in /opt/venvs/matrix-synapse/lib/python3.10/site-packages/synapse/handlers/oidc.py

https://github.com/matrix-org/synapse/blob/develop/synapse/handlers/oidc.py#L1016

It looks like solving this issue is a matter of creating a new configuration option, and only running that part of the code depending on it, so it should be relatively straightforward. @tmortagne would you still be interested in this feature?

(In my case, my tokens seem to be signed but for some reason the validation fails, and I'm not sure if I need to do a change from the oidc server settings or from synapse.)

tmortagne commented 1 year ago

@tmortagne would you still be interested in this feature?

I don't have the need anymore (I took the high road and implemented signature support on the provider side after all :) ) but I still feel it should be supported as I encountered other providers without signature support. Now on the implementation side it feels like what's needed is more bulletproofing than an option by default (as it seems to be possible to see that the id is "officially" not signed before trying to validate it "algorithm").

jcollie commented 1 year ago

I ran into this today trying to use Authentik and I had to add "skip_verifification: true" to the OIDC provider config to get things to work. With out that I would get invalid parameters if Authentik wasn't signing the token, and unsupported protocol if Authentik was signing the token. I verified that I was using RSA keys in Authentik.

yodatak commented 1 year ago

Hi i got the same issue and cannot make the authentik sso works with synapse any way to update https://matrix-org.github.io/synapse/latest/openid.html to make it works ?