Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GDCC/7715 Signed Urls for external tools #9001

Merged
Show file tree
Hide file tree
Changes from 67 commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
07b34b0
initial commit
rtreacy Jul 29, 2021
c017fd3
Merge branch 'develop' into 7715-signed-urls-for-external-tools
rtreacy Mar 11, 2022
4c0fce0
rename getQueryParametersForUrl to handleRequest
rtreacy Mar 16, 2022
36fb985
rename getQueryParametersForUrl to handleRequest
rtreacy Mar 16, 2022
b90216f
add UrlSignerUtil.java
rtreacy Mar 16, 2022
fecd8a1
Merge branch 'develop' into 7715-signed-urls-for-external-tools
rtreacy Mar 16, 2022
a7d1767
Merge branch '7715-signed-urls-for-external-tools' of github.com:IQSS…
rtreacy Mar 16, 2022
cb418a7
Merge branch 'develop' into 7715-signed-urls-for-external-tools
rtreacy Apr 8, 2022
ac23437
add signed Url to header and use POST for external tools, in particul…
rtreacy May 2, 2022
7e82009
use signedUrl for getting authenticated user. add allowedUrls field t…
rtreacy Jun 8, 2022
7c9fa06
fix for validation method/comments
qqmyers Jun 9, 2022
39180cc
JSON API call to request signedUrl
qqmyers Jun 9, 2022
55fafa5
json read object/array from string methods from other branches
qqmyers Jun 9, 2022
01973ff
Merge pull request #8788 from GlobalDataverseCommunityConsortium/7715…
rtreacy Jun 9, 2022
881e3db
define/use an additional secret key
qqmyers Jun 14, 2022
208ab95
refactor to allow URL token substitution outside tools framework
qqmyers Jun 21, 2022
8c2f950
Merge pull request #8802 from GlobalDataverseCommunityConsortium/7715…
rtreacy Jun 23, 2022
0c22b18
sending a list of allowed api calls to DPCreator
rtreacy Jul 15, 2022
1b31e6c
tweak json read/write, getString, cleanup, logging
qqmyers Jul 20, 2022
2c90139
Merge remote-tracking branch 'IQSS/develop' into 7715-signed-urls-for…
qqmyers Jul 20, 2022
66355b0
Merge pull request #8850 from GlobalDataverseCommunityConsortium/7715…
rtreacy Jul 21, 2022
d4189f3
add signer tests, flip param order so sign/validate match, fix val bug
qqmyers Aug 4, 2022
6331bec
Merge pull request #8896 from GlobalDataverseCommunityConsortium/7715…
rtreacy Aug 5, 2022
22cdaaf
passes existing query params an signed urls in POST body as json
Sep 11, 2022
1039457
Merge remote-tracking branch 'IQSS/develop' into
qqmyers Sep 23, 2022
4af2c05
support signedURL in findUser
qqmyers Sep 27, 2022
0cd3e4a
update/fix requestSignedURL
qqmyers Sep 27, 2022
1095f96
reduce duplication
qqmyers Sep 27, 2022
01fb249
cleanup, add hasToken call
qqmyers Sep 27, 2022
12d98fa
remove ; in jvm option name
qqmyers Sep 27, 2022
2287438
remove unnecessary 'apis' json object from manifest structure
qqmyers Sep 27, 2022
1f82b19
refactor, remove extra user variable
qqmyers Sep 27, 2022
a5ca4e2
cleanup, note :me works in UI
qqmyers Sep 27, 2022
a413a13
add tool callback methods for dataset and datafile
qqmyers Sep 27, 2022
2ed2414
add flyway script
qqmyers Sep 27, 2022
6b9d69f
uses JsonObjectBuilder, elininating some string building that was messy
rtreacy Sep 26, 2022
17eec51
Merge remote-tracking branch 'IQSS/develop' into 7715-signed-urls-for…
qqmyers Sep 27, 2022
b098ba6
use httpMethod in toolParams and allowedapicalls
qqmyers Sep 27, 2022
48b2e04
doc updates
qqmyers Sep 27, 2022
2eb90f1
use java.util.Base64
qqmyers Sep 27, 2022
86f910d
release note
qqmyers Sep 27, 2022
6a9ab48
Tests
qqmyers Sep 27, 2022
4da5be0
remove test logging
qqmyers Sep 27, 2022
724f88d
remove toolContext - wasn't set for dataset tools, isn't needed
qqmyers Sep 28, 2022
88bc73c
handle unsigned urls
qqmyers Sep 28, 2022
bcbc7e3
Merge remote-tracking branch 'IQSS/develop' into 7715-signed-urls-for…
qqmyers Oct 5, 2022
63c175d
add sleepForReindex call
qqmyers Oct 5, 2022
d3bc180
and remove old sleep
qqmyers Oct 5, 2022
ceb3968
change sleep to be in seconds
qqmyers Oct 5, 2022
8fb50a8
change other use of sleepForReindex
qqmyers Oct 5, 2022
b3cd411
Merge remote-tracking branch 'IQSS/develop' into 7715-signed-urls-for…
qqmyers Oct 27, 2022
51b5dc2
Merge remote-tracking branch 'IQSS/develop' into 7715-signed-urls-for…
qqmyers Nov 7, 2022
022955d
fix typos
qqmyers Nov 10, 2022
b357cb2
add SITE_URL for running single tests
qqmyers Nov 10, 2022
559e5c5
Merge branch 'develop' into 7715-signed-urls-for-external-tools #7715
pdurbin Nov 10, 2022
d59fbfc
rename sql script post 5.12.1 release #7715
pdurbin Nov 10, 2022
de8386b
typos and minor wording and formatting fixes #7715
pdurbin Nov 10, 2022
5c5468c
use same term as in ext tools
qqmyers Nov 10, 2022
673987b
doc for requestSignedUrl
qqmyers Nov 10, 2022
7ffec36
Merge branch '7715-signed-urls-for-external-tools' of
qqmyers Nov 10, 2022
bf87542
Updates per reviews
qqmyers Nov 10, 2022
cda90ad
Changes per request.
qqmyers Nov 15, 2022
dbca546
Merge remote-tracking branch 'IQSS/develop' into 7715-signed-urls-for…
qqmyers Nov 15, 2022
d1a5680
feat: make API signing secret a JvmSetting #7715
poikilotherm Nov 16, 2022
79f4c85
doc(signed-url): add configuration documentation #7715
poikilotherm Nov 16, 2022
70e350f
Merge pull request #31 from poikilotherm/7715-jvmsetting
qqmyers Nov 17, 2022
5445a85
wordsmithing
qqmyers Nov 17, 2022
fd55f20
Merge remote-tracking branch 'IQSS/develop' into 7715-signed-urls-for…
qqmyers Nov 21, 2022
ffc5539
update flyway numbering
qqmyers Nov 21, 2022
a5b748f
Merge branch '7715-signed-urls-for-external-tools' of https://github.…
qqmyers Nov 21, 2022
fbf7190
Improved error handling per QA
qqmyers Nov 23, 2022
398fd48
Improve error handling
qqmyers Nov 28, 2022
77496b8
add content-type in requestSignedUrl
qqmyers Nov 28, 2022
d7ecb3e
fix example json param
qqmyers Nov 28, 2022
0c8216a
unwrap wrapped response
qqmyers Nov 28, 2022
590ee40
fix for api key param
qqmyers Nov 28, 2022
32b9a8c
Merge remote-tracking branch 'IQSS/develop' into
qqmyers Nov 30, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions doc/release-notes/7715-signed-urls-for-external-tools.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Improved Security for External Tools

