Mercurial > prosody-modules
changeset 5447:aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
When registering a client, a scope field can be included as a promise to
only ever use those. Here we enforce that promise, if given, ensuring a
client can't request or be granted a scope it didn't provide in its
registration. While currently there is no restrictions at registration
time, this could be changed in the future in various ways.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Thu, 11 May 2023 19:33:44 +0200 (19 months ago) |
parents | dd7bddc87f98 |
children | 9d542e86e19a |
files | mod_http_oauth2/mod_http_oauth2.lua |
diffstat | 1 files changed, 21 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/mod_http_oauth2/mod_http_oauth2.lua Thu May 11 21:37:35 2023 +0200 +++ b/mod_http_oauth2/mod_http_oauth2.lua Thu May 11 19:33:44 2023 +0200 @@ -477,14 +477,14 @@ }; end - local scope = array():append(form):filter(function(field) + local scopes = array():append(form):filter(function(field) return field.name == "scope"; - end):pluck("value"):concat(" "); + end):pluck("value"); user.token = form.user_token; return { user = user; - scope = scope; + scopes = scopes; consent = form.consent == "granted"; }; end @@ -649,13 +649,21 @@ return oauth_error("invalid_client", "response_type not allowed"); end + local requested_scopes = parse_scopes(params.scope or ""); + if client.scope then + local client_scopes = set.new(parse_scopes(client.scope)); + requested_scopes:filter(function(scope) + return client_scopes:contains(scope); + end); + end + local auth_state = get_auth_state(request); if not auth_state.user then -- Render login page return render_page(templates.login, { state = auth_state, client = client }); elseif auth_state.consent == nil then -- Render consent page - local scopes, roles = split_scopes(parse_scopes(params.scope or "")); + local scopes, roles = split_scopes(requested_scopes); return render_page(templates.consent, { state = auth_state; client = client; scopes = scopes+roles }, true); elseif not auth_state.consent then -- Notify client of rejection @@ -663,7 +671,15 @@ end -- else auth_state.consent == true - params.scope = auth_state.scope; + local granted_scopes = auth_state.scopes + if client.scope then + local client_scopes = set.new(parse_scopes(client.scope)); + granted_scopes:filter(function(scope) + return client_scopes:contains(scope); + end); + end + + params.scope = granted_scopes:concat(" "); local user_jid = jid.join(auth_state.user.username, module.host); local client_secret = make_client_secret(params.client_id);