diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/dto/ChannelDTO.java b/src/main/java/de/tum/cit/aet/artemis/communication/dto/ChannelDTO.java index 6e5738d3904a..6fd8d9c89fa2 100644 --- a/src/main/java/de/tum/cit/aet/artemis/communication/dto/ChannelDTO.java +++ b/src/main/java/de/tum/cit/aet/artemis/communication/dto/ChannelDTO.java @@ -197,6 +197,11 @@ else if (channel.getExam() != null) { } } + /** + * Converts the DTO to a channel entity + * + * @return the created channel entity based on the attributes in the DTO + */ public Channel toChannel() { Channel channel = new Channel(); channel.setName(this.name); diff --git a/src/main/java/de/tum/cit/aet/artemis/lti/config/Lti13LaunchFilter.java b/src/main/java/de/tum/cit/aet/artemis/lti/config/Lti13LaunchFilter.java index 6929eee2d537..65624c32a3e5 100644 --- a/src/main/java/de/tum/cit/aet/artemis/lti/config/Lti13LaunchFilter.java +++ b/src/main/java/de/tum/cit/aet/artemis/lti/config/Lti13LaunchFilter.java @@ -26,7 +26,7 @@ import de.tum.cit.aet.artemis.core.exception.LtiEmailAlreadyInUseException; import de.tum.cit.aet.artemis.core.security.SecurityUtils; import de.tum.cit.aet.artemis.lti.dto.Claims; -import de.tum.cit.aet.artemis.lti.dto.LtiAuthenticationResponse; +import de.tum.cit.aet.artemis.lti.dto.Lti13AuthenticationResponse; import de.tum.cit.aet.artemis.lti.service.Lti13Service; import uk.ac.ox.ctl.lti13.security.oauth2.client.lti.authentication.OidcAuthenticationToken; import uk.ac.ox.ctl.lti13.security.oauth2.client.lti.web.OAuth2LoginAuthenticationFilter; @@ -125,7 +125,7 @@ private void writeResponse(String targetLinkUri, OidcIdToken ltiIdToken, String log.info("User is authenticated, building LTI response"); lti13Service.buildLtiResponse(uriBuilder, response); } - LtiAuthenticationResponse jsonResponse = new LtiAuthenticationResponse(uriBuilder.build().toUriString(), ltiIdToken.getTokenValue(), clientRegistrationId); + Lti13AuthenticationResponse jsonResponse = new Lti13AuthenticationResponse(uriBuilder.build().toUriString(), ltiIdToken.getTokenValue(), clientRegistrationId); response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); diff --git a/src/main/java/de/tum/cit/aet/artemis/lti/dto/Claims.java b/src/main/java/de/tum/cit/aet/artemis/lti/dto/Claims.java index 41659ae1210b..38a1b7a24bba 100644 --- a/src/main/java/de/tum/cit/aet/artemis/lti/dto/Claims.java +++ b/src/main/java/de/tum/cit/aet/artemis/lti/dto/Claims.java @@ -1,6 +1,6 @@ package de.tum.cit.aet.artemis.lti.dto; -public class Claims extends uk.ac.ox.ctl.lti13.lti.Claims { +public final class Claims extends uk.ac.ox.ctl.lti13.lti.Claims { /** * Constant for LTI Assignment and Grade Services (AGS) claim endpoint. diff --git a/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13AgsClaim.java b/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13AgsClaim.java index c3ba3dab86d0..0b417baa473e 100644 --- a/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13AgsClaim.java +++ b/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13AgsClaim.java @@ -6,12 +6,14 @@ import org.springframework.security.oauth2.core.oidc.OidcIdToken; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; /** * A wrapper record for an LTI 1.3 Assignment and Grading Services Claim. We support the Score Publishing Service in order to transmit scores. */ +@JsonInclude(JsonInclude.Include.NON_EMPTY) public record Lti13AgsClaim(List scope, String lineItem) { /** diff --git a/src/main/java/de/tum/cit/aet/artemis/lti/dto/LtiAuthenticationResponse.java b/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13AuthenticationResponse.java similarity index 58% rename from src/main/java/de/tum/cit/aet/artemis/lti/dto/LtiAuthenticationResponse.java rename to src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13AuthenticationResponse.java index 49470f2fdc5b..0a6de2a3c212 100644 --- a/src/main/java/de/tum/cit/aet/artemis/lti/dto/LtiAuthenticationResponse.java +++ b/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13AuthenticationResponse.java @@ -1,5 +1,7 @@ package de.tum.cit.aet.artemis.lti.dto; +import com.fasterxml.jackson.annotation.JsonInclude; + /** * Holds LTI authentication response details. * @@ -7,5 +9,6 @@ * @param ltiIdToken LTI service provided ID token. * @param clientRegistrationId Client's registration ID with LTI service. */ -public record LtiAuthenticationResponse(String targetLinkUri, String ltiIdToken, String clientRegistrationId) { +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public record Lti13AuthenticationResponse(String targetLinkUri, String ltiIdToken, String clientRegistrationId) { } diff --git a/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13ClientRegistration.java b/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13ClientRegistration.java index f61dc9af1367..ef651272c086 100644 --- a/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13ClientRegistration.java +++ b/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13ClientRegistration.java @@ -1,276 +1,20 @@ package de.tum.cit.aet.artemis.lti.dto; -import java.util.Arrays; import java.util.List; -import org.springframework.security.oauth2.core.AuthorizationGrantType; - +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import de.tum.cit.aet.artemis.lti.config.CustomLti13Configurer; - /** * Represents the client registration details for an LTI 1.3 integration. * This class encapsulates information required for LTI 1.3 client registration, * including response types, grant types, redirect URIs, and tool configuration. */ -public class Lti13ClientRegistration { - - @JsonProperty("client_id") - private String clientId; - - @JsonProperty("response_types") - private List responseTypes; - - @JsonProperty("grant_types") - private List grantTypes; - - @JsonProperty("initiate_login_uri") - private String initiateLoginUri; - - @JsonProperty("redirect_uris") - private List redirectUris; - - @JsonProperty("client_name") - private String clientName; - - @JsonProperty("jwks_uri") - private String jwksUri; - - @JsonProperty("logo_uri") - private String logoUri; - - @JsonProperty("token_endpoint_auth_method") - private String tokenEndpointAuthMethod; - - private String scope; - - @JsonProperty("https://purl.imsglobal.org/spec/lti-tool-configuration") - private Lti13ToolConfiguration lti13ToolConfiguration; - - /** - * Default constructor necessary for conversion. - */ - public Lti13ClientRegistration() { // Necessary for conversion - } - - /** - * Constructs a new Lti13ClientRegistration with specified server URL and client registration ID. - * Initializes various properties such as grant types, response types, and tool configurations. - * - * @param serverUrl The server URL for LTI configuration. - * @param clientRegistrationId The client registration ID for LTI configuration. - */ - public Lti13ClientRegistration(String serverUrl, String clientRegistrationId) { - this.setGrantTypes(Arrays.asList(AuthorizationGrantType.CLIENT_CREDENTIALS.getValue(), AuthorizationGrantType.AUTHORIZATION_CODE.getValue())); - this.setResponseTypes(List.of("id_token")); - this.setClientName("Artemis - " + serverUrl); - this.setTokenEndpointAuthMethod("private_key_jwt"); - this.setScope(String.join(" ", List.of(Scopes.AGS_SCORE, Scopes.AGS_RESULT))); - this.setRedirectUris(List.of(serverUrl + "/" + CustomLti13Configurer.LTI13_LOGIN_REDIRECT_PROXY_PATH)); - this.setInitiateLoginUri(serverUrl + "/" + CustomLti13Configurer.LTI13_LOGIN_INITIATION_PATH + "/" + clientRegistrationId); - this.setJwksUri(serverUrl + "/.well-known/jwks.json"); - this.setLogoUri(serverUrl + "/public/images/logo.png"); - - Lti13ToolConfiguration toolConfiguration = getLti13ToolConfiguration(serverUrl); - this.setLti13ToolConfiguration(toolConfiguration); - } - - private static Lti13ToolConfiguration getLti13ToolConfiguration(String serverUrl) { - Lti13ToolConfiguration toolConfiguration = new Lti13ToolConfiguration(); - - // Extracting the domain from the server URL - String[] urlParts = serverUrl.split("://"); - String domain = ""; - if (urlParts.length >= 1) { - domain = urlParts[1]; // Domain cannot include protocol - } - toolConfiguration.setDomain(domain); - toolConfiguration.setTargetLinkUri(serverUrl + "/courses"); - toolConfiguration.setDescription("Artemis: Interactive Learning with Individual Feedback"); - toolConfiguration.setClaims(Arrays.asList("iss", "email", "sub", "name", "given_name", "family_name")); - Message deepLinkingMessage = new Message(CustomLti13Configurer.LTI13_DEEPLINK_MESSAGE_REQUEST, serverUrl + "/" + CustomLti13Configurer.LTI13_DEEPLINK_REDIRECT_PATH); - toolConfiguration.setMessages(List.of(deepLinkingMessage)); - return toolConfiguration; - } - - public String getClientId() { - return clientId; - } - - public void setClientId(String clientId) { - this.clientId = clientId; - } - - public List getResponseTypes() { - return responseTypes; - } - - public void setResponseTypes(List responseTypes) { - this.responseTypes = responseTypes; - } - - public List getGrantTypes() { - return grantTypes; - } - - public void setGrantTypes(List grantTypes) { - this.grantTypes = grantTypes; - } - - public String getInitiateLoginUri() { - return initiateLoginUri; - } - - public void setInitiateLoginUri(String initiateLoginUri) { - this.initiateLoginUri = initiateLoginUri; - } - - public List getRedirectUris() { - return redirectUris; - } - - public void setRedirectUris(List redirectUris) { - this.redirectUris = redirectUris; - } - - public String getClientName() { - return clientName; - } - - public void setClientName(String clientName) { - this.clientName = clientName; - } - - public String getJwksUri() { - return jwksUri; - } - - public void setJwksUri(String jwksUri) { - this.jwksUri = jwksUri; - } - - public String getLogoUri() { - return logoUri; - } - - public void setLogoUri(String logoUri) { - this.logoUri = logoUri; - } - - public String getTokenEndpointAuthMethod() { - return tokenEndpointAuthMethod; - } - - public void setTokenEndpointAuthMethod(String tokenEndpointAuthMethod) { - this.tokenEndpointAuthMethod = tokenEndpointAuthMethod; - } - - public String getScope() { - return scope; - } - - public void setScope(String scope) { - this.scope = scope; - } - - public Lti13ToolConfiguration getLti13ToolConfiguration() { - return lti13ToolConfiguration; - } - - public void setLti13ToolConfiguration(Lti13ToolConfiguration lti13ToolConfiguration) { - this.lti13ToolConfiguration = lti13ToolConfiguration; - } - - /** - * Inner class representing the LTI 1.3 tool configuration. - */ - public static class Lti13ToolConfiguration { - - private String domain; - - @JsonProperty("target_link_uri") - private String targetLinkUri; - - private String description; - - private List messages; - - private List claims; - - public String getDomain() { - return domain; - } - - public void setDomain(String domain) { - this.domain = domain; - } - - public String getTargetLinkUri() { - return targetLinkUri; - } - - public void setTargetLinkUri(String targetLinkUri) { - this.targetLinkUri = targetLinkUri; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public List getMessages() { - return messages; - } - - public void setMessages(List messages) { - this.messages = messages; - } - - public List getClaims() { - return claims; - } - - public void setClaims(List claims) { - this.claims = claims; - } - } - - /** - * Inner class representing a message in LTI 1.3 tool configuration. - */ - public static class Message { - - private String type; - - @JsonProperty("target_link_uri") - private String targetLinkUri; - - public Message() {// Necessary for conversion - } - - public Message(String type, String targetLinkUri) { - this.type = type; - this.targetLinkUri = targetLinkUri; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getTargetLinkUri() { - return targetLinkUri; - } +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public record Lti13ClientRegistration(@JsonProperty("client_id") String clientId, @JsonProperty("response_types") List responseTypes, + @JsonProperty("grant_types") List grantTypes, @JsonProperty("initiate_login_uri") String initiateLoginUri, @JsonProperty("redirect_uris") List redirectUris, + @JsonProperty("client_name") String clientName, @JsonProperty("jwks_uri") String jwksUri, @JsonProperty("logo_uri") String logoUri, + @JsonProperty("token_endpoint_auth_method") String tokenEndpointAuthMethod, String scope, + @JsonProperty("https://purl.imsglobal.org/spec/lti-tool-configuration") Lti13ToolConfiguration lti13ToolConfiguration) { - public void setTargetLinkUri(String targetLinkUri) { - this.targetLinkUri = targetLinkUri; - } - } } diff --git a/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13ClientRegistrationFactory.java b/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13ClientRegistrationFactory.java new file mode 100644 index 000000000000..e7ffd354871e --- /dev/null +++ b/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13ClientRegistrationFactory.java @@ -0,0 +1,48 @@ +package de.tum.cit.aet.artemis.lti.dto; + +import java.util.Arrays; +import java.util.List; + +import org.springframework.security.oauth2.core.AuthorizationGrantType; + +import de.tum.cit.aet.artemis.lti.config.CustomLti13Configurer; +import uk.ac.ox.ctl.lti13.security.oauth2.client.lti.web.LTIAuthorizationGrantType; + +public class Lti13ClientRegistrationFactory { + + /** + * Constructs a new Lti13ClientRegistration with specified server URL and client registration ID. + * Initializes various properties such as grant types, response types, and tool configurations. + * + * @param serverUrl The server URL for LTI configuration. + * @param clientRegistrationId The client registration ID for LTI configuration. + * @return A new Lti13ClientRegistration object with certain default values for Artemis + */ + public static Lti13ClientRegistration createRegistration(String serverUrl, String clientRegistrationId) { + var grantTypes = Arrays.asList(AuthorizationGrantType.CLIENT_CREDENTIALS.getValue(), LTIAuthorizationGrantType.IMPLICIT.getValue()); + var responseTypes = List.of("id_token"); + var clientName = "Artemis - " + serverUrl; + var tokenEndpointAuthMethod = "private_key_jwt"; + var scope = String.join(" ", List.of(Scopes.AGS_SCORE, Scopes.AGS_RESULT)); + var redirectUris = List.of(serverUrl + "/" + CustomLti13Configurer.LTI13_LOGIN_REDIRECT_PROXY_PATH); + var initiateLoginUri = serverUrl + "/" + CustomLti13Configurer.LTI13_LOGIN_INITIATION_PATH + "/" + clientRegistrationId; + var jwksUri = serverUrl + "/.well-known/jwks.json"; + var logoUri = serverUrl + "/public/images/logo.png"; + + return new Lti13ClientRegistration(clientRegistrationId, responseTypes, grantTypes, initiateLoginUri, redirectUris, clientName, jwksUri, logoUri, tokenEndpointAuthMethod, + scope, createLti13ToolConfiguration(serverUrl)); + } + + private static Lti13ToolConfiguration createLti13ToolConfiguration(String serverUrl) { + + // Extracting the domain from the server URL + String[] urlParts = serverUrl.split("://"); + String domain = ""; + if (urlParts.length >= 1) { + domain = urlParts[1]; // Domain cannot include protocol + } + var claims = Arrays.asList("iss", "email", "sub", "name", "given_name", "family_name"); + var deepLinkingMessage = new Lti13Message(CustomLti13Configurer.LTI13_DEEPLINK_MESSAGE_REQUEST, serverUrl + "/" + CustomLti13Configurer.LTI13_DEEPLINK_REDIRECT_PATH); + return new Lti13ToolConfiguration(domain, serverUrl + "/courses", "Artemis: Interactive Learning with Individual Feedback", List.of(deepLinkingMessage), claims); + } +} diff --git a/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13DeepLinkingResponse.java b/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13DeepLinkingResponse.java index 8d9986d433c0..e622dee0ca5a 100644 --- a/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13DeepLinkingResponse.java +++ b/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13DeepLinkingResponse.java @@ -7,6 +7,7 @@ import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames; import org.springframework.security.oauth2.core.oidc.OidcIdToken; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -34,6 +35,7 @@ * @param clientRegistrationId The client registration ID. * @param returnUrl The URL to return to after deep linking is completed. */ +@JsonInclude(JsonInclude.Include.NON_EMPTY) public record Lti13DeepLinkingResponse(@JsonProperty(IdTokenClaimNames.AUD) String aud, @JsonProperty(IdTokenClaimNames.ISS) String iss, @JsonProperty(IdTokenClaimNames.EXP) String exp, @JsonProperty(IdTokenClaimNames.IAT) String iat, @JsonProperty(IdTokenClaimNames.NONCE) String nonce, @JsonProperty(Claims.MSG) String message, @JsonProperty(Claims.LTI_DEPLOYMENT_ID) String deploymentId, @JsonProperty(Claims.MESSAGE_TYPE) String messageType, @@ -105,7 +107,6 @@ public Map getClaims() { claims.put(Claims.MESSAGE_TYPE, messageType()); claims.put(Claims.LTI_VERSION, ltiVersion()); claims.put(Claims.CONTENT_ITEMS, contentItems()); - return claims; } diff --git a/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13LaunchRequest.java b/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13LaunchRequest.java index 8576a7dff782..e33f0b62c007 100644 --- a/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13LaunchRequest.java +++ b/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13LaunchRequest.java @@ -4,6 +4,7 @@ import org.springframework.security.oauth2.core.oidc.OidcIdToken; import org.springframework.util.Assert; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -19,6 +20,7 @@ * @param agsClaim An optional {@link Lti13AgsClaim} representing the Assignment and Grade Services claim, if present. * @param clientRegistrationId The client registration ID, identifying the tool registration with the platform. */ +@JsonInclude(JsonInclude.Include.NON_EMPTY) public record Lti13LaunchRequest(String iss, String sub, String deploymentId, String resourceLinkId, String targetLinkUri, Lti13AgsClaim agsClaim, String clientRegistrationId) { /** diff --git a/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13Message.java b/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13Message.java new file mode 100644 index 000000000000..43eb826f353e --- /dev/null +++ b/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13Message.java @@ -0,0 +1,12 @@ +package de.tum.cit.aet.artemis.lti.dto; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Inner class representing a message in LTI 1.3 tool configuration. + */ +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public record Lti13Message(String type, @JsonProperty("target_link_uri") String targetLinkUri) { + +} diff --git a/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13PlatformConfiguration.java b/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13PlatformConfiguration.java index e1a54be22f60..23e0aa772dfa 100644 --- a/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13PlatformConfiguration.java +++ b/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13PlatformConfiguration.java @@ -1,5 +1,6 @@ package de.tum.cit.aet.artemis.lti.dto; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; /** @@ -11,6 +12,7 @@ * @param jwksUri The URI for the JSON Web Key Set (JWKS). * @param registrationEndpoint The endpoint URL for registration. */ +@JsonInclude(JsonInclude.Include.NON_EMPTY) public record Lti13PlatformConfiguration(@JsonProperty("issuer") String issuer, @JsonProperty("token_endpoint") String tokenEndpoint, @JsonProperty("authorization_endpoint") String authorizationEndpoint, @JsonProperty("jwks_uri") String jwksUri, @JsonProperty("registration_endpoint") String registrationEndpoint) { diff --git a/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13ToolConfiguration.java b/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13ToolConfiguration.java new file mode 100644 index 000000000000..99a4d8a907f3 --- /dev/null +++ b/src/main/java/de/tum/cit/aet/artemis/lti/dto/Lti13ToolConfiguration.java @@ -0,0 +1,14 @@ +package de.tum.cit.aet.artemis.lti.dto; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Inner class representing the LTI 1.3 tool configuration. + */ +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public record Lti13ToolConfiguration(String domain, @JsonProperty("target_link_uri") String targetLinkUri, String description, List messages, List claims) { + +} diff --git a/src/main/java/de/tum/cit/aet/artemis/lti/service/LtiDynamicRegistrationService.java b/src/main/java/de/tum/cit/aet/artemis/lti/service/LtiDynamicRegistrationService.java index bb4ba0abf16e..636877628224 100644 --- a/src/main/java/de/tum/cit/aet/artemis/lti/service/LtiDynamicRegistrationService.java +++ b/src/main/java/de/tum/cit/aet/artemis/lti/service/LtiDynamicRegistrationService.java @@ -20,6 +20,7 @@ import de.tum.cit.aet.artemis.core.exception.BadRequestAlertException; import de.tum.cit.aet.artemis.lti.domain.LtiPlatformConfiguration; import de.tum.cit.aet.artemis.lti.dto.Lti13ClientRegistration; +import de.tum.cit.aet.artemis.lti.dto.Lti13ClientRegistrationFactory; import de.tum.cit.aet.artemis.lti.dto.Lti13PlatformConfiguration; import de.tum.cit.aet.artemis.lti.repository.LtiPlatformConfigurationRepository; @@ -62,8 +63,7 @@ public void performDynamicRegistration(String openIdConfigurationUrl, String reg throw new BadRequestAlertException("Invalid platform configuration", "LTI", "invalidPlatformConfiguration"); } - Lti13ClientRegistration clientRegistrationResponse = postClientRegistrationToPlatform(platformConfiguration.registrationEndpoint(), clientRegistrationId, - registrationToken); + var clientRegistrationResponse = postClientRegistrationToPlatform(platformConfiguration.registrationEndpoint(), clientRegistrationId, registrationToken); LtiPlatformConfiguration ltiPlatformConfiguration = updateLtiPlatformConfiguration(clientRegistrationId, platformConfiguration, clientRegistrationResponse); ltiPlatformConfigurationRepository.save(ltiPlatformConfiguration); @@ -100,7 +100,7 @@ private Lti13ClientRegistration postClientRegistrationToPlatform(String registra headers.setBearerAuth(registrationToken); } - Lti13ClientRegistration lti13ClientRegistration = new Lti13ClientRegistration(artemisServerUrl, clientRegistrationId); + Lti13ClientRegistration lti13ClientRegistration = Lti13ClientRegistrationFactory.createRegistration(artemisServerUrl, clientRegistrationId); Lti13ClientRegistration registrationResponse = null; try { ResponseEntity response = restTemplate.postForEntity(registrationEndpoint, new HttpEntity<>(lti13ClientRegistration, headers), @@ -123,7 +123,7 @@ private LtiPlatformConfiguration updateLtiPlatformConfiguration(String registrat Lti13ClientRegistration clientRegistrationResponse) { LtiPlatformConfiguration ltiPlatformConfiguration = new LtiPlatformConfiguration(); ltiPlatformConfiguration.setRegistrationId(registrationId); - ltiPlatformConfiguration.setClientId(clientRegistrationResponse.getClientId()); + ltiPlatformConfiguration.setClientId(clientRegistrationResponse.clientId()); ltiPlatformConfiguration.setAuthorizationUri(platformConfiguration.authorizationEndpoint()); ltiPlatformConfiguration.setJwkSetUri(platformConfiguration.jwksUri()); ltiPlatformConfiguration.setTokenUri(platformConfiguration.tokenEndpoint()); diff --git a/src/main/java/de/tum/cit/aet/artemis/lti/service/OnlineCourseConfigurationService.java b/src/main/java/de/tum/cit/aet/artemis/lti/service/OnlineCourseConfigurationService.java index ffbf6db62f82..e70a464b8900 100644 --- a/src/main/java/de/tum/cit/aet/artemis/lti/service/OnlineCourseConfigurationService.java +++ b/src/main/java/de/tum/cit/aet/artemis/lti/service/OnlineCourseConfigurationService.java @@ -15,7 +15,6 @@ import org.springframework.context.annotation.Profile; import org.springframework.security.oauth2.client.registration.ClientRegistration; import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; -import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.stereotype.Service; import de.tum.cit.aet.artemis.core.domain.Course; @@ -24,6 +23,7 @@ import de.tum.cit.aet.artemis.lti.domain.LtiPlatformConfiguration; import de.tum.cit.aet.artemis.lti.domain.OnlineCourseConfiguration; import de.tum.cit.aet.artemis.lti.repository.LtiPlatformConfigurationRepository; +import uk.ac.ox.ctl.lti13.security.oauth2.client.lti.web.LTIAuthorizationGrantType; /** * Service Implementation for OnlineCourseConfiguration. @@ -104,7 +104,7 @@ public ClientRegistration getClientRegistration(LtiPlatformConfiguration ltiPlat .tokenUri(ltiPlatformConfiguration.getTokenUri()) // .redirectUri(artemisServerUrl + "/" + CustomLti13Configurer.LTI13_LOGIN_REDIRECT_PROXY_PATH) // .scope("openid") // - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) // + .authorizationGrantType(LTIAuthorizationGrantType.IMPLICIT) // .build(); } catch (IllegalArgumentException e) { diff --git a/src/test/java/de/tum/cit/aet/artemis/core/security/Lti13LaunchFilterTest.java b/src/test/java/de/tum/cit/aet/artemis/core/security/lti/Lti13LaunchFilterTest.java similarity index 98% rename from src/test/java/de/tum/cit/aet/artemis/core/security/Lti13LaunchFilterTest.java rename to src/test/java/de/tum/cit/aet/artemis/core/security/lti/Lti13LaunchFilterTest.java index 4bc65daa9a32..0d2de6aef218 100644 --- a/src/test/java/de/tum/cit/aet/artemis/core/security/Lti13LaunchFilterTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/core/security/lti/Lti13LaunchFilterTest.java @@ -1,4 +1,4 @@ -package de.tum.cit.aet.artemis.core.security; +package de.tum.cit.aet.artemis.core.security.lti; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.any; @@ -230,7 +230,7 @@ void emailAddressAlreadyInUseServiceLaunchFailed() throws IOException, ServletEx verify(httpResponse).setStatus(HttpStatus.UNAUTHORIZED.value()); assertThat((responseJsonBody.get("targetLinkUri").toString())).as("Response body contains the expected targetLinkUri") .contains("https://any-artemis-domain.org/course/123/exercise/1234"); - assertThat(responseJsonBody.get("ltiIdToken").isNull()).isTrue(); + assertThat(responseJsonBody.get("ltiIdToken")).isNull(); assertThat((responseJsonBody.get("clientRegistrationId").toString())).as("Response body contains the expected clientRegistrationId").contains("some-registration"); } @@ -247,7 +247,7 @@ void emailAddressAlreadyInUseServiceDeepLinkingFailed() throws ServletException, verify(httpResponse).setStatus(HttpStatus.UNAUTHORIZED.value()); assertThat((responseJsonBody.get("targetLinkUri").toString())).as("Response body contains the expected targetLinkUri").contains("/lti/select-course"); - assertThat(responseJsonBody.get("ltiIdToken").isNull()).isTrue(); + assertThat(responseJsonBody.get("ltiIdToken")).isNull(); assertThat((responseJsonBody.get("clientRegistrationId").toString())).as("Response body contains the expected clientRegistrationId").contains("some-registration"); } diff --git a/src/test/java/de/tum/cit/aet/artemis/core/security/lti/Lti13TokenRetrieverTest.java b/src/test/java/de/tum/cit/aet/artemis/core/security/lti/Lti13TokenRetrieverTest.java index 764824a74fe1..02eb2e3fa4f8 100644 --- a/src/test/java/de/tum/cit/aet/artemis/core/security/lti/Lti13TokenRetrieverTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/core/security/lti/Lti13TokenRetrieverTest.java @@ -32,7 +32,6 @@ import org.springframework.security.crypto.keygen.Base64StringKeyGenerator; import org.springframework.security.crypto.keygen.StringKeyGenerator; import org.springframework.security.oauth2.client.registration.ClientRegistration; -import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; @@ -50,6 +49,7 @@ import de.tum.cit.aet.artemis.lti.config.Lti13TokenRetriever; import de.tum.cit.aet.artemis.lti.dto.Scopes; import de.tum.cit.aet.artemis.lti.service.OAuth2JWKSService; +import uk.ac.ox.ctl.lti13.security.oauth2.client.lti.web.LTIAuthorizationGrantType; class Lti13TokenRetrieverTest { @@ -72,7 +72,7 @@ void init() { lti13TokenRetriever = new Lti13TokenRetriever(oAuth2JWKSService, restTemplate); clientRegistration = ClientRegistration.withRegistrationId("regId") // - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) // + .authorizationGrantType(LTIAuthorizationGrantType.IMPLICIT) // .redirectUri("redirectUri") // .authorizationUri("authUri") // .tokenUri("tokenUri").clientId("clientId") // diff --git a/src/test/java/de/tum/cit/aet/artemis/lti/LtiDynamicRegistrationServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/lti/LtiDynamicRegistrationServiceTest.java index 036a4034325d..fb348724ce61 100644 --- a/src/test/java/de/tum/cit/aet/artemis/lti/LtiDynamicRegistrationServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/lti/LtiDynamicRegistrationServiceTest.java @@ -8,6 +8,8 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.util.UUID; + import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -23,6 +25,7 @@ import de.tum.cit.aet.artemis.core.exception.BadRequestAlertException; import de.tum.cit.aet.artemis.lti.domain.OnlineCourseConfiguration; import de.tum.cit.aet.artemis.lti.dto.Lti13ClientRegistration; +import de.tum.cit.aet.artemis.lti.dto.Lti13ClientRegistrationFactory; import de.tum.cit.aet.artemis.lti.dto.Lti13PlatformConfiguration; import de.tum.cit.aet.artemis.lti.service.LtiDynamicRegistrationService; import de.tum.cit.aet.artemis.lti.service.OAuth2JWKSService; @@ -66,7 +69,7 @@ void init() { registrationToken = "token"; platformConfiguration = new Lti13PlatformConfiguration(null, "token", "auth", "jwks", "register"); - clientRegistrationResponse = new Lti13ClientRegistration(); + clientRegistrationResponse = Lti13ClientRegistrationFactory.createRegistration("http://artemis.com", "artemis-" + UUID.randomUUID()); } @AfterEach diff --git a/src/test/java/de/tum/cit/aet/artemis/lti/service/OnlineCourseConfigurationServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/lti/service/OnlineCourseConfigurationServiceTest.java index 28217ced4ec3..0ecb0491005f 100644 --- a/src/test/java/de/tum/cit/aet/artemis/lti/service/OnlineCourseConfigurationServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/lti/service/OnlineCourseConfigurationServiceTest.java @@ -16,13 +16,13 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.client.registration.ClientRegistration; -import org.springframework.security.oauth2.core.AuthorizationGrantType; import de.tum.cit.aet.artemis.core.exception.BadRequestAlertException; import de.tum.cit.aet.artemis.core.exception.EntityNotFoundException; import de.tum.cit.aet.artemis.lti.domain.LtiPlatformConfiguration; import de.tum.cit.aet.artemis.lti.domain.OnlineCourseConfiguration; import de.tum.cit.aet.artemis.lti.test_repository.LtiPlatformConfigurationTestRepository; +import uk.ac.ox.ctl.lti13.security.oauth2.client.lti.web.LTIAuthorizationGrantType; class OnlineCourseConfigurationServiceTest { @@ -65,7 +65,7 @@ void getClientRegistrationSuccess() { ClientRegistration clientRegistration = onlineCourseConfigurationService.getClientRegistration(ltiPlatformConfiguration); - assertThat(clientRegistration.getAuthorizationGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE); + assertThat(clientRegistration.getAuthorizationGrantType()).isEqualTo(LTIAuthorizationGrantType.IMPLICIT); assertThat(clientRegistration.getScopes()).hasSize(1).contains("openid"); assertThat(clientRegistration.getRegistrationId()).isEqualTo("reg"); assertThat(clientRegistration.getRedirectUri()).isEqualTo(artemisServerUrl + "/api/public/lti13/auth-callback");