Mercurial > prosody-modules
comparison mod_http_oauth2/mod_http_oauth2.lua @ 5682: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 |
parents | 8cb3da7df521 |
children | 8488ebde5739 |
comparison
equal
deleted
inserted
replaced
5681:8cb3da7df521 | 5682:527c747711f3 |
---|---|
1097 jti = token_info.id; | 1097 jti = token_info.id; |
1098 }; | 1098 }; |
1099 }; | 1099 }; |
1100 end | 1100 end |
1101 | 1101 |
1102 -- 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 | |
1103 -- 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. | |
1102 local strict_auth_revoke = module:get_option_boolean("oauth2_require_auth_revoke", false); | 1104 local strict_auth_revoke = module:get_option_boolean("oauth2_require_auth_revoke", false); |
1103 | 1105 |
1104 local function handle_revocation_request(event) | 1106 local function handle_revocation_request(event) |
1105 local request, response = event.request, event.response; | 1107 local request, response = event.request, event.response; |
1106 response.headers.cache_control = "no-store"; | 1108 response.headers.cache_control = "no-store"; |
1107 response.headers.pragma = "no-cache"; | 1109 response.headers.pragma = "no-cache"; |
1108 if request.headers.authorization then | 1110 local credentials = get_request_credentials(request); |
1109 local credentials = get_request_credentials(request); | 1111 if credentials then |
1110 if not credentials or credentials.type ~= "basic" then | 1112 if credentials.type ~= "basic" then |
1111 response.headers.www_authenticate = string.format("Basic realm=%q", module.host.."/"..module.name); | 1113 response.headers.www_authenticate = string.format("Basic realm=%q", module.host.."/"..module.name); |
1112 return 401; | 1114 return 401; |
1113 end | 1115 end |
1114 -- OAuth "client" credentials | 1116 -- OAuth "client" credentials |
1115 if not verify_client_secret(credentials.username, credentials.password) then | 1117 if not verify_client_secret(credentials.username, credentials.password) then |
1125 local form_data = strict_formdecode(event.request.body); | 1127 local form_data = strict_formdecode(event.request.body); |
1126 if not form_data or not form_data.token then | 1128 if not form_data or not form_data.token then |
1127 response.headers.accept = "application/x-www-form-urlencoded"; | 1129 response.headers.accept = "application/x-www-form-urlencoded"; |
1128 return 415; | 1130 return 415; |
1129 end | 1131 end |
1132 | |
1133 if credentials then | |
1134 local client = check_client(credentials.username); | |
1135 if not client then | |
1136 return 401; | |
1137 end | |
1138 local token_info = tokens.get_token_info(form_data.token); | |
1139 if not token_info then | |
1140 return 404; | |
1141 end | |
1142 local token_client = token_info.grant.data.oauth2_client; | |
1143 if not token_client or token_client.hash ~= client.client_hash then | |
1144 return 403; | |
1145 end | |
1146 end | |
1147 | |
1130 local ok, err = tokens.revoke_token(form_data.token); | 1148 local ok, err = tokens.revoke_token(form_data.token); |
1131 if not ok then | 1149 if not ok then |
1132 module:log("warn", "Unable to revoke token: %s", tostring(err)); | 1150 module:log("warn", "Unable to revoke token: %s", tostring(err)); |
1133 return 500; | 1151 return 500; |
1134 end | 1152 end |