This release adds support for configuring external tools to use signed URLs to access the Dataverse API. This eliminates the need for tools to have access to the user's apiToken in order to access draft or restricted datasets and datafiles. Signed URLS can be transferred via POST or via a callback when triggering a tool via GET.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Tool Type Scope Description
Data Explorer explore file A GUI which lists the variables in a tabular data file allowing searching, charting and cross tabulation analysis. See the README.md file at https://github.com/scholarsportal/dataverse-data-explorer-v2 for the instructions on adding Data Explorer to your Dataverse.
Whole Tale explore dataset A platform for the creation of reproducible research packages that allows users to launch containerized interactive analysis environments based on popular tools such as Jupyter and RStudio. Using this integration, Dataverse users can launch Jupyter and RStudio environments to analyze published datasets. For more information, see the `Whole Tale User Guide <https://wholetale.readthedocs.io/en/stable/users_guide/integration.html>`_.
File Previewers explore file A set of tools that display the content of files - including audio, html, `Hypothes.is <https://hypothes.is/>`_ annotations, images, PDF, text, video, tabular data, spreadsheets, and GeoJSON - allowing them to be viewed without downloading. The previewers can be run directly from github.io, so the only required step is using the Dataverse API to register the ones you want to use. Documentation, including how to optionally brand the previewers, and an invitation to contribute through github are in the README.md file. Initial development was led by the Qualitative Data Repository and the spreasdheet previewer was added by the Social Sciences and Humanities Open Cloud (SSHOC) project. https://github.com/gdcc/dataverse-previewers
File Previewers explore file A set of tools that display the content of files - including audio, html, `Hypothes.is <https://hypothes.is/>`_ annotations, images, PDF, text, video, tabular data, spreadsheets, GeoJSON, and ZipFiles - allowing them to be viewed without downloading the file. The previewers can be run directly from github.io, so the only required step is using the Dataverse API to register the ones you want to use. Documentation, including how to optionally brand the previewers, and an invitation to contribute through github are in the README.md file. Initial development was led by the Qualitative Data Repository and the spreasdheet previewer was added by the Social Sciences and Humanities Open Cloud (SSHOC) project. https://github.com/gdcc/dataverse-previewers
Data Curation Tool configure file A GUI for curating data by adding labels, groups, weights and other details to assist with informed reuse. See the README.md file at https://github.com/scholarsportal/Dataverse-Data-Curation-Tool for the installation instructions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,16 @@
"PID": "{datasetPid}"
},
{
"apiToken": "{apiToken}"
"locale":"{localeCode}"
}
]
],
"allowedApiCalls": [
{
"name":"retrieveDatasetJson",
"httpMethod":"GET",
"urlTemplate":"/api/v1/datasets/{datasetId}",
"timeOut":10
}
]
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"displayName": "Fabulous File Tool",
"description": "Fabulous Fun for Files!",
"description": "A non-existent tool that is fabulous fun for files!",
"toolName": "fabulous",
"scope": "file",
"types": [
Expand All @@ -9,13 +9,25 @@
],
"toolUrl": "https://fabulousfiletool.com",
"contentType": "text/tab-separated-values",
"httpMethod":"GET",
"toolParameters": {
"queryParameters": [
{
"fileid": "{fileId}"
},
{
"key": "{apiToken}"
"datasetPid": "{datasetPid}"
},
{
"locale":"{localeCode}"
}
],
"allowedApiCalls": [
{
"name":"retrieveDataFile",
"httpMethod":"GET",
"urlTemplate":"/api/v1/access/datafile/{fileId}",
"timeOut":270
}
]
}
Expand Down
33 changes: 32 additions & 1 deletion doc/sphinx-guides/source/api/external-tools.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ Terminology

