Group OIDC settings under cameleer.server.security.oidc.*
Move OIDC properties into a nested Oidc class within SecurityProperties for clearer grouping. Env vars gain an extra separator: cameleer.server.security.oidc.issueruri → CAMELEER_SERVER_SECURITY_OIDC_ISSUERURI cameleer.server.security.oidc.jwkseturi → CAMELEER_SERVER_SECURITY_OIDC_JWKSETURI cameleer.server.security.oidc.audience → CAMELEER_SERVER_SECURITY_OIDC_AUDIENCE cameleer.server.security.oidc.tlsskipverify → CAMELEER_SERVER_SECURITY_OIDC_TLSSKIPVERIFY Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -59,7 +59,7 @@ public class UserAdminController {
|
|||||||
this.rbacService = rbacService;
|
this.rbacService = rbacService;
|
||||||
this.userRepository = userRepository;
|
this.userRepository = userRepository;
|
||||||
this.auditService = auditService;
|
this.auditService = auditService;
|
||||||
String issuer = securityProperties.getOidcIssuerUri();
|
String issuer = securityProperties.getOidc().getIssuerUri();
|
||||||
this.oidcEnabled = issuer != null && !issuer.isBlank();
|
this.oidcEnabled = issuer != null && !issuer.isBlank();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ public class OidcTokenExchanger {
|
|||||||
body += "&resource=" + java.net.URLEncoder.encode(configAudience, java.nio.charset.StandardCharsets.UTF_8);
|
body += "&resource=" + java.net.URLEncoder.encode(configAudience, java.nio.charset.StandardCharsets.UTF_8);
|
||||||
httpRequest.setBody(body);
|
httpRequest.setBody(body);
|
||||||
}
|
}
|
||||||
if (securityProperties.isOidcTlsSkipVerify()) {
|
if (securityProperties.getOidc().isTlsSkipVerify()) {
|
||||||
httpRequest.setSSLSocketFactory(InsecureTlsHelper.socketFactory());
|
httpRequest.setSSLSocketFactory(InsecureTlsHelper.socketFactory());
|
||||||
httpRequest.setHostnameVerifier(InsecureTlsHelper.hostnameVerifier());
|
httpRequest.setHostnameVerifier(InsecureTlsHelper.hostnameVerifier());
|
||||||
}
|
}
|
||||||
@@ -267,7 +267,7 @@ public class OidcTokenExchanger {
|
|||||||
OIDCProviderMetadata metadata = getProviderMetadata(issuerUri);
|
OIDCProviderMetadata metadata = getProviderMetadata(issuerUri);
|
||||||
URL jwksUrl = metadata.getJWKSetURI().toURL();
|
URL jwksUrl = metadata.getJWKSetURI().toURL();
|
||||||
JWKSource<SecurityContext> jwkSource = OidcProviderHelper.buildJwkSource(
|
JWKSource<SecurityContext> jwkSource = OidcProviderHelper.buildJwkSource(
|
||||||
jwksUrl, securityProperties.isOidcTlsSkipVerify());
|
jwksUrl, securityProperties.getOidc().isTlsSkipVerify());
|
||||||
var keySelector = new JWSVerificationKeySelector<SecurityContext>(
|
var keySelector = new JWSVerificationKeySelector<SecurityContext>(
|
||||||
OidcProviderHelper.SUPPORTED_ALGORITHMS, jwkSource);
|
OidcProviderHelper.SUPPORTED_ALGORITHMS, jwkSource);
|
||||||
ConfigurableJWTProcessor<SecurityContext> processor = new DefaultJWTProcessor<>();
|
ConfigurableJWTProcessor<SecurityContext> processor = new DefaultJWTProcessor<>();
|
||||||
@@ -286,7 +286,7 @@ public class OidcTokenExchanger {
|
|||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (providerMetadata == null || !issuerUri.equals(cachedIssuerUri)) {
|
if (providerMetadata == null || !issuerUri.equals(cachedIssuerUri)) {
|
||||||
providerMetadata = OidcProviderHelper.fetchMetadata(
|
providerMetadata = OidcProviderHelper.fetchMetadata(
|
||||||
issuerUri, securityProperties.isOidcTlsSkipVerify());
|
issuerUri, securityProperties.getOidc().isTlsSkipVerify());
|
||||||
cachedIssuerUri = issuerUri;
|
cachedIssuerUri = issuerUri;
|
||||||
jwtProcessor = null; // Reset processor when issuer changes
|
jwtProcessor = null; // Reset processor when issuer changes
|
||||||
log.info("OIDC provider metadata loaded from {}", issuerUri);
|
log.info("OIDC provider metadata loaded from {}", issuerUri);
|
||||||
@@ -303,7 +303,7 @@ public class OidcTokenExchanger {
|
|||||||
OIDCProviderMetadata metadata = getProviderMetadata(issuerUri);
|
OIDCProviderMetadata metadata = getProviderMetadata(issuerUri);
|
||||||
URL jwksUrl = metadata.getJWKSetURI().toURL();
|
URL jwksUrl = metadata.getJWKSetURI().toURL();
|
||||||
JWKSource<SecurityContext> jwkSource = OidcProviderHelper.buildJwkSource(
|
JWKSource<SecurityContext> jwkSource = OidcProviderHelper.buildJwkSource(
|
||||||
jwksUrl, securityProperties.isOidcTlsSkipVerify());
|
jwksUrl, securityProperties.getOidc().isTlsSkipVerify());
|
||||||
var keySelector = new JWSVerificationKeySelector<SecurityContext>(
|
var keySelector = new JWSVerificationKeySelector<SecurityContext>(
|
||||||
OidcProviderHelper.SUPPORTED_ALGORITHMS, jwkSource);
|
OidcProviderHelper.SUPPORTED_ALGORITHMS, jwkSource);
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public class SecurityConfig {
|
|||||||
CorsConfigurationSource corsConfigurationSource,
|
CorsConfigurationSource corsConfigurationSource,
|
||||||
UserRepository userRepository) throws Exception {
|
UserRepository userRepository) throws Exception {
|
||||||
JwtDecoder oidcDecoder = null;
|
JwtDecoder oidcDecoder = null;
|
||||||
String issuer = securityProperties.getOidcIssuerUri();
|
String issuer = securityProperties.getOidc().getIssuerUri();
|
||||||
if (issuer != null && !issuer.isBlank()) {
|
if (issuer != null && !issuer.isBlank()) {
|
||||||
try {
|
try {
|
||||||
oidcDecoder = buildOidcDecoder(securityProperties);
|
oidcDecoder = buildOidcDecoder(securityProperties);
|
||||||
@@ -155,22 +155,22 @@ public class SecurityConfig {
|
|||||||
* {@code at+jwt} token type (RFC 9068) by accepting any JWT type.
|
* {@code at+jwt} token type (RFC 9068) by accepting any JWT type.
|
||||||
*/
|
*/
|
||||||
private JwtDecoder buildOidcDecoder(SecurityProperties properties) throws Exception {
|
private JwtDecoder buildOidcDecoder(SecurityProperties properties) throws Exception {
|
||||||
String issuerUri = properties.getOidcIssuerUri();
|
String issuerUri = properties.getOidc().getIssuerUri();
|
||||||
|
|
||||||
// Resolve JWKS URI: use explicit config if set, otherwise discover from OIDC metadata.
|
// Resolve JWKS URI: use explicit config if set, otherwise discover from OIDC metadata.
|
||||||
URL jwksUri;
|
URL jwksUri;
|
||||||
String jwkSetUri = properties.getOidcJwkSetUri();
|
String jwkSetUri = properties.getOidc().getJwkSetUri();
|
||||||
if (jwkSetUri != null && !jwkSetUri.isBlank()) {
|
if (jwkSetUri != null && !jwkSetUri.isBlank()) {
|
||||||
jwksUri = new URI(jwkSetUri).toURL();
|
jwksUri = new URI(jwkSetUri).toURL();
|
||||||
log.info("Using explicit JWKS URI: {}", jwksUri);
|
log.info("Using explicit JWKS URI: {}", jwksUri);
|
||||||
} else {
|
} else {
|
||||||
OIDCProviderMetadata metadata = OidcProviderHelper.fetchMetadata(
|
OIDCProviderMetadata metadata = OidcProviderHelper.fetchMetadata(
|
||||||
issuerUri, properties.isOidcTlsSkipVerify());
|
issuerUri, properties.getOidc().isTlsSkipVerify());
|
||||||
jwksUri = metadata.getJWKSetURI().toURL();
|
jwksUri = metadata.getJWKSetURI().toURL();
|
||||||
}
|
}
|
||||||
|
|
||||||
JWKSource<SecurityContext> jwkSource = OidcProviderHelper.buildJwkSource(
|
JWKSource<SecurityContext> jwkSource = OidcProviderHelper.buildJwkSource(
|
||||||
jwksUri, properties.isOidcTlsSkipVerify());
|
jwksUri, properties.getOidc().isTlsSkipVerify());
|
||||||
var keySelector = new JWSVerificationKeySelector<SecurityContext>(
|
var keySelector = new JWSVerificationKeySelector<SecurityContext>(
|
||||||
OidcProviderHelper.SUPPORTED_ALGORITHMS, jwkSource);
|
OidcProviderHelper.SUPPORTED_ALGORITHMS, jwkSource);
|
||||||
var processor = new DefaultJWTProcessor<SecurityContext>();
|
var processor = new DefaultJWTProcessor<SecurityContext>();
|
||||||
@@ -181,7 +181,7 @@ public class SecurityConfig {
|
|||||||
|
|
||||||
// Validate issuer + optionally audience
|
// Validate issuer + optionally audience
|
||||||
OAuth2TokenValidator<Jwt> validators;
|
OAuth2TokenValidator<Jwt> validators;
|
||||||
String audience = properties.getOidcAudience();
|
String audience = properties.getOidc().getAudience();
|
||||||
if (audience != null && !audience.isBlank()) {
|
if (audience != null && !audience.isBlank()) {
|
||||||
validators = new DelegatingOAuth2TokenValidator<>(
|
validators = new DelegatingOAuth2TokenValidator<>(
|
||||||
JwtValidators.createDefaultWithIssuer(issuerUri),
|
JwtValidators.createDefaultWithIssuer(issuerUri),
|
||||||
|
|||||||
@@ -17,11 +17,24 @@ public class SecurityProperties {
|
|||||||
private String uiPassword;
|
private String uiPassword;
|
||||||
private String uiOrigin;
|
private String uiOrigin;
|
||||||
private String jwtSecret;
|
private String jwtSecret;
|
||||||
private String oidcIssuerUri;
|
|
||||||
private String oidcJwkSetUri;
|
|
||||||
private String oidcAudience;
|
|
||||||
private boolean oidcTlsSkipVerify;
|
|
||||||
private String corsAllowedOrigins;
|
private String corsAllowedOrigins;
|
||||||
|
private Oidc oidc = new Oidc();
|
||||||
|
|
||||||
|
public static class Oidc {
|
||||||
|
private String issuerUri;
|
||||||
|
private String jwkSetUri;
|
||||||
|
private String audience;
|
||||||
|
private boolean tlsSkipVerify;
|
||||||
|
|
||||||
|
public String getIssuerUri() { return issuerUri; }
|
||||||
|
public void setIssuerUri(String issuerUri) { this.issuerUri = issuerUri; }
|
||||||
|
public String getJwkSetUri() { return jwkSetUri; }
|
||||||
|
public void setJwkSetUri(String jwkSetUri) { this.jwkSetUri = jwkSetUri; }
|
||||||
|
public String getAudience() { return audience; }
|
||||||
|
public void setAudience(String audience) { this.audience = audience; }
|
||||||
|
public boolean isTlsSkipVerify() { return tlsSkipVerify; }
|
||||||
|
public void setTlsSkipVerify(boolean tlsSkipVerify) { this.tlsSkipVerify = tlsSkipVerify; }
|
||||||
|
}
|
||||||
|
|
||||||
public long getAccessTokenExpiryMs() { return accessTokenExpiryMs; }
|
public long getAccessTokenExpiryMs() { return accessTokenExpiryMs; }
|
||||||
public void setAccessTokenExpiryMs(long accessTokenExpiryMs) { this.accessTokenExpiryMs = accessTokenExpiryMs; }
|
public void setAccessTokenExpiryMs(long accessTokenExpiryMs) { this.accessTokenExpiryMs = accessTokenExpiryMs; }
|
||||||
@@ -39,14 +52,8 @@ public class SecurityProperties {
|
|||||||
public void setUiOrigin(String uiOrigin) { this.uiOrigin = uiOrigin; }
|
public void setUiOrigin(String uiOrigin) { this.uiOrigin = uiOrigin; }
|
||||||
public String getJwtSecret() { return jwtSecret; }
|
public String getJwtSecret() { return jwtSecret; }
|
||||||
public void setJwtSecret(String jwtSecret) { this.jwtSecret = jwtSecret; }
|
public void setJwtSecret(String jwtSecret) { this.jwtSecret = jwtSecret; }
|
||||||
public String getOidcIssuerUri() { return oidcIssuerUri; }
|
|
||||||
public void setOidcIssuerUri(String oidcIssuerUri) { this.oidcIssuerUri = oidcIssuerUri; }
|
|
||||||
public String getOidcJwkSetUri() { return oidcJwkSetUri; }
|
|
||||||
public void setOidcJwkSetUri(String oidcJwkSetUri) { this.oidcJwkSetUri = oidcJwkSetUri; }
|
|
||||||
public String getOidcAudience() { return oidcAudience; }
|
|
||||||
public void setOidcAudience(String oidcAudience) { this.oidcAudience = oidcAudience; }
|
|
||||||
public boolean isOidcTlsSkipVerify() { return oidcTlsSkipVerify; }
|
|
||||||
public void setOidcTlsSkipVerify(boolean oidcTlsSkipVerify) { this.oidcTlsSkipVerify = oidcTlsSkipVerify; }
|
|
||||||
public String getCorsAllowedOrigins() { return corsAllowedOrigins; }
|
public String getCorsAllowedOrigins() { return corsAllowedOrigins; }
|
||||||
public void setCorsAllowedOrigins(String corsAllowedOrigins) { this.corsAllowedOrigins = corsAllowedOrigins; }
|
public void setCorsAllowedOrigins(String corsAllowedOrigins) { this.corsAllowedOrigins = corsAllowedOrigins; }
|
||||||
|
public Oidc getOidc() { return oidc; }
|
||||||
|
public void setOidc(Oidc oidc) { this.oidc = oidc; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,11 +69,12 @@ cameleer:
|
|||||||
uipassword: ${CAMELEER_SERVER_SECURITY_UIPASSWORD:admin}
|
uipassword: ${CAMELEER_SERVER_SECURITY_UIPASSWORD:admin}
|
||||||
uiorigin: ${CAMELEER_SERVER_SECURITY_UIORIGIN:http://localhost:5173}
|
uiorigin: ${CAMELEER_SERVER_SECURITY_UIORIGIN:http://localhost:5173}
|
||||||
jwtsecret: ${CAMELEER_SERVER_SECURITY_JWTSECRET:}
|
jwtsecret: ${CAMELEER_SERVER_SECURITY_JWTSECRET:}
|
||||||
oidcissueruri: ${CAMELEER_SERVER_SECURITY_OIDCISSUERURI:}
|
|
||||||
oidcjwkseturi: ${CAMELEER_SERVER_SECURITY_OIDCJWKSETURI:}
|
|
||||||
oidcaudience: ${CAMELEER_SERVER_SECURITY_OIDCAUDIENCE:}
|
|
||||||
oidctlsskipverify: ${CAMELEER_SERVER_SECURITY_OIDCTLSSKIPVERIFY:false}
|
|
||||||
corsallowedorigins: ${CAMELEER_SERVER_SECURITY_CORSALLOWEDORIGINS:}
|
corsallowedorigins: ${CAMELEER_SERVER_SECURITY_CORSALLOWEDORIGINS:}
|
||||||
|
oidc:
|
||||||
|
issueruri: ${CAMELEER_SERVER_SECURITY_OIDC_ISSUERURI:}
|
||||||
|
jwkseturi: ${CAMELEER_SERVER_SECURITY_OIDC_JWKSETURI:}
|
||||||
|
audience: ${CAMELEER_SERVER_SECURITY_OIDC_AUDIENCE:}
|
||||||
|
tlsskipverify: ${CAMELEER_SERVER_SECURITY_OIDC_TLSSKIPVERIFY:false}
|
||||||
clickhouse:
|
clickhouse:
|
||||||
url: ${CAMELEER_SERVER_CLICKHOUSE_URL:jdbc:clickhouse://localhost:8123/cameleer}
|
url: ${CAMELEER_SERVER_CLICKHOUSE_URL:jdbc:clickhouse://localhost:8123/cameleer}
|
||||||
username: ${CAMELEER_SERVER_CLICKHOUSE_USERNAME:default}
|
username: ${CAMELEER_SERVER_CLICKHOUSE_USERNAME:default}
|
||||||
|
|||||||
Reference in New Issue
Block a user