From fd743e284c2dc870aaac5377d9e613c3e61c7c29 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Thu, 12 Oct 2017 16:32:13 -0400 Subject: [PATCH] disallow API token lookup via API by default #3153 --- doc/sphinx-guides/source/api/native-api.rst | 7 ------- .../source/installation/config.rst | 7 +++++++ .../iq/dataverse/api/BuiltinUsers.java | 9 +++++++++ .../settings/SettingsServiceBean.java | 1 + .../iq/dataverse/api/BuiltinUsersIT.java | 19 +++++++++++++++++++ 5 files changed, 36 insertions(+), 7 deletions(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 7cce55b81db..756966a610c 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -437,13 +437,6 @@ Place this ``user-add.json`` file in your current directory and run the followin curl -d @user-add.json -H "Content-type:application/json" "$SERVER_URL/api/builtin-users?password=$NEWUSER_PASSWORD&key=$BUILTIN_USERS_KEY" -Retrieving the API Token of a Builtin User -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -To retrieve the API token of a builtin user, given that user's password, use the curl command below:: - - curl "$SERVER_URL/api/builtin-users/$DV_USER_NAME/api-token?password=$DV_USER_PASSWORD" - Roles ~~~~~ diff --git a/doc/sphinx-guides/source/installation/config.rst b/doc/sphinx-guides/source/installation/config.rst index 31bbed45c07..d42bab467a4 100644 --- a/doc/sphinx-guides/source/installation/config.rst +++ b/doc/sphinx-guides/source/installation/config.rst @@ -1204,3 +1204,10 @@ You can replace the default dataset metadata fields that are displayed above fil ``curl http://localhost:8080/api/admin/settings/:CustomDatasetSummaryFields -X PUT -d 'producer,subtitle,alternativeTitle'`` You have to put the datasetFieldType name attribute in the :CustomDatasetSummaryFields setting for this to work. + +:AllowApiTokenLookupViaApi +++++++++++++++++++++++++++ + +Dataverse 4.8.1 and below allowed API Token lookup via API but for better security this has been disabled by default. Set this to true if you really want the old behavior. + +``curl -X PUT -d 'true' http://localhost:8080/api/admin/settings/:AllowApiTokenLookupViaApi`` diff --git a/src/main/java/edu/harvard/iq/dataverse/api/BuiltinUsers.java b/src/main/java/edu/harvard/iq/dataverse/api/BuiltinUsers.java index 233d57e1b45..633623719a4 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/BuiltinUsers.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/BuiltinUsers.java @@ -10,6 +10,7 @@ import edu.harvard.iq.dataverse.authorization.providers.builtin.PasswordEncryption; import edu.harvard.iq.dataverse.authorization.users.ApiToken; import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; +import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import java.sql.Timestamp; import java.util.Calendar; import java.util.logging.Level; @@ -53,6 +54,14 @@ public class BuiltinUsers extends AbstractApiBean { @GET @Path("{username}/api-token") public Response getApiToken( @PathParam("username") String username, @QueryParam("password") String password ) { + boolean disabled = true; + boolean lookupAllowed = settingsSvc.isTrueForKey(SettingsServiceBean.Key.AllowApiTokenLookupViaApi, false); + if (lookupAllowed) { + disabled = false; + } + if (disabled) { + return error(Status.FORBIDDEN, "This API endpoint has been disabled."); + } BuiltinUser u = null; if (retrievingApiTokenViaEmailEnabled) { u = builtinUserSvc.findByUsernameOrEmail(username); diff --git a/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java index 29376f04d97..94024bf5949 100644 --- a/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java @@ -32,6 +32,7 @@ public class SettingsServiceBean { * So there. */ public enum Key { + AllowApiTokenLookupViaApi, /** * Ordered, comma-separated list of custom fields to show above the fold * on dataset page such as "data_type,sample,pdb" diff --git a/src/test/java/edu/harvard/iq/dataverse/api/BuiltinUsersIT.java b/src/test/java/edu/harvard/iq/dataverse/api/BuiltinUsersIT.java index 43b5219195e..99a7b395379 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/BuiltinUsersIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/BuiltinUsersIT.java @@ -17,6 +17,7 @@ import javax.json.Json; import javax.json.JsonObjectBuilder; import static javax.ws.rs.core.Response.Status.OK; +import static javax.ws.rs.core.Response.Status.FORBIDDEN; import static junit.framework.Assert.assertEquals; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.Matchers.startsWith; @@ -37,6 +38,11 @@ public class BuiltinUsersIT { @BeforeClass public static void setUp() { RestAssured.baseURI = UtilIT.getRestAssuredBaseUri(); + + Response removeIdentifierGenerationStyle = UtilIT.deleteSetting(SettingsServiceBean.Key.AllowApiTokenLookupViaApi); + removeIdentifierGenerationStyle.then().assertThat() + .statusCode(200); + } @Test @@ -171,6 +177,15 @@ public void testLogin() { String createdToken = createdUser.getString("data.apiToken"); logger.info(createdToken); + Response getApiTokenShouldFail = getApiTokenUsingUsername(usernameToCreate, usernameToCreate); + getApiTokenShouldFail.then().assertThat() + .body("message", equalTo("This API endpoint has been disabled.")) + .statusCode(FORBIDDEN.getStatusCode()); + + Response setAllowApiTokenLookupViaApi = UtilIT.setSetting(SettingsServiceBean.Key.AllowApiTokenLookupViaApi, "true"); + setAllowApiTokenLookupViaApi.then().assertThat() + .statusCode(OK.getStatusCode()); + Response getApiTokenUsingUsername = getApiTokenUsingUsername(usernameToCreate, usernameToCreate); getApiTokenUsingUsername.prettyPrint(); assertEquals(200, getApiTokenUsingUsername.getStatusCode()); @@ -189,6 +204,10 @@ public void testLogin() { assertEquals(createdToken, retrievedTokenUsingEmail); } + Response removeIdentifierGenerationStyle = UtilIT.deleteSetting(SettingsServiceBean.Key.AllowApiTokenLookupViaApi); + removeIdentifierGenerationStyle.then().assertThat() + .statusCode(200); + } @Test