You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit f98eb11
Browse filesBrowse the repository at this point in the historyBrowse files
The OAuth2 plugin resolves a login to a UserOAuth2Authenticator through a fixed
provider-name to Spring-bean map, and each OIDC vendor is its own bean running the
same authorization-code flow with no vendor-specific logic. A new IdP needs a new
class, and since provider is both the display name and the routing key, a domain can
register only one keycloak.
This adds a type column to oauth_provider. OAuth2AuthManagerImpl looks the name up in
the bean map first and only on a miss falls back to the registration's type, so
provider becomes an admin-chosen label and type selects the implementation. One bean
then serves any number of registrations under arbitrary names. Existing google, github
and keycloak rows carry a null type and dispatch by name as before.
GenericOIDCOAuth2Provider is registered under type oidc and configured with the issuer
URL. It reads the token and JWKS endpoints from the issuer's discovery document (the
issuer must match), and validates the id_token before trusting it: signature against the
JWKS key named by the token kid, then issuer, audience and expiry, using the CXF JOSE
library already on the classpath. It holds no token state between logins, and a code
verified through verifyOAuthCodeAndGetUser is redeemed once so the following oauthlogin
does not re-present it.
ListOAuthProvidersCmd and UpdateOAuthProviderCmd derived the response enabled flag from a
name-to-bean check, which reported every generically-named registration as disabled; both
now also accept a registration whose type resolves to a plugin.
The schema change adds type and issuer_url to oauth_provider in the 4.23.0.0 to 24.0.0
upgrade file. Login.vue renders the OAuth buttons from the registered provider list so a
generic oidc provider gets a Sign in with <label> button and starts the flow from the
issuer's authorize endpoint, resolved from discovery.
Copy file name to clipboardExpand all lines: engine/schema/src/main/resources/META-INF/db/schema-42300to2400.sql
+4Lines changed: 4 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -18,3 +18,7 @@
18
18
--;
19
19
-- Schema upgrade from 4.23.0.0 to 24.0.0
20
20
--;
21
+
22
+
-- Generic OIDC OAuth2 provider: a type to select the implementation, and the issuer URL for discovery
23
+
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.oauth_provider', 'type', 'VARCHAR(40) DEFAULT NULL COMMENT ''Provider implementation serving this registration, for example oidc; NULL means the provider name selects the implementation'' AFTER `token_url` ');
24
+
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.oauth_provider', 'issuer_url', 'VARCHAR(255) DEFAULT NULL COMMENT ''Issuer URL of the OpenID Connect provider, used to read its discovery document'' AFTER `type` ');
Copy file name to clipboardExpand all lines: plugins/user-authenticators/oauth2/src/main/java/org/apache/cloudstack/oauth2/OAuth2UserAuthenticator.java
+2-2Lines changed: 2 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -74,8 +74,8 @@ public Pair<Boolean, ActionOnFailedAuthentication> authenticate(String username,
Copy file name to clipboardExpand all lines: plugins/user-authenticators/oauth2/src/main/java/org/apache/cloudstack/oauth2/api/command/ListOAuthProvidersCmd.java
Copy file name to clipboardExpand all lines: plugins/user-authenticators/oauth2/src/main/java/org/apache/cloudstack/oauth2/api/command/RegisterOAuthProviderCmd.java
@@ -76,6 +77,16 @@ public class RegisterOAuthProviderCmd extends BaseCmd {
76
77
@Parameter(name = ApiConstants.TOKEN_URL, type = CommandType.STRING, description = "Token URL for OAuth finalization (only required for keycloak provider)", since = "4.23.0")
77
78
privateStringtokenUrl;
78
79
80
+
@Parameter(name = ApiConstants.TYPE, type = CommandType.STRING,
81
+
description = "Type of the provider implementation serving this registration, for example oidc for any OpenID Connect compliant provider. "
82
+
+ "When set, the name in provider is a label chosen by the administrator rather than a built in provider name.", since = "4.24.0")
83
+
privateStringtype;
84
+
85
+
@Parameter(name = ApiConstants.ISSUER_URL, type = CommandType.STRING,
86
+
description = "Issuer URL of the OpenID Connect provider, required for type oidc. The token endpoint and the keys that sign "
87
+
+ "its tokens are read from the issuer's discovery document", since = "4.24.0")
88
+
privateStringissuerUrl;
89
+
79
90
@Parameter(name = ApiConstants.DETAILS, type = CommandType.MAP,
80
91
description = "Any OAuth provider details in key/value pairs using format details[i].keyname=keyvalue. Example: details[0].clientsecret=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")
81
92
protectedMapdetails;
@@ -121,6 +132,14 @@ public String getTokenUrl() {
121
132
returntokenUrl;
122
133
}
123
134
135
+
publicStringgetType() {
136
+
returntype;
137
+
}
138
+
139
+
publicStringgetIssuerUrl() {
140
+
returnissuerUrl;
141
+
}
142
+
124
143
publicMapgetDetails() {
125
144
if (MapUtils.isEmpty(details)) {
126
145
returnnull;
@@ -143,12 +162,18 @@ public void execute() throws ServerApiException, ConcurrentOperationException, E
143
162
}
144
163
}
145
164
165
+
if (StringUtils.equalsIgnoreCase(GenericOIDCOAuth2Provider.OIDC_PROVIDER_TYPE, getType()) && StringUtils.isBlank(getIssuerUrl())) {
166
+
thrownewServerApiException(ApiErrorCode.BAD_REQUEST, "Parameter issuerurl is mandatory for an oidc OAuth provider");
Copy file name to clipboardExpand all lines: plugins/user-authenticators/oauth2/src/main/java/org/apache/cloudstack/oauth2/api/command/UpdateOAuthProviderCmd.java
@@ -67,6 +68,10 @@ public final class UpdateOAuthProviderCmd extends BaseCmd {
67
68
@Parameter(name = ApiConstants.TOKEN_URL, type = CommandType.STRING, description = "Token URL pre-registered in the specific OAuth provider", since = "4.23.0")
68
69
privateStringtokenUrl;
69
70
71
+
@Parameter(name = ApiConstants.ISSUER_URL, type = CommandType.STRING,
72
+
description = "Issuer URL of the OpenID Connect provider, used to read its discovery document", since = "4.24.0")
73
+
privateStringissuerUrl;
74
+
70
75
@Parameter(name = ApiConstants.ENABLED, type = CommandType.BOOLEAN, description = "OAuth provider will be enabled or disabled based on this value")
71
76
privateBooleanenabled;
72
77
@@ -113,6 +118,10 @@ public String getTokenUrl() {
Copy file name to clipboardExpand all lines: plugins/user-authenticators/oauth2/src/main/java/org/apache/cloudstack/oauth2/api/response/OauthProviderResponse.java
+24Lines changed: 24 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -70,6 +70,14 @@ public class OauthProviderResponse extends BaseResponse {
70
70
@Param(description = "path of the domain the provider belongs to (empty for global)", since = "4.23.0")
71
71
privateStringdomainPath;
72
72
73
+
@SerializedName(ApiConstants.TYPE)
74
+
@Param(description = "Type of the provider, for example oidc for a generic OpenID Connect provider. Empty for the built in providers", since = "4.24.0")
75
+
privateStringtype;
76
+
77
+
@SerializedName(ApiConstants.ISSUER_URL)
78
+
@Param(description = "Issuer URL of the OpenID Connect provider, used for discovery", since = "4.24.0")
79
+
privateStringissuerUrl;
80
+
73
81
@SerializedName(ApiConstants.AUTHORIZE_URL)
74
82
@Param(description = "Authorize URL registered in the OAuth provider")
75
83
privateStringauthorizeUrl;
@@ -180,6 +188,22 @@ public void setDomainPath(String domainPath) {
0 commit comments