contentType File level tools operate on a specific **file type** (content type or MIME type such as "application/pdf") and this must be specified. Dataset level tools do not use contentType.

toolParameters **Query parameters** are supported and described below.
toolParameters **httpMethod**, **queryParameters**, and **allowedApiCalls** are supported and described below.

httpMethod Either ``GET`` or ``POST``.

queryParameters **Key/value combinations** that can be appended to the toolUrl. For example, once substitution takes place (described below) the user may be redirected to ``https://fabulousfiletool.com?fileId=42&siteUrl=http://demo.dataverse.org``.

Expand All @@ -102,6 +104,16 @@ Terminology

reserved words A **set of strings surrounded by curly braces** such as ``{fileId}`` or ``{datasetId}`` that will be inserted into query parameters. See the table below for a complete list.

allowedApiCalls An array of objects defining callbacks the tool is allowed to make to the Dataverse API. If the dataset or file being accessed is not public, the callback URLs will be signed to allow the tool access for a defined time.

allowedApiCalls name A name the tool will use to identify this callback URL such as ``retrieveDataFile``.

allowedApiCalls urlTemplate The relative URL for the callback using reserved words to indicate where values should by dynamically substituted such as ``/api/v1/datasets/{datasetId}``.

allowedApiCalls httpMethod Which HTTP method the specified callback uses such as ``GET`` or ``POST``.

