From 359048b34f39d4abc463aa9292f55031daaf65b5 Mon Sep 17 00:00:00 2001 From: Torsten Krohn Date: Fri, 1 Apr 2022 17:24:33 +0200 Subject: [PATCH] feat: implement web token creation --- .../api/authorization/AuthenticatedUser.java | 11 +++++++ .../api/controller/VideoController.java | 9 ++++-- .../video/VideoCallUrlGeneratorService.java | 14 +++++++++ .../video/jwt/TokenGeneratorService.java | 31 +++++++++++++++++-- .../config/AuthenticatedUserConfig.java | 3 ++ .../config/security/WebSecurityConfig.java | 2 ++ .../api/controller/VideoControllerIT.java | 4 +++ 7 files changed, 69 insertions(+), 5 deletions(-) diff --git a/src/main/java/de/caritas/cob/videoservice/api/authorization/AuthenticatedUser.java b/src/main/java/de/caritas/cob/videoservice/api/authorization/AuthenticatedUser.java index a799351..acb7aa9 100644 --- a/src/main/java/de/caritas/cob/videoservice/api/authorization/AuthenticatedUser.java +++ b/src/main/java/de/caritas/cob/videoservice/api/authorization/AuthenticatedUser.java @@ -1,5 +1,9 @@ package de.caritas.cob.videoservice.api.authorization; +import static java.util.Objects.nonNull; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import java.util.Set; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @@ -23,4 +27,11 @@ public class AuthenticatedUser { @NonNull private String accessToken; + + private Set roles; + + @JsonIgnore + public boolean isConsultant() { + return nonNull(roles) && roles.contains(Authority.CONSULTANT.name()); + } } diff --git a/src/main/java/de/caritas/cob/videoservice/api/controller/VideoController.java b/src/main/java/de/caritas/cob/videoservice/api/controller/VideoController.java index 8218933..4995085 100644 --- a/src/main/java/de/caritas/cob/videoservice/api/controller/VideoController.java +++ b/src/main/java/de/caritas/cob/videoservice/api/controller/VideoController.java @@ -6,9 +6,9 @@ import de.caritas.cob.videoservice.api.model.RejectVideoCallDTO; import de.caritas.cob.videoservice.api.model.VideoCallInfoDTO; import de.caritas.cob.videoservice.api.service.RejectVideoCallService; +import de.caritas.cob.videoservice.api.service.video.VideoCallUrlGeneratorService; import de.caritas.cob.videoservice.generated.api.controller.VideocallsApi; import io.swagger.annotations.Api; -import java.util.Optional; import javax.validation.Valid; import lombok.NonNull; import lombok.RequiredArgsConstructor; @@ -27,6 +27,7 @@ public class VideoController implements VideocallsApi { private final @NonNull StartVideoCallFacade startVideoCallFacade; private final @NonNull RejectVideoCallService rejectVideoCallService; + private final @NonNull VideoCallUrlGeneratorService videoCallUrlGeneratorService; /** * Starts a new video call. @@ -55,7 +56,9 @@ public ResponseEntity rejectVideoCall(@Valid RejectVideoCallDTO rejectVide } @Override - public ResponseEntity getWebToken(String rcUserId, String groupId) { - return ResponseEntity.of(Optional.empty()); + public ResponseEntity getWebToken(String rcUserId, String roomId) { + var videoCallInfo = videoCallUrlGeneratorService.generateJwt(roomId); + + return ResponseEntity.ok(videoCallInfo); } } diff --git a/src/main/java/de/caritas/cob/videoservice/api/service/video/VideoCallUrlGeneratorService.java b/src/main/java/de/caritas/cob/videoservice/api/service/video/VideoCallUrlGeneratorService.java index 175a7db..5c81e62 100644 --- a/src/main/java/de/caritas/cob/videoservice/api/service/video/VideoCallUrlGeneratorService.java +++ b/src/main/java/de/caritas/cob/videoservice/api/service/video/VideoCallUrlGeneratorService.java @@ -1,6 +1,7 @@ package de.caritas.cob.videoservice.api.service.video; import de.caritas.cob.videoservice.api.exception.httpresponse.InternalServerErrorException; +import de.caritas.cob.videoservice.api.model.VideoCallInfoDTO; import de.caritas.cob.videoservice.api.service.video.jwt.TokenGeneratorService; import de.caritas.cob.videoservice.api.service.video.jwt.model.VideoCallUrls; import java.net.MalformedURLException; @@ -57,4 +58,17 @@ private String buildUrl(String uuid, String token) { } } + /** + * Generate JWT. + * + * @param roomId room id + * @return VideoCallInfoDTO + */ + public VideoCallInfoDTO generateJwt(String roomId) { + var videoCallInfo = new VideoCallInfoDTO(); + videoCallInfo.setJwt(tokenGeneratorService.generateToken(roomId)); + videoCallInfo.setDomain(videoCallServerUrl); + + return videoCallInfo; + } } diff --git a/src/main/java/de/caritas/cob/videoservice/api/service/video/jwt/TokenGeneratorService.java b/src/main/java/de/caritas/cob/videoservice/api/service/video/jwt/TokenGeneratorService.java index 7849439..7238001 100644 --- a/src/main/java/de/caritas/cob/videoservice/api/service/video/jwt/TokenGeneratorService.java +++ b/src/main/java/de/caritas/cob/videoservice/api/service/video/jwt/TokenGeneratorService.java @@ -60,6 +60,18 @@ public void initAlgorithm() { this.algorithm = Algorithm.HMAC256(this.secret); } + /** + * Generate token. + * + * @param roomId room id + * @return token + */ + public String generateToken(String roomId) { + return authenticatedUser.isConsultant() + ? generateModeratorToken(roomId) + : generateNonModeratorToken(roomId); + } + /** * Generates the {@link VideoCallToken} for anonymous user and asker (containing user name). * @@ -69,12 +81,12 @@ public void initAlgorithm() { */ public VideoCallToken generateNonModeratorToken(String roomId, String askerName) { return VideoCallToken.builder() - .guestToken(buildGuestJwt(roomId)) + .guestToken(generateNonModeratorToken(roomId)) .userRelatedToken(buildUserRelatedJwt(roomId, askerName)) .build(); } - private String buildGuestJwt(String roomId) { + public String generateNonModeratorToken(String roomId) { return buildBasicJwt(roomId) .sign(algorithm); } @@ -128,6 +140,21 @@ public String generateModeratorToken(String roomId, String guestVideoCallUrl) { return buildModeratorJwt(roomId, guestVideoCallUrl); } + /** + * Generate moderator token. + * + * @param roomId room id + * @return token + */ + public String generateModeratorToken(String roomId) { + var userContext = createUserContext(authenticatedUser.getUsername()); + + return buildBasicJwt(roomId) + .withClaim(MODERATOR_CLAIM, true) + .withClaim(CONTEXT_CLAIM, userContext) + .sign(algorithm); + } + private String buildModeratorJwt(String roomId, String guestVideoCallUrl) { return buildBasicJwt(roomId) .withClaim(MODERATOR_CLAIM, true) diff --git a/src/main/java/de/caritas/cob/videoservice/config/AuthenticatedUserConfig.java b/src/main/java/de/caritas/cob/videoservice/config/AuthenticatedUserConfig.java index 957a01f..04102e8 100644 --- a/src/main/java/de/caritas/cob/videoservice/config/AuthenticatedUserConfig.java +++ b/src/main/java/de/caritas/cob/videoservice/config/AuthenticatedUserConfig.java @@ -43,6 +43,9 @@ public AuthenticatedUser getAuthenticatedUser() { authenticatedUser.setUserId(getUserAttribute(claimMap, CLAIM_NAME_USER_ID)); authenticatedUser.setUsername(getUserAttribute(claimMap, CLAIM_NAME_USERNAME)); + var roles = keycloakSecContext.getToken().getRealmAccess().getRoles(); + authenticatedUser.setRoles(roles); + return authenticatedUser; } diff --git a/src/main/java/de/caritas/cob/videoservice/config/security/WebSecurityConfig.java b/src/main/java/de/caritas/cob/videoservice/config/security/WebSecurityConfig.java index c6c9b74..bd4c7a5 100644 --- a/src/main/java/de/caritas/cob/videoservice/config/security/WebSecurityConfig.java +++ b/src/main/java/de/caritas/cob/videoservice/config/security/WebSecurityConfig.java @@ -64,6 +64,8 @@ protected void configure(HttpSecurity http) throws Exception { .hasAuthority(CONSULTANT.getAuthority()) .antMatchers("/videocalls/reject") .hasAnyAuthority(USER.getAuthority()) + .antMatchers("/videocalls/*/jwt") + .hasAnyAuthority(CONSULTANT.getAuthority()) //TODO: add anonymous .anyRequest().denyAll() .and() .exceptionHandling() diff --git a/src/test/java/de/caritas/cob/videoservice/api/controller/VideoControllerIT.java b/src/test/java/de/caritas/cob/videoservice/api/controller/VideoControllerIT.java index 8125422..cbcb3bb 100644 --- a/src/test/java/de/caritas/cob/videoservice/api/controller/VideoControllerIT.java +++ b/src/test/java/de/caritas/cob/videoservice/api/controller/VideoControllerIT.java @@ -21,6 +21,7 @@ import de.caritas.cob.videoservice.api.facade.StartVideoCallFacade; import de.caritas.cob.videoservice.api.model.RejectVideoCallDTO; import de.caritas.cob.videoservice.api.service.RejectVideoCallService; +import de.caritas.cob.videoservice.api.service.video.VideoCallUrlGeneratorService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -48,6 +49,9 @@ public class VideoControllerIT { @MockBean private RoleAuthorizationAuthorityMapper roleAuthorizationAuthorityMapper; + @MockBean + private VideoCallUrlGeneratorService videoCallUrlGeneratorService; + @Test public void createVideoCall_Should_ReturnCreated_When_EverythingSucceeded() throws Exception {