From a0bf4ee541bf280f730a69bf668aabfe86c3918f Mon Sep 17 00:00:00 2001 From: Mauro Mugnaini Date: Mon, 16 Nov 2020 23:32:11 +0100 Subject: [PATCH] Changed auth code --- .../avatar/AbstractAvatarResource.java | 27 ++++++ .../keycloak/avatar/AvatarAdminResource.java | 96 ++----------------- .../gcube/keycloak/avatar/AvatarResource.java | 24 +---- 3 files changed, 35 insertions(+), 112 deletions(-) diff --git a/avatar-realm-resource/src/main/java/org/gcube/keycloak/avatar/AbstractAvatarResource.java b/avatar-realm-resource/src/main/java/org/gcube/keycloak/avatar/AbstractAvatarResource.java index b9c0082..bc1cf2c 100644 --- a/avatar-realm-resource/src/main/java/org/gcube/keycloak/avatar/AbstractAvatarResource.java +++ b/avatar-realm-resource/src/main/java/org/gcube/keycloak/avatar/AbstractAvatarResource.java @@ -2,6 +2,8 @@ package org.gcube.keycloak.avatar; import java.io.InputStream; +import javax.ws.rs.NotFoundException; +import javax.ws.rs.core.Response; import javax.ws.rs.core.StreamingOutput; import org.apache.commons.io.IOUtils; @@ -11,6 +13,9 @@ import org.jboss.logging.Logger; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.UserModel; +import org.keycloak.services.managers.AppAuthManager; +import org.keycloak.services.managers.AuthenticationManager; +import org.keycloak.services.managers.AuthenticationManager.AuthResult; public abstract class AbstractAvatarResource { @@ -21,9 +26,22 @@ public abstract class AbstractAvatarResource { public static final Class DEFAULT_IMPLEMENTATION = FileAvatarStorageProvider.class; protected KeycloakSession session; + protected AuthenticationManager.AuthResult auth; public AbstractAvatarResource(KeycloakSession session) { this.session = session; + auth = authenticate(session); + } + + private AuthResult authenticate(KeycloakSession session) { + logger.debug("Authenticating with bearer token"); + AuthResult auth = new AppAuthManager().authenticateBearerToken(session); + + if (auth == null) { + logger.debug("Authenticating with identity cookie"); + auth = new AppAuthManager().authenticateIdentityCookie(session, session.getContext().getRealm()); + } + return auth; } public AvatarStorageProvider getAvatarStorageProvider() { @@ -55,4 +73,13 @@ public abstract class AbstractAvatarResource { return is != null ? output -> IOUtils.copy(is, output) : null; } + + protected Response fetchAndCreateResponse(RealmModel realm, UserModel user) { + StreamingOutput so = fetchUserImage(realm, user); + if (so == null) { + throw new NotFoundException("Avatar image not found"); + } + return Response.ok(so).build(); + } + } diff --git a/avatar-realm-resource/src/main/java/org/gcube/keycloak/avatar/AvatarAdminResource.java b/avatar-realm-resource/src/main/java/org/gcube/keycloak/avatar/AvatarAdminResource.java index 0277caf..0a6f8e2 100644 --- a/avatar-realm-resource/src/main/java/org/gcube/keycloak/avatar/AvatarAdminResource.java +++ b/avatar-realm-resource/src/main/java/org/gcube/keycloak/avatar/AvatarAdminResource.java @@ -6,7 +6,6 @@ import javax.ws.rs.Consumes; import javax.ws.rs.ForbiddenException; import javax.ws.rs.GET; import javax.ws.rs.NotAuthorizedException; -import javax.ws.rs.NotFoundException; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; @@ -14,66 +13,34 @@ import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; import org.gcube.keycloak.avatar.storage.AvatarStorageProvider; import org.jboss.resteasy.annotations.cache.NoCache; import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput; 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.models.UserModel; -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.permissions.AdminPermissionEvaluator; -import org.keycloak.services.resources.admin.permissions.AdminPermissions; public class AvatarAdminResource extends AbstractAvatarResource { - private AdminPermissionEvaluator realmAuth; - @Context private AvatarStorageProvider avatarStorageProvider; - private AppAuthManager authManager; -// private TokenManager tokenManager; - @Context private HttpHeaders httpHeaders; @Context private ClientConnection clientConnection; - private AdminAuth auth; - public AvatarAdminResource(KeycloakSession session) { super(session); - authManager = new AppAuthManager(); // tokenManager = new TokenManager(); } public void init() { - RealmModel realm = session.getContext().getRealm(); - - auth = authenticateRealmAdminRequest(); - - RealmManager realmManager = new RealmManager(session); - if (realm == null) - throw new NotFoundException("Realm not found"); - - if (!auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm()) && !auth.getRealm().equals(realm)) { - throw new org.keycloak.services.ForbiddenException(); - } - realmAuth = AdminPermissions.evaluator(session, realm, auth); - - session.getContext().setRealm(realm); + checkRealmAdmin(); } @GET @@ -81,10 +48,8 @@ public class AvatarAdminResource extends AbstractAvatarResource { @Produces({ "image/png", "image/jpeg", "image/gif" }) public Response downloadUserAvatarImage(@PathParam("user_id") String userId) { try { - canViewUsers(); UserModel user = session.users().getUserById(userId, session.getContext().getRealm()); - return Response.ok(fetchUserImage(session.getContext().getRealm(), user)).build(); - + return fetchAndCreateResponse(session.getContext().getRealm(), user); } catch (ForbiddenException e) { return Response.status(Response.Status.FORBIDDEN).entity(e.getMessage()).build(); } catch (Exception e) { @@ -102,7 +67,6 @@ public class AvatarAdminResource extends AbstractAvatarResource { if (auth == null) { return Response.status(Response.Status.UNAUTHORIZED).build(); } - canManageUsers(); RealmModel realm = session.getContext().getRealm(); UserModel user = session.users().getUserById(userId, session.getContext().getRealm()); @@ -119,59 +83,13 @@ public class AvatarAdminResource extends AbstractAvatarResource { return Response.ok().build(); } - protected AdminAuth authenticateRealmAdminRequest() { - String tokenString = authManager.extractAuthorizationHeaderToken(httpHeaders); - MultivaluedMap queryParameters = session.getContext().getUri().getQueryParameters(); - if (tokenString == null && queryParameters.containsKey("access_token")) { - tokenString = queryParameters.getFirst("access_token"); - } - if (tokenString == null) { + private void checkRealmAdmin() { + if (auth == 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 = authManager.authenticateBearerToken(tokenString, session, realm, - session.getContext().getUri(), clientConnection, httpHeaders); + } else if (auth.getToken().getRealmAccess() == null + || !auth.getToken().getRealmAccess().isUserInRole("admin")) { - if (authResult == null) { - logger.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); - } - - private void canViewUsers() { - if (!realmAuth.users().canView()) { - String message = "user does not have permission to view users"; - logger.info(message); - throw new ForbiddenException(message); - } - } - - private void canManageUsers() { - if (!realmAuth.users().canManage()) { - String message = "user does not have permission to manage users"; - logger.info(message); - throw new ForbiddenException(message); + throw new ForbiddenException("Does not have realm admin role"); } } } diff --git a/avatar-realm-resource/src/main/java/org/gcube/keycloak/avatar/AvatarResource.java b/avatar-realm-resource/src/main/java/org/gcube/keycloak/avatar/AvatarResource.java index e093011..0a238b1 100644 --- a/avatar-realm-resource/src/main/java/org/gcube/keycloak/avatar/AvatarResource.java +++ b/avatar-realm-resource/src/main/java/org/gcube/keycloak/avatar/AvatarResource.java @@ -7,23 +7,18 @@ import javax.ws.rs.Consumes; import javax.ws.rs.ForbiddenException; import javax.ws.rs.GET; import javax.ws.rs.NotAuthorizedException; -import javax.ws.rs.NotFoundException; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import javax.ws.rs.core.StreamingOutput; import javax.ws.rs.core.UriInfo; import org.jboss.resteasy.annotations.cache.NoCache; import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput; import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.keycloak.models.KeycloakSession; -import org.keycloak.services.managers.AppAuthManager; -import org.keycloak.services.managers.AuthenticationManager; -import org.keycloak.services.managers.AuthenticationManager.AuthResult; import org.keycloak.services.resources.RealmsResource; public class AvatarResource extends AbstractAvatarResource { @@ -31,21 +26,8 @@ public class AvatarResource extends AbstractAvatarResource { public static final String STATE_CHECKER_ATTRIBUTE = "state_checker"; public static final String STATE_CHECKER_PARAMETER = "stateChecker"; - private final AuthenticationManager.AuthResult auth; - public AvatarResource(KeycloakSession session) { super(session); - auth = authenticate(session); - } - - private AuthResult authenticate(KeycloakSession session) { - logger.debug("Authenticating with bearer token"); - AuthResult auth = new AppAuthManager().authenticateBearerToken(session, session.getContext().getRealm()); - if (auth == null) { - logger.debug("Authenticating with identity cookie"); - auth = new AppAuthManager().authenticateIdentityCookie(session, session.getContext().getRealm()); - } - return auth; } @Path("/admin") @@ -64,11 +46,7 @@ public class AvatarResource extends AbstractAvatarResource { throw new NotAuthorizedException("Bearer"); } logger.debugf("Getting avatar for user %s in realm %s", auth.getUser(), auth.getSession().getRealm()); - StreamingOutput so = fetchUserImage(auth.getSession().getRealm(), auth.getUser()); - if (so == null) { - throw new NotFoundException("Avatar image not found"); - } - return Response.ok(so).build(); + return fetchAndCreateResponse(auth.getSession().getRealm(), auth.getUser()); } @POST