qqmyers marked this conversation as resolved.
Show resolved Hide resolved
allowedApiCalls timeOut For non-public datasets and datafiles, how many minutes the signed URLs given to the tool should be valid for. Must be an integer.

toolName A **name** of an external tool that is used to differentiate between external tools and also used in bundle.properties for localization in the Dataverse installation web interface. For example, the toolName for Data Explorer is ``explorer``. For the Data Curation Tool the toolName is ``dct``. This is an optional parameter in the manifest JSON file.
=========================== ==========

Expand Down Expand Up @@ -131,6 +143,25 @@ Reserved Words
``{localeCode}`` optional The code for the language ("en" for English, "fr" for French, etc.) that user has selected from the language toggle in a Dataverse installation. See also :ref:`i18n`.
=========================== ========== ===========

.. _api-exttools-auth:

Authorization Options
+++++++++++++++++++++

When called for datasets or data files that are not public (i.e. in a draft dataset or for a restricted file), external tools are allowed access via the user's credentials. This is accomplished by one of two mechanisms:

* Signed URLs (more secure, recommended)

- Configured via the ``allowedApiCalls`` section of the manifest. The tool will be provided with signed URLs allowing the specified access to the given dataset or datafile for the specified amount of time. The tool will not be able to access any other datasets or files the user may have access to and will not be able to make calls other than those specified.
- For tools invoked via a GET call, Dataverse will include a callback query parameter with a Base64 encoded value. The decoded value is a signed URL that can be called to retrieve a JSON response containing all of the queryParameters and allowedApiCalls specified in the manfiest.
- For tools invoked via POST, Dataverse will send a JSON body including the requested queryParameters and allowedApiCalls. Dataverse expects the response to the POST to indicate a redirect which Dataverse will use to open the tool.

* API Token (deprecated, less secure, not recommended)

- Configured via the ``queryParameters`` by including an ``{apiToken}`` value. When this is present Dataverse will send the user's apiToken to the tool. With the user's API token, the tool can perform any action via the Dataverse API that the user could. External tools configured via this method should be assessed for their trustworthiness.
- For tools invoked via GET, this will be done via a query parameter in the request URL which could be cached in the browser's history. Dataverse expects the response to the POST to indicate a redirect which Dataverse will use to open the tool.
- For tools invoked via POST, Dataverse will send a JSON body including the apiToken.

Internationalization of Your External Tool
++++++++++++++++++++++++++++++++++++++++++

Expand Down
67 changes: 65 additions & 2 deletions doc/sphinx-guides/source/api/native-api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2029,6 +2029,24 @@ Archiving is an optional feature that may be configured for a Dataverse installa

curl -H "X-Dataverse-key: $API_TOKEN" -X DELETE "$SERVER_URL/api/datasets/:persistentId/$VERSION/archivalStatus?persistentId=$PERSISTENT_IDENTIFIER"

Get External Tool Parameters
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This API call is intended as a callback that can be used by :doc:`/installation/external-tools` to retrieve signed Urls necessary for their interaction with Dataverse.
It can be called directly as well.

The response is a JSON object described in the :doc:`/api/external-tools` section of the API guide.

.. code-block:: bash

export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
export SERVER_URL=https://demo.dataverse.org
export PERSISTENT_IDENTIFIER=doi:10.5072/FK2/7U7YBV
export VERSION=1.0
export TOOL_ID=1


curl -H "X-Dataverse-key: $API_TOKEN" -H "Accept:application/json" "$SERVER_URL/api/datasets/:persistentId/versions/$VERSION/toolparams/$TOOL_ID?persistentId=$PERSISTENT_IDENTIFIER"

Files
-----
Expand Down Expand Up @@ -2689,6 +2707,24 @@ Note the optional "limit" parameter. Without it, the API will attempt to populat

By default, the admin API calls are blocked and can only be called from localhost. See more details in :ref:`:BlockedApiEndpoints <:BlockedApiEndpoints>` and :ref:`:BlockedApiPolicy <:BlockedApiPolicy>` settings in :doc:`/installation/config`.

Get External Tool Parameters
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This API call is intended as a callback that can be used by :doc:`/installation/external-tools` to retrieve signed Urls necessary for their interaction with Dataverse.
It can be called directly as well.

