Software /
code /
prosody-modules
Diff
mod_http_oauth2/mod_http_oauth2.lua @ 5705:527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
RFC 7009 section 2.1 states:
> The authorization server first validates the client credentials (in
> case of a confidential client) and then verifies whether the token was
> issued to the client making the revocation request. If this
> validation fails, the request is refused and the client is informed of
> the error by the authorization server as described below.
The first part was already covered (in strict mode). This adds the later
part using the hash of client_id recorded in 0860497152af
It still seems weird to me that revoking a leaked token should not be
allowed whoever might have discovered it, as that seems the responsible
thing to do.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Sun, 29 Oct 2023 11:30:49 +0100 |
parent | 5704:8cb3da7df521 |
child | 5738:8488ebde5739 |
line wrap: on
line diff
--- a/mod_http_oauth2/mod_http_oauth2.lua Sun Oct 29 11:20:15 2023 +0100 +++ b/mod_http_oauth2/mod_http_oauth2.lua Sun Oct 29 11:30:49 2023 +0100 @@ -1099,15 +1099,17 @@ }; end +-- RFC 7009 says that the authorization server should validate that only the client that a token was issued to should be able to revoke it. However +-- this would prevent someone who comes across a leaked token from doing the responsible thing and revoking it, so this is not enforced by default. local strict_auth_revoke = module:get_option_boolean("oauth2_require_auth_revoke", false); local function handle_revocation_request(event) local request, response = event.request, event.response; response.headers.cache_control = "no-store"; response.headers.pragma = "no-cache"; - if request.headers.authorization then - local credentials = get_request_credentials(request); - if not credentials or credentials.type ~= "basic" then + local credentials = get_request_credentials(request); + if credentials then + if credentials.type ~= "basic" then response.headers.www_authenticate = string.format("Basic realm=%q", module.host.."/"..module.name); return 401; end @@ -1127,6 +1129,22 @@ response.headers.accept = "application/x-www-form-urlencoded"; return 415; end + + if credentials then + local client = check_client(credentials.username); + if not client then + return 401; + end + local token_info = tokens.get_token_info(form_data.token); + if not token_info then + return 404; + end + local token_client = token_info.grant.data.oauth2_client; + if not token_client or token_client.hash ~= client.client_hash then + return 403; + end + end + local ok, err = tokens.revoke_token(form_data.token); if not ok then module:log("warn", "Unable to revoke token: %s", tostring(err));