Compare commits
2 Commits
24fd96c8b2
...
018285c109
| Author | SHA1 | Date | |
|---|---|---|---|
| 018285c109 | |||
| 350e1a8a43 |
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>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package de.anxietyprime.swajodel;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
|
||||
77
src/main/java/de/anxietyprime/swajodel/User.java
Normal file
77
src/main/java/de/anxietyprime/swajodel/User.java
Normal file
@@ -0,0 +1,77 @@
|
||||
package de.anxietyprime.swajodel;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
|
||||
public class User {
|
||||
static public String getUUID () {
|
||||
return SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
}
|
||||
|
||||
static public Long getUserID () {
|
||||
String uuid = SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
Long id = -1L;
|
||||
|
||||
// DB connection and statement
|
||||
Connection c;
|
||||
PreparedStatement stmt;
|
||||
|
||||
// try to get data from db
|
||||
try {
|
||||
// check for the driver
|
||||
Class.forName("org.postgresql.Driver");
|
||||
// get the connection with credentials from env variables
|
||||
c = DriverManager
|
||||
.getConnection("jdbc:postgresql://"+
|
||||
System.getenv("POSTGRES_IP")+"/"+System.getenv("POSTGRES_DB"),
|
||||
System.getenv("POSTGRES_USER"), System.getenv("POSTGRES_PASSWORD"));
|
||||
// disable auto commits
|
||||
c.setAutoCommit(false);
|
||||
|
||||
// create a new statement
|
||||
stmt = c.prepareStatement("SELECT id FROM users WHERE username = (?)");
|
||||
|
||||
stmt.setObject(1, uuid);
|
||||
|
||||
// insert post and get its id
|
||||
ResultSet rs = stmt.executeQuery();
|
||||
|
||||
// check if there is a parent
|
||||
if (!rs.next()) {
|
||||
// create a new statement
|
||||
stmt = c.prepareStatement("INSERT INTO users(username, password) VALUES (?, 'unused') RETURNING id");
|
||||
|
||||
// fill statement
|
||||
stmt.setObject(1, uuid);
|
||||
|
||||
// execute statement
|
||||
rs = stmt.executeQuery();
|
||||
|
||||
// commit the changes
|
||||
c.commit();
|
||||
|
||||
rs.next();
|
||||
}
|
||||
|
||||
id = rs.getLong("id");
|
||||
|
||||
// close all connections to db
|
||||
stmt.close();
|
||||
c.close();
|
||||
}
|
||||
|
||||
// else log the error
|
||||
catch ( Exception e ) {
|
||||
System.err.println( e.getClass().getName()+": "+ e.getMessage() );
|
||||
throw new ResponseStatusException(HttpStatus.SERVICE_UNAVAILABLE, "Database is offline");
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
}
|
||||
@@ -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