The response is a JSON object described in the :doc:`/api/external-tools` section of the API guide.

.. code-block:: bash

export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
export SERVER_URL=https://demo.dataverse.org
export FILE_ID=3
export FILEMETADATA_ID=1
export TOOL_ID=1

curl -H "X-Dataverse-key: $API_TOKEN" -H "Accept:application/json" "$SERVER_URL/api/files/$FILE_ID/metadata/$FILEMETADATA_ID/toolparams/$TOOL_ID

Users Token Management
----------------------

Expand Down Expand Up @@ -4070,6 +4106,33 @@ The fully expanded example above (without environment variables) looks like this
.. code-block:: bash

curl -X DELETE https://demo.dataverse.org/api/admin/template/24

.. _api-native-signed-url:



Request Signed URL
~~~~~~~~~~~~~~~~~~

Dataverse has the ability to create signed URLs for it's API calls.
A signature, which is valid only for the specific API call and only for a specified duration, allows the call to proceed with the authentication of the specified user.
It is intended as an alternative to the use of an API key (which is valid for a long time period and can be used with any API call).
Signed URLs were developed to support External Tools but may be useful in other scenarios where Dataverse or a third-party tool needs to delegate limited access to another user or tool.
This API call allows a Dataverse superUser to generate a signed URL for such scenarios.
The JSON input parameter required is an object with the following keys:

- ``url`` - the exact URL to sign, including api version number and all query parameters
- ``timeOut`` - how long in minutes the signature should be valid for, default is 10 minutes
- ``httpMethod`` - which HTTP method is required, default is GET
- ``user`` - the user identifier for the account associated with this signature, the default is the superuser making the call. The API call will succeed/fail based on whether the specified user has the required permissions.

A curl example using allowing access to a dataset's metadata

.. code-block:: bash

export SERVER_URL=https://demo.dataverse.org
export API_KEY=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
export JSON={"url":"https://demo.dataverse.org/api/v1/datasets/:persistentId/?persistentId=doi:10.5072/FK2/J8SJZB","timeOut":5,"user":"alberteinstein"}

curl -H 'X-Dataverse-key:$API_KEY' -d $JSON $SERVER_URL/api/admin/requestSignedUrl

Please see :ref:`dataverse.api.signature-secret` for the configuration option to add a shared secret, enabling extra
security.
40 changes: 38 additions & 2 deletions doc/sphinx-guides/source/installation/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -580,8 +580,7 @@ Optionally, you may provide static credentials for each S3 storage using MicroPr
- ``dataverse.files.<id>.access-key`` for this storage's "access key ID"
- ``dataverse.files.<id>.secret-key`` for this storage's "secret access key"

You may provide the values for these via any of the
`supported config sources <https://docs.payara.fish/community/docs/documentation/microprofile/config/README.html>`_.
You may provide the values for these via any `supported MicroProfile Config API source`_.

**WARNING:**

Expand Down Expand Up @@ -1670,6 +1669,39 @@ This setting is useful in cases such as running your Dataverse installation behi
"HTTP_VIA",
"REMOTE_ADDR"


.. _dataverse.api.signature-secret:

dataverse.api.signature-secret
++++++++++++++++++++++++++++++

Context: Dataverse has the ability to create "Signed URLs" for it's API calls. Using a signed URLs is more secure than
providing API tokens, which are long-lived and give the holder all of the permissions of the user. In contrast, signed URLs
are time limited and only allow the action of the API call in the URL. See :ref:`api-exttools-auth` and
:ref:`api-native-signed-url` for more details.

The key used to sign a URL is created from the API token of the creating user plus a signature-secret provided by an administrator.
**Using a signature-secret is highly recommended.** This setting defaults to an empty string. Using a non-empty
signature-secret makes it impossible for someone who knows an API token from forging signed URLs and provides extra security by
making the overall signing key longer.

Since the signature-secret is sensitive, you should treat it like a password. Here is an example how to set your shared secret
with the secure method "password alias":

.. code-block:: shell

echo "AS_ADMIN_ALIASPASSWORD=change-me-super-secret" > /tmp/password.txt
asadmin create-password-alias --passwordfile /tmp/password.txt dataverse.api.signature-secret
rm /tmp/password.txt

