diff --git a/src/main/java/de/jottyfan/timetrack/config/SecurityConfiguration.java b/src/main/java/de/jottyfan/timetrack/config/SecurityConfiguration.java index c992356..b44f747 100644 --- a/src/main/java/de/jottyfan/timetrack/config/SecurityConfiguration.java +++ b/src/main/java/de/jottyfan/timetrack/config/SecurityConfiguration.java @@ -1,23 +1,17 @@ package de.jottyfan.timetrack.config; -import org.springframework.beans.factory.annotation.Value; - import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.core.convert.converter.Converter; -import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.oauth2.client.oidc.web.logout.OidcClientInitiatedLogoutSuccessHandler; import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository; -import org.springframework.security.oauth2.jwt.Jwt; -import org.springframework.security.oauth2.jwt.JwtDecoder; -import org.springframework.security.oauth2.jwt.NimbusJwtDecoder; import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter; +import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter; import org.springframework.security.web.SecurityFilterChain; - -import de.jottyfan.timetrack.config.converter.KeycloakRealmRoleConverter; +import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy; +import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy; /** * @@ -28,9 +22,11 @@ import de.jottyfan.timetrack.config.converter.KeycloakRealmRoleConverter; @EnableWebSecurity @EnableMethodSecurity public class SecurityConfiguration { - - @Value("${spring.security.oauth2.client.provider.keycloak.jwk-set-uri}") - private String jwtSetUri; + + @Bean + protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { + return new NullAuthenticatedSessionStrategy(); + } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity sec, InMemoryClientRegistrationRepository crr) @@ -40,19 +36,19 @@ public class SecurityConfiguration { .oauth2Login(o -> o.defaultSuccessUrl("/")) .logout(o -> o.logoutSuccessHandler(new OidcClientInitiatedLogoutSuccessHandler(crr))) .authorizeHttpRequests(o -> o.requestMatchers("/public/**").permitAll().anyRequest().authenticated()) - .oauth2ResourceServer(o -> o.jwt(j -> j.jwtAuthenticationConverter(getConverter()))); + .oauth2ResourceServer(o -> o.jwt(j -> roleConverter())) + .sessionManagement(o -> o.init(sec)); // @formatter:on return sec.build(); } - - private Converter getConverter() { - JwtAuthenticationConverter jwtConverter = new JwtAuthenticationConverter(); - jwtConverter.setJwtGrantedAuthoritiesConverter(new KeycloakRealmRoleConverter()); - return jwtConverter; - } - + @Bean - JwtDecoder jwtDecoder() { - return NimbusJwtDecoder.withJwkSetUri(this.jwtSetUri).build(); + public JwtAuthenticationConverter roleConverter() { + JwtGrantedAuthoritiesConverter gac = new JwtGrantedAuthoritiesConverter(); + gac.setAuthorityPrefix("ROLE_"); + gac.setAuthoritiesClaimName("roles"); + JwtAuthenticationConverter jac = new JwtAuthenticationConverter(); + jac.setJwtGrantedAuthoritiesConverter(gac); + return jac; } } diff --git a/src/main/java/de/jottyfan/timetrack/config/converter/KeycloakRealmRoleConverter.java b/src/main/java/de/jottyfan/timetrack/config/converter/KeycloakRealmRoleConverter.java deleted file mode 100644 index fa9f69c..0000000 --- a/src/main/java/de/jottyfan/timetrack/config/converter/KeycloakRealmRoleConverter.java +++ /dev/null @@ -1,29 +0,0 @@ -package de.jottyfan.timetrack.config.converter; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import org.springframework.core.convert.converter.Converter; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.oauth2.jwt.Jwt; - -/** - * - * @author henkej - * - */ -public class KeycloakRealmRoleConverter implements Converter> { - @Override - public Collection convert(Jwt jwt) { - Object o = jwt.getClaims().get("realm_access"); - @SuppressWarnings("unchecked") - final Map realmAccess = (Map) o; - Object o2 = realmAccess.get("roles"); - @SuppressWarnings("unchecked") - List l = (List) o2; - return l.stream().map(roleName -> "ROLE_" + roleName).map(SimpleGrantedAuthority::new).collect(Collectors.toList()); - } -} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 5b04a82..937ea55 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,25 +1,24 @@ +# include properties file from /etc +spring.config.import = /etc/timetrack.properties + # jooq spring.datasource.driver-class-name = org.postgresql.Driver -# todo: export to /etc/timetrack -spring.datasource.url = jdbc:postgresql://localhost:5432/timetrack -spring.datasource.username = timetrack -spring.datasource.password = timetrack +spring.datasource.url = ${db.url} +spring.datasource.username = ${db.username} +spring.datasource.password = ${db.password} # security -keycloak.url = http://localhost:8080/realms/jottyfan -keycloak.openid.url = ${keycloak.url}/protocol/openid-connect -spring.security.oauth2.client.registration.keycloak.client-id = timetrack +spring.security.oauth2.client.registration.keycloak.client-id = ${keycloak.client-id} spring.security.oauth2.client.registration.keycloak.scope = openid spring.security.oauth2.client.registration.keycloak.authorization-grant-type = authorization_code -# todo: export to /etc/timetrack -spring.security.oauth2.client.registration.keycloak.redirect-uri = http://localhost:8888/timetrack/login/oauth2/code/timetrack -spring.security.oauth2.client.provider.keycloak.issuer-uri = ${keycloak.url} -spring.security.oauth2.client.provider.keycloak.authorization-uri = ${keycloak.openid.url}/auth -spring.security.oauth2.client.provider.keycloak.token-uri = ${keycloak.openid.url}/token -spring.security.oauth2.client.provider.keycloak.user-info-uri = ${keycloak.openid.url}/userinfo -spring.security.oauth2.client.provider.keycloak.jwk-set-uri = ${keycloak.openid.url}/certs +spring.security.oauth2.client.registration.keycloak.redirect-uri = ${keycloak.redirect-uri} +spring.security.oauth2.client.provider.keycloak.issuer-uri = ${keycloak.issuer-uri} +spring.security.oauth2.client.provider.keycloak.authorization-uri = ${keycloak.openid-url}/auth +spring.security.oauth2.client.provider.keycloak.token-uri = ${keycloak.openid-url}/token +spring.security.oauth2.client.provider.keycloak.user-info-uri = ${keycloak.openid-url}/userinfo +spring.security.oauth2.client.provider.keycloak.jwk-set-uri = ${keycloak.openid-url}/certs spring.security.oauth2.client.provider.keycloak.user-name-attribute = preferred_username # application -server:.port = 8083 +server.port = 8083 server.servlet.context-path = /timetrack diff --git a/src/main/resources/templates/calendar/calendar.html b/src/main/resources/templates/calendar/calendar.html index f0a6701..3ec5428 100644 --- a/src/main/resources/templates/calendar/calendar.html +++ b/src/main/resources/templates/calendar/calendar.html @@ -6,7 +6,7 @@ Kalender
    - +
-
+