feat: interraction between the backend and keycloak
Some checks failed
CI / build (push) Failing after 9s

This commit is contained in:
Pierre Tellier
2025-02-11 10:00:11 +01:00
parent c32eea8a40
commit 249d00177c
7 changed files with 179 additions and 10 deletions

View File

@ -2,13 +2,13 @@ package enseirb.myinpulse.api;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.*;
import javax.management.relation.RoleNotFoundException;
import java.security.Principal;
@SpringBootApplication
@RestController
public class GetUserInfo {
@ -22,7 +22,8 @@ public class GetUserInfo {
@CrossOrigin(methods = {RequestMethod.GET, RequestMethod.OPTIONS})
@GetMapping("/random")
public boolean rand(){
public boolean rand(@RequestHeader("Authorization") String token) throws RoleNotFoundException {
System.err.println(token);
System.err.println("HELLO");
return Math.random() > 0.5;
}

View File

@ -0,0 +1,7 @@
package enseirb.myinpulse.exceptions;
public class RoleNotFoudException extends RuntimeException {
public RoleNotFoudException(String message) {
super(message);
}
}

View File

@ -0,0 +1,7 @@
package enseirb.myinpulse.exceptions;
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String message) {
super(message);
}
}

View File

@ -1,3 +1,7 @@
/*
* Source: https://github.com/ChristianHuff-DEV/secure-spring-rest-api-using-keycloak/blob/main/src/main/java/io/betweendata/RestApi/security/oauth2/KeycloakJwtRolesConverter.java
* edited by Pierre Tellier
*/
package enseirb.myinpulse.security;
import org.springframework.core.convert.converter.Converter;
@ -41,17 +45,16 @@ public class KeycloakJwtRolesConverter implements Converter<Jwt, AbstractAuthent
private static final String CLAIM_ROLES = "roles";
@Override
public AbstractAuthenticationToken convert(Jwt source)
{
public AbstractAuthenticationToken convert(Jwt source) {
return new JwtAuthenticationToken(source, Stream.concat(new JwtGrantedAuthoritiesConverter().convert(source)
.stream(), TEMPORARNAME(source).stream())
.stream(), tokenRolesExtractor(source).stream())
.collect(toSet()));
}
/**
* Extracts the realm and resource level roles from a JWT token distinguishing between them using prefixes.
*/
public Collection<GrantedAuthority> TEMPORARNAME(Jwt jwt) {
public Collection<GrantedAuthority> tokenRolesExtractor(Jwt jwt) {
// Collection that will hold the extracted roles
Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>();

View File

@ -0,0 +1,77 @@
package enseirb.myinpulse.utils;
import enseirb.myinpulse.exceptions.UserNotFoundException;
import org.springframework.web.client.RestClient;
import javax.management.relation.RoleNotFoundException;
import static org.springframework.http.MediaType.APPLICATION_JSON;
public class KeycloakApi {
static final String keycloakUrl = "http://localhost:7080";
static final String realmName = "test";
/**
* Uses Keycloak API to retrieve a role representation of a role by its name
* @param roleName name of the role
* @param bearer authorization header used by the client to authenticate to keycloak
*/
static public RoleRepresentation getRoleRepresentationByName(String roleName, String bearer) throws RoleNotFoundException {
RoleRepresentation[] response = RestClient.builder().baseUrl(keycloakUrl)
.defaultHeader("Authorization", bearer)
.build()
.get()
.uri("/admin/realms/{realmName}/roles/{roleName}", realmName, roleName)
.retrieve()
.body(RoleRepresentation[].class);
if (response == null || response.length == 0) {
throw new RoleNotFoundException("Role not found");
}
return response[0];
}
static public String getUserIdByName(String username, String bearer) throws UserNotFoundException {
UserRepresentation[] response = RestClient.builder().baseUrl(keycloakUrl)
.defaultHeader("Authorization", bearer)
.build()
.get()
.uri("/admin/realms/{realmName}/users?username={username}", realmName, username)
.retrieve()
.body(UserRepresentation[].class);
if (response == null || response.length == 0) {
throw new UserNotFoundException("User not found");
}
return response[0].id;
}
static public void setRoleToUser(String username, String roleName, String bearer) throws RoleNotFoundException, UserNotFoundException {
RoleRepresentation roleRepresentation = getRoleRepresentationByName(roleName, bearer);
String userId = getUserIdByName(username, bearer);
RestClient.builder().baseUrl(keycloakUrl)
.defaultHeader("Authorization", bearer)
.build()
.post()
.uri("/admin/realms/${realmName}/users/${userId}/role-mappings/realm", realmName, userId)
.body(roleRepresentation)
.contentType(APPLICATION_JSON)
.retrieve();
}
}
class RoleRepresentation {
public String id;
public String name;
public String description;
}
class UserRepresentation {
public String id;
public String name;
}