nextcloud / user_oidc

OIDC connect user backend for Nextcloud
GNU Affero General Public License v3.0
76 stars 29 forks source link

Audience claim verification check with Bearer token #856

Closed SagarGi closed 3 weeks ago

SagarGi commented 2 months ago

Description

I am currently in a situation where i have an access_token for nextcloud which i got from keycloak. The user_oidc app allows a setting to make API request as bearer-auth using the access_token. In the access_token i have an audience claim for example another-client other than nextcloud itself.

for example:

{
    "exp": 1714648426,
    "iat": 1714647826,
    "auth_time": 1714647781,
    "jti": "8ebabf79-7a87-4c74-86fe-58e24300677b",
    "iss": "https://keycloak.local/realms/opendesk",
    `"aud": "https://openproject.local"`,
    "sub": "6b65f442-e0a2-4e2d-ac0a-32506dd57f41",
    "typ": "Bearer",
    "azp": "nextcloud",
    "session_state": "28b06352-4cb6-4fca-9487-11795e1ec7a2",
}

In the above payload of the access_token the audience claim is "aud": "https://openproject.local" which is not nextcloud. And i am able to make API request with it.

I have some question regarding it.

julien-nc commented 2 months ago

Does the user_oidc app check and verify the audience claim in the access_token for API request?

No, only the token expiration is checked: https://github.com/nextcloud/user_oidc/blob/main/lib/User/Validator/SelfEncodedValidator.php#L67-L71

There are many more checks done when obtaining a token during login: https://github.com/nextcloud/user_oidc/blob/main/lib/Controller/LoginController.php#L444-L484

It is kind of intended. I mean, the goal is to let other services (using the same client from the same IdP) make API requests to NC.

Why are you asking? Do you expect the validation to fail in this case?

SagarGi commented 1 month ago

@julien-nc Any other services making request with the nextcloud with any audience claim seemed a bit odd. Also i might lack knowledge why the audience claim is not verified and checked in user_oidc. But we want to have a situation in NC+OP integration where the services knows that the token is intended only for it to make requests.

julien-nc commented 1 month ago

Is the audience supposed to always be the Oidc client ID? If so, then we can validate the audience and this means only tokens obtained by OP with the same Oidc client than NC could be used to make requests against NC.

wielinde commented 1 month ago

Hey @julien-nc, AFAIK Keycloak's token endpoint allows replacing one token for another. So, if OP has one access token with the OP client as audience it, then OP can request a new token with it to get another access token with the desired audience, the Nextcloud client. For that to work Keycloak's realm needs to have set policies that allow this. The Keycloak docs explain that. See Keycloak's docs (paragraph 7) on token exchange https://www.keycloak.org/docs/latest/securing_apps/index.html#_token-exchange

If you think it from the other way around: if you don't have audience awareness during authorisation you could (mis)use the same token for requests in the other direction. Without an audience check any Keycloak access token from a client within the same realm will authorize in Nextcloud, even though it was originally given to a completely different client, e. g. some untrustworthy service that you would only give little permissions/scopes within Keycloak.

julien-nc commented 1 month ago

Ok then I guess we can add audience check in the bearer token validation. This would be the same check as when getting the login token, we would check the audience is the Oidc client ID. Let's make this check optional and enable by default. Wdyt?

wielinde commented 1 month ago

@julien-nc Sounds great! Thank you!