Can also be set via any `supported MicroProfile Config API source`_, e.g. the environment variable
``DATAVERSE_API_SIGNATURE_SECRET``.

**WARNING:** For security, do not use the sources "environment variable" or "system property" (JVM option) in a
production context! Rely on password alias, secrets directory or cloud based sources instead!



.. _:ApplicationServerSettings:

Application Server Settings
Expand Down Expand Up @@ -3067,3 +3099,7 @@ The interval in seconds between Dataverse calls to Globus to check on upload pro
+++++++++++++++++++++++++

A true/false option to add a Globus transfer option to the file download menu which is not yet fully supported in the dataverse-globus app. See :ref:`globus-support` for details.



.. _supported MicroProfile Config API source: https://docs.payara.fish/community/docs/Technical%20Documentation/MicroProfile/Config/Overview.html
30 changes: 29 additions & 1 deletion src/main/java/edu/harvard/iq/dataverse/api/AbstractApiBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,11 @@
import edu.harvard.iq.dataverse.privateurl.PrivateUrlServiceBean;
import edu.harvard.iq.dataverse.locality.StorageSiteServiceBean;
import edu.harvard.iq.dataverse.search.savedsearch.SavedSearchServiceBean;
import edu.harvard.iq.dataverse.settings.JvmSettings;
import edu.harvard.iq.dataverse.settings.SettingsServiceBean;
import edu.harvard.iq.dataverse.util.BundleUtil;
import edu.harvard.iq.dataverse.util.SystemConfig;
import edu.harvard.iq.dataverse.util.UrlSignerUtil;
import edu.harvard.iq.dataverse.util.json.JsonParser;
import edu.harvard.iq.dataverse.util.json.NullSafeJsonBuilder;
import edu.harvard.iq.dataverse.validation.PasswordValidatorServiceBean;
Expand Down Expand Up @@ -362,7 +364,7 @@ protected AuthenticatedUser findUserByApiToken( String apiKey ) {
protected User findUserOrDie() throws WrappedResponse {
final String requestApiKey = getRequestApiKey();
final String requestWFKey = getRequestWorkflowInvocationID();
if (requestApiKey == null && requestWFKey == null) {
if (requestApiKey == null && requestWFKey == null && getRequestParameter(UrlSignerUtil.SIGNED_URL_TOKEN)==null) {
return GuestUser.get();
}
PrivateUrlUser privateUrlUser = privateUrlSvc.getPrivateUrlUserFromToken(requestApiKey);
Expand Down Expand Up @@ -419,10 +421,36 @@ private AuthenticatedUser findAuthenticatedUserOrDie( String key, String wfid )
} else {
throw new WrappedResponse(badWFKey(wfid));
}
} else if (getRequestParameter(UrlSignerUtil.SIGNED_URL_TOKEN) != null) {
AuthenticatedUser authUser = getAuthenticatedUserFromSignedUrl();
if (authUser != null) {
return authUser;
}
}
//Just send info about the apiKey - workflow users will learn about invocationId elsewhere
throw new WrappedResponse(badApiKey(null));
}

private AuthenticatedUser getAuthenticatedUserFromSignedUrl() {
AuthenticatedUser authUser = null;
// The signedUrl contains a param telling which user this is supposed to be for.
// We don't trust this. So we lookup that user, and get their API key, and use
// that as a secret in validating the signedURL. If the signature can't be
// validated with their key, the user (or their API key) has been changed and
// we reject the request.
// ToDo - add null checks/ verify that calling methods catch things.
String user = httpRequest.getParameter("user");
AuthenticatedUser targetUser = authSvc.getAuthenticatedUser(user);
String key = JvmSettings.API_SIGNING_SECRET.lookupOptional().orElse("")
+ authSvc.findApiTokenByUser(targetUser).getTokenString();
String signedUrl = httpRequest.getRequestURL().toString() + "?" + httpRequest.getQueryString();
String method = httpRequest.getMethod();
boolean validated = UrlSignerUtil.isValidUrl(signedUrl, user, method, key);
if (validated) {
authUser = targetUser;
}
return authUser;
}

protected Dataverse findDataverseOrDie( String dvIdtf ) throws WrappedResponse {
Dataverse dv = findDataverse(dvIdtf);
Expand Down
Loading