# HG changeset patch # User Kim Alvefur # Date 1698575449 -3600 # Node ID 527c747711f32def5a9ffedb0845207184b2c391 # Parent 8cb3da7df521fae119b41d3ecf3d6d7ed21df7d3 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. diff -r 8cb3da7df521 -r 527c747711f3 mod_http_oauth2/mod_http_oauth2.lua --- 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));