diff --git a/backend/app/src/main/java/eu/viandeendirect/security/configuration/KeycloakJwtAuthenticationConverter.java b/backend/app/src/main/java/eu/viandeendirect/security/configuration/KeycloakJwtAuthenticationConverter.java index 06a2554..9f90910 100644 --- a/backend/app/src/main/java/eu/viandeendirect/security/configuration/KeycloakJwtAuthenticationConverter.java +++ b/backend/app/src/main/java/eu/viandeendirect/security/configuration/KeycloakJwtAuthenticationConverter.java @@ -19,34 +19,40 @@ public class KeycloakJwtAuthenticationConverter implements Converter { - private final String resourceId; - - public KeycloakJwtAuthenticationConverter(String resourceId) { - this.resourceId = resourceId; - } + public static final String CUSTOMER_FRONTEND_CLIENT_ID = "viandeendirect-customer-frontend"; + public static final String PRODUCER_FRONTEND_CLIENT_ID = "viandeendirect-producer-frontend"; @Override public AbstractAuthenticationToken convert(final Jwt source) { Collection authorities = Stream.concat( defaultGrantedAuthoritiesConverter.convert(source).stream(), - extractResourceRoles(source, resourceId).stream()) + extractResourceRoles(source).stream()) .collect(Collectors.toSet()); JwtAuthenticationToken jwtAuthenticationToken = new JwtAuthenticationToken(source, authorities); return jwtAuthenticationToken; } - private static Collection extractResourceRoles(final Jwt jwt, final String resourceId) { + private static Collection extractResourceRoles(final Jwt jwt) { Map resourceAccess = jwt.getClaim("resource_access"); - Map resource; + if (resourceAccess == null) { + return Collections.emptySet(); + } + Map customerResourceAccess = (Map) resourceAccess.get(CUSTOMER_FRONTEND_CLIENT_ID); + Map producerResourceAccess = (Map) resourceAccess.get(PRODUCER_FRONTEND_CLIENT_ID); Collection resourceRoles; - if (resourceAccess != null && (resource = (Map) resourceAccess.get(resourceId)) != null && - (resourceRoles = (Collection) resource.get("roles")) != null) - return resourceRoles.stream() - .map(resourceRole -> new SimpleGrantedAuthority("ROLE_" + resourceRole.toUpperCase())) - .collect(Collectors.toSet()); + if (producerResourceAccess != null && (resourceRoles = (Collection) producerResourceAccess.get("roles")) != null) + return getGrantedAuthorities(resourceRoles); + if (customerResourceAccess != null && (resourceRoles = (Collection) customerResourceAccess.get("roles")) != null) + return getGrantedAuthorities(resourceRoles); return Collections.emptySet(); } + private static Set getGrantedAuthorities(Collection resourceRoles) { + return resourceRoles.stream() + .map(resourceRole -> new SimpleGrantedAuthority("ROLE_" + resourceRole.toUpperCase())) + .collect(Collectors.toSet()); + } + private final JwtGrantedAuthoritiesConverter defaultGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter(); } \ No newline at end of file diff --git a/backend/app/src/main/java/eu/viandeendirect/security/configuration/SecurityConfiguration.java b/backend/app/src/main/java/eu/viandeendirect/security/configuration/SecurityConfiguration.java index bd5a391..0acf9ae 100644 --- a/backend/app/src/main/java/eu/viandeendirect/security/configuration/SecurityConfiguration.java +++ b/backend/app/src/main/java/eu/viandeendirect/security/configuration/SecurityConfiguration.java @@ -89,7 +89,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .logoutSuccessUrl("/"); http.oauth2ResourceServer() .jwt() - .jwtAuthenticationConverter(new KeycloakJwtAuthenticationConverter("viandeendirect-frontend")); + .jwtAuthenticationConverter(new KeycloakJwtAuthenticationConverter()); return http.build(); } } diff --git a/backend/app/src/main/resources/application.properties b/backend/app/src/main/resources/application.properties index de3607e..d9ace33 100644 --- a/backend/app/src/main/resources/application.properties +++ b/backend/app/src/main/resources/application.properties @@ -1,3 +1,4 @@ server.port=8080 spring.jackson.date-format=eu.viandeendirect.RFC3339DateFormat spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false +logging.level.org.springframework.security=TRACE diff --git a/frontend/.dockerignore b/frontend/.dockerignore new file mode 100644 index 0000000..4cfcb2f --- /dev/null +++ b/frontend/.dockerignore @@ -0,0 +1 @@ +app/public/* \ No newline at end of file diff --git a/frontend/app/public/config/keycloak.json b/frontend/app/public/config/keycloak.json index 5b28a99..1e2d63a 100644 --- a/frontend/app/public/config/keycloak.json +++ b/frontend/app/public/config/keycloak.json @@ -2,7 +2,7 @@ "realm": "viandeendirect", "auth-server-url": "http://localhost:8180/", "ssl-required": "external", - "resource": "viandeendirect-frontend", + "resource": "viandeendirect-producer-frontend", "public-client": true, "confidential-port": 0 } \ No newline at end of file diff --git a/frontend/app/src/api/ApiBuilder.ts b/frontend/app/src/api/ApiBuilder.ts index a7451e1..076a7d5 100644 --- a/frontend/app/src/api/ApiBuilder.ts +++ b/frontend/app/src/api/ApiBuilder.ts @@ -36,7 +36,9 @@ export class ApiBuilder { if(process.env.REACT_APP_MOCK_API) { return new MockApi() } else { - return new DefaultApi(ApiClient.instance) + let apiClient = ApiClient.instance + apiClient.basePath = await this.getBackendUrl() + return new DefaultApi(apiClient) } }