Skip to content

Commit 2316064

Browse files
Merge branch 'develop' into 359-enhance-publishing-message-acknowledgement
2 parents 9aa34a3 + a843c84 commit 2316064

11 files changed

Lines changed: 99 additions & 6 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
This release fixes a bug where the value of the dataverse.auth.oidc.enabled setting, available when Provisioning an authentication provider via JVM options (see ref: https://guides.dataverse.org/en/latest/installation/oidc.html#provision-via-jvm-options) was not being not being propagated to the current Dataverse user interface (where enabled=false providers are not displayed for login/registration) or represented in the GET api/admin/authenticationProviders API call.
2+
3+
A new JVM setting ('dataverse.auth.oidc.hidden-jsf') was added to hide an enabled OIDC Provider from the JSF UI.
4+
5+
For Dataverse instances deploying both the current JSF UI and the new SPA UI, this fix allows the OIDC Keycloak provider configured for the SPA to be hidden in the JSF UI (useful in cases where it would duplicate other configured providers).
6+
7+
Note: The API to create a new Auth Provider can only be used to create a provider for both JSF and SPA. Use JVM / MicroProfile config setting to create SPA only providers.

doc/sphinx-guides/source/api/native-api.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7679,6 +7679,8 @@ Add new authentication provider. The POST data is in JSON format, similar to the
76797679
76807680
POST http://$SERVER/api/admin/authenticationProviders
76817681
7682+
.. note:: This endpoint will create providers for both JSF and SPA. Use :ref:`jvm-options` / *MicroProfile Config* if you need to create SPA only providers.
7683+
76827684
Show Authentication Provider
76837685
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
76847686

doc/sphinx-guides/source/installation/oidc.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,10 @@ The following options are available:
151151
- Enable or disable provisioning the provider via MicroProfile.
152152
- N
153153
- ``false``
154+
* - ``dataverse.auth.oidc.hidden-jsf``
155+
- Show or Hide the provider from the JSF UI via MicroProfile.
156+
- N
157+
- ``false``
154158
* - ``dataverse.auth.oidc.client-id``
155159
- The client-id of the application to identify it at your provider.
156160
- Y
@@ -187,4 +191,4 @@ The following options are available:
187191
- Tune the maximum age, in seconds, of all OIDC providers' verifier cache entries. Default is 5 minutes, equivalent to lifetime
188192
of many OIDC access tokens.
189193
- N
190-
- 300
194+
- 300

docker-compose-dev.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ services:
2222
DATAVERSE_MAIL_SYSTEM_EMAIL: "dataverse@localhost"
2323
DATAVERSE_MAIL_MTA_HOST: "smtp"
2424
DATAVERSE_AUTH_OIDC_ENABLED: "1"
25+
DATAVERSE_AUTH_OIDC_HIDDEN_JSF: "1"
2526
DATAVERSE_AUTH_OIDC_CLIENT_ID: test
2627
DATAVERSE_AUTH_OIDC_CLIENT_SECRET: 94XHrfNRwXsjqTqApRrwWmhDLDHpIYV8
2728
DATAVERSE_AUTH_OIDC_AUTH_SERVER_URL: http://keycloak.mydomain.com:8090/realms/test

src/main/java/edu/harvard/iq/dataverse/LoginPage.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ public List<AuthenticationProviderDisplayInfo> listAuthenticationProviders() {
143143
Collections.sort(idps, Comparator.comparing(AuthenticationProvider::getOrder).thenComparing(AuthenticationProvider::getId));
144144

145145
for (AuthenticationProvider idp : idps) {
146-
if (idp != null) {
146+
if (idp != null && !idp.isHidden()) {
147147
infos.add(idp.getInfo());
148148
}
149149
}

src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationProvider.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
* "authenticationProvider.name." + "ship" ->
1919
* (c) Bundle.properties entry: "authenticationProvider.name.shib=Shibboleth"
2020
*
21-
* {@code AuthenticationPrvider}s are normally registered at startup in {@link AuthenticationServiceBean#startup()}.
21+
* {@code AuthenticationProvider}s are normally registered at startup in {@link AuthenticationServiceBean#startup()}.
2222
*
2323
* @author michael
2424
*/
@@ -33,9 +33,13 @@ public interface AuthenticationProvider {
3333
default boolean isUserInfoUpdateAllowed() { return false; };
3434
default boolean isUserDeletionAllowed() { return false; };
3535
default boolean isOAuthProvider() { return false; };
36-
37-
38-
36+
default boolean isEnabled() {
37+
return true;
38+
};
39+
default boolean isHidden() {
40+
return false;
41+
};
42+
3943
/**
4044
* Some providers (e.g organizational ones) provide verified email addresses.
4145
* @return {@code true} if we can treat email addresses coming from this provider as verified, {@code false} otherwise.

src/main/java/edu/harvard/iq/dataverse/authorization/providers/oauth2/AbstractOAuth2AuthenticationProvider.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ public String toString() {
9393
protected String clientSecret;
9494
protected String baseUserEndpoint;
9595
protected String redirectUrl;
96+
protected boolean enabled = true;
97+
protected boolean hidden = false; // Special flag to hide this provider in JSF UI
9698

9799
/**
98100
* List of scopes to be requested for authorization at identity provider.
@@ -272,6 +274,21 @@ public String getSubTitle() {
272274

273275
public String getSpacedScope() { return String.join(" ", getScope()); }
274276

277+
public void setEnabled(boolean enabled) {
278+
this.enabled = enabled;
279+
}
280+
281+
public boolean isEnabled() {
282+
return enabled;
283+
}
284+
285+
public void setHidden(boolean hidden) {
286+
this.hidden = hidden;
287+
}
288+
public boolean isHidden() {
289+
return hidden;
290+
}
291+
275292
@Override
276293
public int hashCode() {
277294
int hash = 7;

src/main/java/edu/harvard/iq/dataverse/authorization/providers/oauth2/oidc/OIDCAuthenticationProviderFactory.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public AuthenticationProvider buildProvider( AuthenticationProviderRow aRow ) th
4949
oidc.setId(aRow.getId());
5050
oidc.setTitle(aRow.getTitle());
5151
oidc.setSubTitle(aRow.getSubtitle());
52+
oidc.setEnabled(aRow.isEnabled());
5253

5354
return oidc;
5455
}
@@ -70,6 +71,8 @@ public static AuthenticationProvider buildFromSettings() throws AuthorizationSet
7071
oidc.setId("oidc-mpconfig");
7172
oidc.setTitle(JvmSettings.OIDC_TITLE.lookupOptional().orElse("OpenID Connect"));
7273
oidc.setSubTitle(JvmSettings.OIDC_SUBTITLE.lookupOptional().orElse("OpenID Connect"));
74+
oidc.setEnabled(JvmSettings.OIDC_ENABLED.lookupOptional(Boolean.class).orElse(true));
75+
oidc.setHidden(JvmSettings.OIDC_HIDDEN_JSF.lookupOptional(Boolean.class).orElse(false));
7376

7477
return oidc;
7578
}

src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ public enum JvmSettings {
247247
// AUTH: OIDC SETTINGS
248248
SCOPE_OIDC(SCOPE_AUTH, "oidc"),
249249
OIDC_ENABLED(SCOPE_OIDC, "enabled"),
250+
OIDC_HIDDEN_JSF(SCOPE_OIDC, "hidden-jsf"), // Special case when this provider needs to be hidden in JSF UI
250251
OIDC_TITLE(SCOPE_OIDC, "title"),
251252
OIDC_SUBTITLE(SCOPE_OIDC, "subtitle"),
252253
OIDC_AUTH_SERVER_URL(SCOPE_OIDC, "auth-server-url"),

src/test/java/edu/harvard/iq/dataverse/api/AdminIT.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ public class AdminIT {
4949
private static final Logger logger = Logger.getLogger(AdminIT.class.getCanonicalName());
5050

5151
private final String testNonSuperuserApiToken = createTestNonSuperuserApiToken();
52+
static final String clientId = "test";
53+
static final String clientSecret = "94XHrfNRwXsjqTqApRrwWmhDLDHpIYV8";
5254

5355
@BeforeAll
5456
public static void setUp() {
@@ -1117,4 +1119,48 @@ public void testSetSuperUserStatus(Boolean status) {
11171119
toggleSuperuser.then().assertThat()
11181120
.statusCode(OK.getStatusCode());
11191121
}
1122+
1123+
// Testing creating an OIDC Provider not intended for use in JSF UI
1124+
@Test
1125+
public void testAddAuthProviders() {
1126+
Response createSuperuser = UtilIT.createRandomUser();
1127+
String superuserUsername = UtilIT.getUsernameFromResponse(createSuperuser);
1128+
String superuserApiToken = UtilIT.getApiTokenFromResponse(createSuperuser);
1129+
Response toggleSuperuser = UtilIT.makeSuperUser(superuserUsername);
1130+
toggleSuperuser.then().assertThat()
1131+
.statusCode(OK.getStatusCode());
1132+
1133+
Response getAuthProviders = UtilIT.getAuthProviders(superuserApiToken);
1134+
getAuthProviders.prettyPrint();
1135+
1136+
String factoryData = String.format("type: oidc | issuer: http://keycloak.mydomain.com:8090/realms/test | clientId: %s | clientSecret: %s", clientId, clientSecret);
1137+
JsonObject jsonObject = Json.createObjectBuilder()
1138+
.add("id", "oidc1")
1139+
.add("factoryAlias", "oidc")
1140+
.add("title", "Open ID Connect SPA")
1141+
.add("subtitle", "SPA OIDC Provider")
1142+
.add("factoryData", factoryData)
1143+
.add("enabled", false)
1144+
.build();
1145+
Response addAuthProviders = UtilIT.addAuthProviders(superuserApiToken, jsonObject);
1146+
addAuthProviders.prettyPrint();
1147+
addAuthProviders.then().assertThat()
1148+
.statusCode(CREATED.getStatusCode());
1149+
1150+
getAuthProviders = UtilIT.getAuthProviders(superuserApiToken);
1151+
getAuthProviders.prettyPrint();
1152+
getAuthProviders.then().assertThat()
1153+
.statusCode(OK.getStatusCode());
1154+
1155+
boolean found = false;
1156+
List<Map<String, Object>> providers = getAuthProviders.body().jsonPath().getList("data");
1157+
for (Map<String, Object> provider : providers) {
1158+
if ("oidc1".equalsIgnoreCase((String) provider.get("id"))) {
1159+
found = true;
1160+
assertTrue(provider.get("title") != null && provider.get("title").equals("Open ID Connect SPA"));
1161+
assertTrue(provider.get("enabled") != null && !(Boolean) provider.get("enabled"));
1162+
}
1163+
}
1164+
assertTrue(found);
1165+
}
11201166
}

0 commit comments

Comments
 (0)