added keycloak
This commit is contained in:
19
pom.xml
19
pom.xml
@@ -37,7 +37,24 @@
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.7.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package de.anxietyprime.swajodel.security;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
import org.springframework.security.oauth2.jwt.JwtClaimNames;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Component
|
||||
public class JwtConverter implements Converter<Jwt, AbstractAuthenticationToken> {
|
||||
|
||||
private final JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
|
||||
|
||||
private final JwtConverterProperties properties;
|
||||
|
||||
public JwtConverter(JwtConverterProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractAuthenticationToken convert(Jwt jwt) {
|
||||
Collection<GrantedAuthority> authorities = Stream.concat(
|
||||
jwtGrantedAuthoritiesConverter.convert(jwt).stream(),
|
||||
extractResourceRoles(jwt).stream()).collect(Collectors.toSet());
|
||||
return new JwtAuthenticationToken(jwt, authorities, getPrincipalClaimName(jwt));
|
||||
}
|
||||
|
||||
private String getPrincipalClaimName(Jwt jwt) {
|
||||
String claimName = JwtClaimNames.SUB;
|
||||
if (properties.getPrincipalAttribute() != null) {
|
||||
claimName = properties.getPrincipalAttribute();
|
||||
}
|
||||
return jwt.getClaim(claimName);
|
||||
}
|
||||
|
||||
private Collection<? extends GrantedAuthority> extractResourceRoles(Jwt jwt) {
|
||||
Map<String, Object> resourceAccess = jwt.getClaim("resource_access");
|
||||
Map<String, Object> resource;
|
||||
Collection<String> resourceRoles;
|
||||
|
||||
if (resourceAccess == null
|
||||
|| (resource = (Map<String, Object>) resourceAccess.get(properties.getResourceId())) == null
|
||||
|| (resourceRoles = (Collection<String>) resource.get("roles")) == null) {
|
||||
return Set.of();
|
||||
}
|
||||
return resourceRoles.stream()
|
||||
.map(role -> new SimpleGrantedAuthority("ROLE_" + role))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package de.anxietyprime.swajodel.security;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
@Data
|
||||
@Validated
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "jwt.auth.converter")
|
||||
|
||||
|
||||
public class JwtConverterProperties {
|
||||
|
||||
private String resourceId;
|
||||
private String principalAttribute;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package de.anxietyprime.swajodel.security;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class SecurityConfig {
|
||||
|
||||
public static final String ADMIN = "admin";
|
||||
public static final String USER = "user";
|
||||
private final JwtConverter jwtConverter;
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
http.authorizeHttpRequests((authz) ->
|
||||
authz.requestMatchers(HttpMethod.GET, "/messages/").permitAll()
|
||||
.anyRequest().authenticated());
|
||||
|
||||
http.sessionManagement(sess -> sess.sessionCreationPolicy(
|
||||
SessionCreationPolicy.STATELESS));
|
||||
http.oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(jwtConverter)));
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1 +1,5 @@
|
||||
spring.application.name=SWA-Jodel
|
||||
|
||||
# Security Configuration
|
||||
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://keycloak.anxietyprime.de/realms/Jodel
|
||||
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=${spring.security.oauth2.resourceserver.jwt.issuer-uri}/protocol/openid-connect/certs
|
||||
|
||||
Reference in New Issue
Block a user