Phase 2: Tenants + Identity + Licensing #32
@@ -10,6 +10,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.oauth2.server.resource.web.authentication.BearerTokenAuthenticationFilter;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
@@ -19,9 +20,11 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
|
||||
public class SecurityConfig {
|
||||
|
||||
private final JwtAuthenticationFilter machineTokenFilter;
|
||||
private final TenantResolutionFilter tenantResolutionFilter;
|
||||
|
||||
public SecurityConfig(JwtAuthenticationFilter machineTokenFilter) {
|
||||
public SecurityConfig(JwtAuthenticationFilter machineTokenFilter, TenantResolutionFilter tenantResolutionFilter) {
|
||||
this.machineTokenFilter = machineTokenFilter;
|
||||
this.tenantResolutionFilter = tenantResolutionFilter;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -50,7 +53,8 @@ public class SecurityConfig {
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> {}))
|
||||
.addFilterBefore(machineTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
.addFilterBefore(machineTokenFilter, UsernamePasswordAuthenticationFilter.class)
|
||||
.addFilterAfter(tenantResolutionFilter, BearerTokenAuthenticationFilter.class);
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package net.siegeln.cameleer.saas.config;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public final class TenantContext {
|
||||
|
||||
private static final ThreadLocal<UUID> CURRENT_TENANT = new ThreadLocal<>();
|
||||
|
||||
private TenantContext() {}
|
||||
|
||||
public static UUID getTenantId() {
|
||||
return CURRENT_TENANT.get();
|
||||
}
|
||||
|
||||
public static void setTenantId(UUID tenantId) {
|
||||
CURRENT_TENANT.set(tenantId);
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
CURRENT_TENANT.remove();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package net.siegeln.cameleer.saas.config;
|
||||
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import net.siegeln.cameleer.saas.tenant.TenantService;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Component
|
||||
public class TenantResolutionFilter extends OncePerRequestFilter {
|
||||
|
||||
private final TenantService tenantService;
|
||||
|
||||
public TenantResolutionFilter(TenantService tenantService) {
|
||||
this.tenantService = tenantService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
try {
|
||||
var authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
if (authentication instanceof JwtAuthenticationToken jwtAuth) {
|
||||
Jwt jwt = jwtAuth.getToken();
|
||||
String orgId = jwt.getClaimAsString("organization_id");
|
||||
|
||||
if (orgId != null) {
|
||||
tenantService.getByLogtoOrgId(orgId)
|
||||
.ifPresent(tenant -> TenantContext.setTenantId(tenant.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
} finally {
|
||||
TenantContext.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user