feat: add CAMELEER_OIDC_JWK_SET_URI for direct JWKS fetching
When set, fetches JWKs from this URL directly instead of discovering from the OIDC well-known endpoint. Needed when the public issuer URL (e.g., https://domain.com/oidc) isn't reachable from inside containers but the internal URL (http://logto:3001/oidc/jwks) is. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -155,7 +155,15 @@ public class SecurityConfig {
|
|||||||
private JwtDecoder buildOidcDecoder(SecurityProperties properties) throws Exception {
|
private JwtDecoder buildOidcDecoder(SecurityProperties properties) throws Exception {
|
||||||
String issuerUri = properties.getOidcIssuerUri();
|
String issuerUri = properties.getOidcIssuerUri();
|
||||||
|
|
||||||
// Discover JWKS URI and supported algorithms from OIDC discovery
|
// Resolve JWKS URI: use explicit config if set, otherwise discover from OIDC metadata.
|
||||||
|
// Explicit URI is needed when the public issuer URL isn't reachable from inside
|
||||||
|
// containers (e.g., https://domain.com/oidc) but the internal URL is (http://logto:3001/oidc/jwks).
|
||||||
|
URL jwksUri;
|
||||||
|
String jwkSetUri = properties.getOidcJwkSetUri();
|
||||||
|
if (jwkSetUri != null && !jwkSetUri.isBlank()) {
|
||||||
|
jwksUri = new URI(jwkSetUri).toURL();
|
||||||
|
log.info("Using explicit JWKS URI: {}", jwksUri);
|
||||||
|
} else {
|
||||||
String discoveryUrl = issuerUri.endsWith("/")
|
String discoveryUrl = issuerUri.endsWith("/")
|
||||||
? issuerUri + ".well-known/openid-configuration"
|
? issuerUri + ".well-known/openid-configuration"
|
||||||
: issuerUri + "/.well-known/openid-configuration";
|
: issuerUri + "/.well-known/openid-configuration";
|
||||||
@@ -165,7 +173,8 @@ public class SecurityConfig {
|
|||||||
JSONObject json = (JSONObject) new JSONParser(JSONParser.DEFAULT_PERMISSIVE_MODE).parse(in);
|
JSONObject json = (JSONObject) new JSONParser(JSONParser.DEFAULT_PERMISSIVE_MODE).parse(in);
|
||||||
metadata = OIDCProviderMetadata.parse(json);
|
metadata = OIDCProviderMetadata.parse(json);
|
||||||
}
|
}
|
||||||
URL jwksUri = metadata.getJWKSetURI().toURL();
|
jwksUri = metadata.getJWKSetURI().toURL();
|
||||||
|
}
|
||||||
|
|
||||||
// Build decoder supporting ES384 (Logto default) and ES256, RS256
|
// Build decoder supporting ES384 (Logto default) and ES256, RS256
|
||||||
var jwkSource = JWKSourceBuilder.create(jwksUri).build();
|
var jwkSource = JWKSourceBuilder.create(jwksUri).build();
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ public class SecurityProperties {
|
|||||||
private String uiOrigin;
|
private String uiOrigin;
|
||||||
private String jwtSecret;
|
private String jwtSecret;
|
||||||
private String oidcIssuerUri;
|
private String oidcIssuerUri;
|
||||||
|
private String oidcJwkSetUri;
|
||||||
private String oidcAudience;
|
private String oidcAudience;
|
||||||
|
|
||||||
public long getAccessTokenExpiryMs() { return accessTokenExpiryMs; }
|
public long getAccessTokenExpiryMs() { return accessTokenExpiryMs; }
|
||||||
@@ -38,6 +39,8 @@ public class SecurityProperties {
|
|||||||
public void setJwtSecret(String jwtSecret) { this.jwtSecret = jwtSecret; }
|
public void setJwtSecret(String jwtSecret) { this.jwtSecret = jwtSecret; }
|
||||||
public String getOidcIssuerUri() { return oidcIssuerUri; }
|
public String getOidcIssuerUri() { return oidcIssuerUri; }
|
||||||
public void setOidcIssuerUri(String oidcIssuerUri) { this.oidcIssuerUri = 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 String getOidcAudience() { return oidcAudience; }
|
||||||
public void setOidcAudience(String oidcAudience) { this.oidcAudience = oidcAudience; }
|
public void setOidcAudience(String oidcAudience) { this.oidcAudience = oidcAudience; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ security:
|
|||||||
ui-origin: ${CAMELEER_UI_ORIGIN:http://localhost:5173}
|
ui-origin: ${CAMELEER_UI_ORIGIN:http://localhost:5173}
|
||||||
jwt-secret: ${CAMELEER_JWT_SECRET:}
|
jwt-secret: ${CAMELEER_JWT_SECRET:}
|
||||||
oidc-issuer-uri: ${CAMELEER_OIDC_ISSUER_URI:}
|
oidc-issuer-uri: ${CAMELEER_OIDC_ISSUER_URI:}
|
||||||
|
oidc-jwk-set-uri: ${CAMELEER_OIDC_JWK_SET_URI:}
|
||||||
oidc-audience: ${CAMELEER_OIDC_AUDIENCE:}
|
oidc-audience: ${CAMELEER_OIDC_AUDIENCE:}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user