feat: push OIDC config to provisioned server for SSO login
After provisioning a server, pushes Logto Traditional Web App credentials (client ID + secret) via the server's OIDC admin API. This enables SSO: users authenticated via Logto can access the server dashboard without a separate login. Reads tradAppSecret from bootstrap JSON via LogtoConfig. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -29,12 +29,13 @@ public class LogtoConfig {
|
|||||||
private String serverEndpoint;
|
private String serverEndpoint;
|
||||||
|
|
||||||
private String tradAppId;
|
private String tradAppId;
|
||||||
|
private String tradAppSecret;
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
if (isConfigured()) return;
|
if (isConfigured()) return;
|
||||||
|
|
||||||
// Fall back to bootstrap file for M2M credentials + trad app ID
|
// Fall back to bootstrap file for M2M credentials + trad app
|
||||||
try {
|
try {
|
||||||
File file = new File(BOOTSTRAP_FILE);
|
File file = new File(BOOTSTRAP_FILE);
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
@@ -48,6 +49,9 @@ public class LogtoConfig {
|
|||||||
if (node.has("tradAppId")) {
|
if (node.has("tradAppId")) {
|
||||||
tradAppId = node.get("tradAppId").asText();
|
tradAppId = node.get("tradAppId").asText();
|
||||||
}
|
}
|
||||||
|
if (node.has("tradAppSecret")) {
|
||||||
|
tradAppSecret = node.get("tradAppSecret").asText();
|
||||||
|
}
|
||||||
log.info("Loaded M2M credentials from bootstrap file");
|
log.info("Loaded M2M credentials from bootstrap file");
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -60,6 +64,7 @@ public class LogtoConfig {
|
|||||||
public String getM2mClientSecret() { return m2mClientSecret; }
|
public String getM2mClientSecret() { return m2mClientSecret; }
|
||||||
public String getServerEndpoint() { return serverEndpoint; }
|
public String getServerEndpoint() { return serverEndpoint; }
|
||||||
public String getTradAppId() { return tradAppId; }
|
public String getTradAppId() { return tradAppId; }
|
||||||
|
public String getTradAppSecret() { return tradAppSecret; }
|
||||||
|
|
||||||
public boolean isConfigured() {
|
public boolean isConfigured() {
|
||||||
return logtoEndpoint != null && !logtoEndpoint.isEmpty()
|
return logtoEndpoint != null && !logtoEndpoint.isEmpty()
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@@ -127,6 +128,28 @@ public class VendorTenantService {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.warn("License push failed for tenant {}: {}", tenant.getSlug(), e.getMessage());
|
log.warn("License push failed for tenant {}: {}", tenant.getSlug(), e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Configure OIDC on the provisioned server (SSO via Logto)
|
||||||
|
if (logtoConfig.getTradAppId() != null && logtoConfig.getTradAppSecret() != null) {
|
||||||
|
try {
|
||||||
|
String publicBase = provisioningProps.publicProtocol() + "://" + provisioningProps.publicHost();
|
||||||
|
serverApiClient.pushOidcConfig(result.serverEndpoint(), Map.of(
|
||||||
|
"enabled", true,
|
||||||
|
"issuerUri", publicBase + "/oidc",
|
||||||
|
"clientId", logtoConfig.getTradAppId(),
|
||||||
|
"clientSecret", logtoConfig.getTradAppSecret(),
|
||||||
|
"autoSignup", true,
|
||||||
|
"defaultRoles", List.of("VIEWER"),
|
||||||
|
"displayNameClaim", "name",
|
||||||
|
"rolesClaim", "roles",
|
||||||
|
"audience", "https://api.cameleer.local",
|
||||||
|
"additionalScopes", List.of()
|
||||||
|
));
|
||||||
|
log.info("Pushed OIDC config to server for tenant {}", tenant.getSlug());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("OIDC config push failed for tenant {}: {}", tenant.getSlug(), e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
tenant.setProvisionError(result.error());
|
tenant.setProvisionError(result.error());
|
||||||
tenant.setStatus(TenantStatus.PROVISIONING);
|
tenant.setStatus(TenantStatus.PROVISIONING);
|
||||||
|
|||||||
Reference in New Issue
Block a user