Compare commits

...

3 Commits

4 changed files with 33 additions and 14 deletions

View File

@ -35,7 +35,7 @@ import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.provider.ProviderConfigurationBuilder;
import org.keycloak.social.facebook.FacebookIdentityProviderFactory;
import org.keycloak.social.google.GoogleIdentityProviderFactory;
import org.keycloak.social.linkedin.LinkedInIdentityProviderFactory;
import org.keycloak.social.linkedin.LinkedInOIDCIdentityProviderFactory;
/**
* @author <a href="mailto:mauro.mugnaini@nubisware.com">Mauro Mugnaini</a>
@ -62,7 +62,7 @@ public class AvatarImporter extends AbstractClaimMapper {
public static final String[] PROVIDERS_WITH_SPECIFIC_CODE = {
FacebookIdentityProviderFactory.PROVIDER_ID,
LinkedInIdentityProviderFactory.PROVIDER_ID
LinkedInOIDCIdentityProviderFactory.PROVIDER_ID
};
public static final String[] COMPATIBLE_PROVIDERS = (String[]) ArrayUtils.addAll(PROVIDERS_WITH_PICTURE_CLAIM,
@ -169,7 +169,7 @@ public class AvatarImporter extends AbstractClaimMapper {
logger.info("Cannot load avatar image from claim: " + imageClaim, e);
}
}
} else if (LinkedInIdentityProviderFactory.PROVIDER_ID.equals(identityProviderAlias)) {
} else if (LinkedInOIDCIdentityProviderFactory.PROVIDER_ID.equals(identityProviderAlias)) {
avatarInputStream = loadAvatarFromLinkedIn(context);
} else if (FacebookIdentityProviderFactory.PROVIDER_ID.equals(identityProviderAlias)) {
avatarInputStream = loadAvatarFromFacebook(context);
@ -217,6 +217,14 @@ public class AvatarImporter extends AbstractClaimMapper {
"https://api.linkedin.com/v2/me?projection=(profilePicture(displayImage~:playableStreams))&oauth2_access_token="
+ getAccessTokenString(context)).openStream())));
// If the token cannot be passed anymore via parameter, try use this
// URLConnection urlConnection = new URL(
// "https://api.linkedin.com/v2/me?projection=(profilePicture(displayImage~:playableStreams))")
// .openConnection();
// urlConnection.addRequestProperty("Authorization ", "Bearer " + getAccessTokenString(context));
// JSONObject displayImageProjection = (JSONObject) new JSONParser()
// .parse(new InputStreamReader(urlConnection.getInputStream()));
String imageURL = null;
@SuppressWarnings("unchecked")

View File

@ -7,6 +7,7 @@ import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.reactive.RestForm;
import org.jboss.resteasy.reactive.multipart.FileUpload;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.common.util.Resteasy;
import org.keycloak.http.HttpRequest;
import org.keycloak.models.KeycloakSession;
import org.keycloak.services.cors.Cors;
@ -19,7 +20,6 @@ import jakarta.ws.rs.OPTIONS;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.UriBuilder;
@ -43,8 +43,10 @@ public class AvatarResource extends AbstractAvatarResource {
}
@OPTIONS
public Response handleCorsPreflight(@Context final HttpRequest request) {
logger.info("Received CORS preflight request for ext/user; request is " + request);
public Response handleCorsPreflight() {
logger.info("Received CORS preflight request for ext/user");
KeycloakSession session = Resteasy.getContextData(KeycloakSession.class);
HttpRequest request = session.getContext().getHttpRequest();
return Cors.add(request, Response.ok())
.preflight()
.allowAllOrigins()
@ -56,12 +58,14 @@ public class AvatarResource extends AbstractAvatarResource {
@GET
@Produces({ "image/png", "image/jpeg", "image/gif" })
public Response downloadCurrentUserAvatarImage(@Context final HttpRequest request) {
public Response downloadCurrentUserAvatarImage() {
if (auth == null) {
logger.debug("Unhautorized call to get avatar");
throw new NotAuthorizedException("Bearer");
}
logger.debugf("Getting avatar for user %s in realm %s", auth.getUser(), auth.getSession().getRealm());
KeycloakSession session = Resteasy.getContextData(KeycloakSession.class);
HttpRequest request = session.getContext().getHttpRequest();
return Cors
.add(request,
Response.fromResponse(fetchAndCreateResponse(auth.getSession().getRealm(), auth.getUser())))
@ -75,7 +79,7 @@ public class AvatarResource extends AbstractAvatarResource {
@POST
@NoCache
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadCurrentUserAvatarImage(@RestForm(AVATAR_IMAGE_PARAMETER) FileUpload image, @Context UriInfo uriInfo) {
public Response uploadCurrentUserAvatarImage(@RestForm(AVATAR_IMAGE_PARAMETER) FileUpload image) {
if (auth == null) {
throw new NotAuthorizedException("Bearer");
}
@ -85,6 +89,8 @@ public class AvatarResource extends AbstractAvatarResource {
// }
logger.debugf("Uploading new avatar for user %s in realm %s", auth.getUser(), auth.getSession().getRealm());
KeycloakSession session = Resteasy.getContextData(KeycloakSession.class);
UriInfo uriInfo = session.getContext().getUri();
Response response = null;
try {
saveUserImage(auth.getSession().getRealm(), auth.getUser(), Files.newInputStream(image.uploadedFile()));

View File

@ -20,7 +20,9 @@ public class MinioAvatarStorageTest {
private static final String ENDPOINT_URL = "https://isti-cloud.isti.cnr.it:13808";
private static final String ACCESS_KEY_ENV = "ACCESS_KEY";
private static final String SECRET_KEY_ENV = "SECRET_KEY";
private static final String BUCKET = "keycloak";
private static final String BUCKET = "keycloak-data-dev";
private static final boolean ALSO_DELETE_OBJECT = true;
@Test
public void test() throws FileNotFoundException {
@ -34,17 +36,20 @@ public class MinioAvatarStorageTest {
MinioAvatarStorageProvider minioAvatarStorageProvider = new MinioAvatarStorageProvider(minioConfig);
RealmModel realmModel = Mockito.mock(RealmModel.class);
when(realmModel.getName()).thenReturn("testRealm");
when(realmModel.getName()).thenReturn("d4science");
UserModel userModel = Mockito.mock(UserModel.class);
when(userModel.getUsername()).thenReturn("test.user");
minioAvatarStorageProvider.saveAvatarImage(realmModel, userModel,
this.getClass().getClassLoader().getResourceAsStream("tm-avatar.png"));
assertNotNull(minioAvatarStorageProvider.loadAvatarImage(realmModel, userModel));
minioAvatarStorageProvider.deleteAvatarImage(realmModel, userModel);
assertNull(minioAvatarStorageProvider.loadAvatarImage(realmModel, userModel));
// Delete of a non existing resource must not raise an exception, assuring it with a proper test
minioAvatarStorageProvider.deleteAvatarImage(realmModel, userModel);
if (ALSO_DELETE_OBJECT) {
minioAvatarStorageProvider.deleteAvatarImage(realmModel, userModel);
assertNull(minioAvatarStorageProvider.loadAvatarImage(realmModel, userModel));
// Delete of a non existing resource must not raise an exception, assuring it with a proper test
minioAvatarStorageProvider.deleteAvatarImage(realmModel, userModel);
}
}
}