Resolve scopes from bearer tokens when processing requests to the Account API

Closes #35357

Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com>
This commit is contained in:
Pedro Igor 2024-11-27 10:23:10 -03:00
parent 8a4651c664
commit 45f9bcd673
4 changed files with 29 additions and 2 deletions

View file

@ -167,8 +167,8 @@ Enabled when::
Enables or disables an attribute. If set to `Always`, the attribute is available from any user profile context.
If set to `Scopes are requested`, the attribute is only available when the client acting on behalf of the user is requesting a
set of one or more scopes. You can use this option to dynamically enforce certain attributes depending on the client scopes
being requested. For the account and administration consoles, scopes are not evaluated and the attribute is always enabled.
That is because filtering attributes by scopes only works when running authentication flows.
being requested. For the administration console, scopes are not evaluated and the attribute is always enabled.
That is because filtering attributes by scopes only works when running end-user authentication flows.
Required::
Set the conditions to mark an attribute as required. If disabled, the attribute is optional.

View file

@ -17,6 +17,7 @@
package org.keycloak.models;
import org.keycloak.Token;
import org.keycloak.common.ClientConnection;
import org.keycloak.http.HttpRequest;
import org.keycloak.http.HttpResponse;
@ -108,4 +109,8 @@ public interface KeycloakContext {
UserSessionModel getUserSession();
void setUserSession(UserSessionModel session);
Token getBearerToken();
void setBearerToken(Token token);
}

View file

@ -18,6 +18,7 @@
package org.keycloak.services;
import jakarta.ws.rs.core.HttpHeaders;
import org.keycloak.Token;
import org.keycloak.common.ClientConnection;
import org.keycloak.http.HttpRequest;
import org.keycloak.http.HttpResponse;
@ -60,6 +61,7 @@ public abstract class DefaultKeycloakContext implements KeycloakContext {
private HttpRequest request;
private HttpResponse response;
private ClientConnection clientConnection;
private Token bearerToken;
public DefaultKeycloakContext(KeycloakSession session) {
this.session = session;
@ -222,4 +224,14 @@ public abstract class DefaultKeycloakContext implements KeycloakContext {
public void setUserSession(UserSessionModel userSession) {
this.userSession = userSession;
}
@Override
public void setBearerToken(Token token) {
this.bearerToken = token;
}
@Override
public Token getBearerToken() {
return bearerToken;
}
}

View file

@ -17,6 +17,8 @@
package org.keycloak.services.managers;
import org.jboss.logging.Logger;
import org.keycloak.Token;
import org.keycloak.TokenCategory;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.cookie.CookieProvider;
import org.keycloak.cookie.CookieType;
@ -1537,6 +1539,7 @@ public class AuthenticationManager {
}
context.setUserSession(offlineUserSession);
context.setClient(client);
context.setBearerToken(token);
return new AuthResult(user, offlineUserSession, token, client);
}
}
@ -1568,6 +1571,7 @@ public class AuthenticationManager {
return null;
}
context.setClient(client);
context.setBearerToken(token);
}
context.setUserSession(userSession);
@ -1683,6 +1687,12 @@ public class AuthenticationManager {
public static String getRequestedScopes(KeycloakSession session, ClientModel client) {
KeycloakContext context = session.getContext();
Token bearerToken = context.getBearerToken();
if (bearerToken != null && TokenCategory.ACCESS.equals(bearerToken.getCategory())) {
return AccessToken.class.cast(bearerToken).getScope();
}
AuthenticationSessionModel authenticationSession = context.getAuthenticationSession();
if (authenticationSession != null) {