All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.phasetwo.keycloak.resources.AbstractAdminResource Maven / Gradle / Ivy

There is a newer version: 0.32
Show newest version
package io.phasetwo.keycloak.resources;

import jakarta.validation.constraints.*;
import jakarta.ws.rs.*;
import jakarta.ws.rs.NotAuthorizedException;
import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.core.HttpHeaders;
import lombok.extern.jbosslog.JBossLog;
import org.keycloak.common.ClientConnection;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.jose.jws.JWSInputException;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.representations.AccessToken;
import org.keycloak.services.managers.AppAuthManager;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resources.admin.AdminAuth;
import org.keycloak.services.resources.admin.AdminEventBuilder;
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.services.resources.admin.permissions.AdminPermissions;
import org.keycloak.services.resources.admin.permissions.ManagementPermissions;

@JBossLog
public abstract class AbstractAdminResource {

  protected final ClientConnection connection;
  protected final HttpHeaders headers;
  protected final KeycloakSession session;
  protected final RealmModel realm;

  protected AdminAuth auth;
  protected AdminEventBuilder adminEvent;
  protected AdminPermissionEvaluator permissions;

  protected AbstractAdminResource(KeycloakSession session) {
    this.session = session;
    this.realm = session.getContext().getRealm();
    this.headers = session.getContext().getRequestHeaders();
    this.connection = session.getContext().getConnection();
  }

  public void setup() {
    setupAuth();
    setupEvents();
    setupPermissions();
    setupCors();
  }

  public void requireAdminRole(String role) {
    if (!hasAdminRole(role))
      throw new NotAuthorizedException(String.format("%s role is required", role));
  }

  public boolean hasAdminRole(String role) {
    return ManagementPermissions.hasOneAdminRole(session, realm, auth, role);
  }

  private void setupCors() {
    CorsResource.setupCors(session, auth);
  }

  private void setupAuth() {
    auth = authenticateRealmAdminRequest(headers);
  }

  private void setupEvents() {
    adminEvent =
        new AdminEventBuilder(this.realm, auth, session, session.getContext().getConnection())
            .realm(realm);
  }

  private void setupPermissions() {
    permissions = AdminPermissions.evaluator(session, realm, auth);
  }

  private AdminAuth authenticateRealmAdminRequest(HttpHeaders headers) {
    String tokenString = AppAuthManager.extractAuthorizationHeaderToken(headers);
    if (tokenString == null) throw new NotAuthorizedException("Bearer");
    AccessToken token;
    try {
      JWSInput input = new JWSInput(tokenString);
      token = input.readJsonContent(AccessToken.class);
    } catch (JWSInputException e) {
      throw new NotAuthorizedException("Bearer token format error");
    }
    String realmName = token.getIssuer().substring(token.getIssuer().lastIndexOf('/') + 1);
    RealmManager realmManager = new RealmManager(session);
    RealmModel realm = realmManager.getRealmByName(realmName);
    if (realm == null) {
      throw new NotAuthorizedException("Unknown realm in token");
    }
    session.getContext().setRealm(realm);

    AuthenticationManager.AuthResult authResult =
        new AppAuthManager.BearerTokenAuthenticator(session)
            .setRealm(realm)
            .setConnection(connection)
            .setHeaders(headers)
            .authenticate();

    if (authResult == null) {
      log.debug("Token not valid");
      throw new NotAuthorizedException("Bearer");
    }

    ClientModel client = realm.getClientByClientId(token.getIssuedFor());
    if (client == null) {
      throw new NotFoundException("Could not find client for authorization");
    }

    return new AdminAuth(realm, authResult.getToken(), authResult.getUser(), client);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy