Skip to content

Commit

Permalink
Merge pull request #1303 from research-software-directory/1288-integr…
Browse files Browse the repository at this point in the history
…ating-third-party-services

Add support for third-party services
  • Loading branch information
cmeessen authored Oct 7, 2024
2 parents ee47d07 + c0e9d0c commit c7b0320
Show file tree
Hide file tree
Showing 39 changed files with 565 additions and 70 deletions.
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ POSTGREST_URL_EXTERNAL=http://localhost/api/v1
# .env.local: http://localhost/auth, .env: http://auth:7000
RSD_AUTH_URL=http://auth:7000

# RSD Reverse Proxy URL
# consumed by services: frontend
# .env.local: http://localhost, .env: http://nginx
RSD_REVERSE_PROXY_URL=http://nginx

# consumed by services: authentication
# If set to "dev", the first user to log in will become admin.
# Any other value doesn't activate this feature (and doesn't do anything).
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
// SPDX-FileCopyrightText: 2022 - 2023 Ewan Cahen (Netherlands eScience Center) <[email protected]>
// SPDX-FileCopyrightText: 2022 - 2023 Netherlands eScience Center
// SPDX-FileCopyrightText: 2024 Christian Meeßen (GFZ) <[email protected]>
// SPDX-FileCopyrightText: 2024 Helmholtz Centre Potsdam - GFZ German Research Centre for Geosciences
//
// SPDX-License-Identifier: Apache-2.0

package nl.esciencecenter.rsd.authentication;

import java.util.List;
import java.util.Map;
import java.util.UUID;

public record AccountInfo(
UUID account,
String name,
boolean isAdmin
boolean isAdmin,
Map<String, List<String>> data
) {
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// SPDX-FileCopyrightText: 2022 - 2024 Ewan Cahen (Netherlands eScience Center) <[email protected]>
// SPDX-FileCopyrightText: 2022 - 2024 Netherlands eScience Center
// SPDX-FileCopyrightText: 2024 Christian Meeßen (GFZ) <[email protected]>
// SPDX-FileCopyrightText: 2024 Helmholtz Centre Potsdam - GFZ German Research Centre for Geosciences
//
// SPDX-License-Identifier: Apache-2.0

Expand All @@ -14,7 +16,9 @@
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

Expand Down Expand Up @@ -42,7 +46,8 @@ public OpenIdInfo openidInfo() throws IOException, InterruptedException {
String subject = idJwt.getSubject();
String email = idJwt.getClaim("email").asString();
String name = idJwt.getClaim("name").asString();
return new OpenIdInfo(subject, name, email, Config.azureOrganisation());
Map<String, List<String>> emptyData = Collections.emptyMap();
return new OpenIdInfo(subject, name, email, Config.azureOrganisation(), emptyData);
}

private Map<String, String> createForm() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
import java.net.http.HttpResponse.BodyHandlers;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

Expand Down Expand Up @@ -206,11 +209,20 @@ public OpenIdInfo openidInfo() throws IOException, InterruptedException {
}
String organisation = getOrganisationFromEntitlements(entitlements);

List<String> eduPersonEntitlements = new ArrayList<>();
for (int i=0; i<entitlements.size(); i++) {
eduPersonEntitlements.add(entitlements.get(i).toString());
}

Map<String, List<String>> data = new HashMap<>();
data.put("eduPersonEntitlements", eduPersonEntitlements);

return new OpenIdInfo(
userInfo.getSubject().toString(),
userInfo.getName(),
userInfo.getEmailAddress(),
organisation
organisation,
data
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// SPDX-FileCopyrightText: 2022 - 2023 Netherlands eScience Center
// SPDX-FileCopyrightText: 2022 Dusan Mijatovic (dv4all)
// SPDX-FileCopyrightText: 2022 dv4all
// SPDX-FileCopyrightText: 2024 Christian Meeßen (GFZ) <[email protected]>
// SPDX-FileCopyrightText: 2024 Helmholtz Centre Potsdam - GFZ German Research Centre for Geosciences
//
// SPDX-License-Identifier: Apache-2.0

Expand Down Expand Up @@ -34,10 +36,12 @@ String createUserJwt(AccountInfo accountInfo) {
.withClaim("role", accountInfo.isAdmin() ? "rsd_admin" : "rsd_user")
.withClaim("account", accountInfo.account().toString())
.withClaim("name", accountInfo.name())
.withClaim("data", accountInfo.data())
.withExpiresAt(new Date(System.currentTimeMillis() + ONE_HOUR_IN_MILLISECONDS))
.sign(signingAlgorithm);
}


String createAdminJwt() {
return JWT.create()
.withClaim("iss", "rsd_auth")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
import io.javalin.http.Context;

import java.util.Base64;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.UUID;

public class Main {
Expand Down Expand Up @@ -98,7 +101,8 @@ public static void main(String[] args) {
String name = sub;
String email = sub + "@example.com";
String organisation = "Example organisation";
OpenIdInfo localInfo = new OpenIdInfo(sub, name, email, organisation);
Map<String, List<String>> emptyData = Collections.emptyMap();
OpenIdInfo localInfo = new OpenIdInfo(sub, name, email, organisation, emptyData);

AccountInfo accountInfo = new PostgrestAccount().account(localInfo, OpenidProvider.local);
createAndSetToken(ctx, accountInfo);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
// SPDX-FileCopyrightText: 2022 Ewan Cahen (Netherlands eScience Center) <[email protected]>
// SPDX-FileCopyrightText: 2022 Netherlands eScience Center
// SPDX-FileCopyrightText: 2024 Christian Meeßen (GFZ) <[email protected]>
// SPDX-FileCopyrightText: 2024 Helmholtz Centre Potsdam - GFZ German Research Centre for Geosciences
//
// SPDX-License-Identifier: Apache-2.0

package nl.esciencecenter.rsd.authentication;

public record OpenIdInfo(String sub, String name, String email, String organisation) {
import java.util.List;
import java.util.Map;

public record OpenIdInfo(
String sub,
String name,
String email,
String organisation,
Map<String, List<String>> data
) {
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// SPDX-FileCopyrightText: 2022 - 2024 Ewan Cahen (Netherlands eScience Center) <[email protected]>
// SPDX-FileCopyrightText: 2022 - 2024 Netherlands eScience Center
// SPDX-FileCopyrightText: 2024 Christian Meeßen (GFZ) <[email protected]>
// SPDX-FileCopyrightText: 2024 Helmholtz Centre Potsdam - GFZ German Research Centre for Geosciences
//
// SPDX-License-Identifier: Apache-2.0

Expand All @@ -14,7 +16,9 @@
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

Expand Down Expand Up @@ -44,7 +48,8 @@ public OpenIdInfo openidInfo() throws IOException, InterruptedException {
else if (familyName != null) name = familyName;
else if (givenName != null) name = givenName;
}
return new OpenIdInfo(subject, name, null, null);
Map<String, List<String>> emptyData = Collections.emptyMap();
return new OpenIdInfo(subject, name, null, null, emptyData);
}

private Map<String, String> createForm() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// SPDX-FileCopyrightText: 2022 - 2024 Ewan Cahen (Netherlands eScience Center) <[email protected]>
// SPDX-FileCopyrightText: 2022 - 2024 Netherlands eScience Center
// SPDX-FileCopyrightText: 2024 Christian Meeßen (GFZ) <[email protected]>
// SPDX-FileCopyrightText: 2024 Helmholtz Centre Potsdam - GFZ German Research Centre for Geosciences
//
// SPDX-License-Identifier: Apache-2.0

Expand Down Expand Up @@ -64,7 +66,7 @@ else if (accountsWithSub.size() == 1) {
isAdmin = true;
}

return new AccountInfo(account, name, isAdmin);
return new AccountInfo(account, name, isAdmin, openIdInfo.data());
}
// The login credentials do no exist yet, create a new account and return it.
else {
Expand All @@ -78,7 +80,7 @@ else if (accountsWithSub.size() == 1) {

boolean isAdmin = createAdminIfDevAndNoAdminsExist(backendUri, token, accountId);

return new AccountInfo(accountId, openIdInfo.name(), isAdmin);
return new AccountInfo(accountId, openIdInfo.name(), isAdmin, openIdInfo.data());
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// SPDX-FileCopyrightText: 2021 - 2024 Ewan Cahen (Netherlands eScience Center) <[email protected]>
// SPDX-FileCopyrightText: 2021 - 2024 Netherlands eScience Center
// SPDX-FileCopyrightText: 2022 - 2024 Helmholtz Centre Potsdam - GFZ German Research Centre for Geosciences
// SPDX-FileCopyrightText: 2022 Dusan Mijatovic (dv4all)
// SPDX-FileCopyrightText: 2022 Helmholtz Centre Potsdam - GFZ German Research Centre for Geosciences
// SPDX-FileCopyrightText: 2022 Matthias Rüster (GFZ) <[email protected]>
// SPDX-FileCopyrightText: 2022 dv4all
// SPDX-FileCopyrightText: 2024 Christian Meeßen (GFZ) <[email protected]>
//
// SPDX-License-Identifier: Apache-2.0

Expand All @@ -18,7 +19,9 @@
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

Expand All @@ -43,7 +46,8 @@ public OpenIdInfo openidInfo() throws IOException, InterruptedException {
String name = idJwt.getClaim("name").asString();
String email = idJwt.getClaim("email").asString();
String organisation = idJwt.getClaim("schac_home_organization").asString();
return new OpenIdInfo(subject, name, email, organisation);
Map<String, List<String>> emptyData = Collections.emptyMap();
return new OpenIdInfo(subject, name, email, organisation, emptyData);
}

private Map<String, String> createForm() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,17 @@
import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.Collections;
import java.util.List;
import java.util.Map;

class MainTest {
Map<String, List<String>> emptyData = Collections.emptyMap();
OpenIdInfo userinfo = new OpenIdInfo(
"12345", "User Name", "[email protected]", "Example User"
"12345", "User Name", "[email protected]", "Example User", emptyData
);
OpenIdInfo userinfoNullOrganisation = new OpenIdInfo(
"12345", "User Name", "[email protected]", null
"12345", "User Name", "[email protected]", null, emptyData
);
static MockedStatic<Config> utilities;

Expand Down
4 changes: 3 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ services:
- RSD_AUTH_URL
- RSD_AUTH_PROVIDERS
- RSD_AUTH_COUPLE_PROVIDERS
- RSD_REVERSE_PROXY_URL
- MATOMO_URL
- MATOMO_ID
- SURFCONEXT_CLIENT_ID
Expand Down Expand Up @@ -149,7 +150,8 @@ services:
- database
- backend
- auth
# volumes:
volumes:
- ./frontend/public:/app/public
# - ./deployment/hmz/styles:/app/public/styles
# - ./deployment/hmz/data:/app/public/data
# - ./deployment/hmz/images:/app/public/images
Expand Down
68 changes: 68 additions & 0 deletions documentation/docs/03-rsd-instance/05-plugins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Plugins

:::info
Plugin support is currently under development and in testing phase, the API may be subject to changes.
:::

The RSD provides limited support for plugins, enabling third-party services to insert links into dedicated areas (plugin slots) within the user interface.

Plugins can be configured so that they can run in the same docker network, or on different servers.

## Configuration

### Environment Variables

If you are deploying the plugins alongside the main RSD in the same Docker network, the frontend container needs access to the environment variable `RSD_REVERSE_PROXY_URL`.
By default, the variable is set to:

```shell
RSD_REVERSE_PROXY_URL=http://nginx
```

### Frontend settings

For the RSD frontend to know which plugins should be used, they are configure in the `host` property of `frontend/public/data/settings.json`:

```json
{
"host": {
"plugins": ["<plugin>"]
}
}
```

Options for `<plugin>`:

* **url**: starting with `http://`or `https://` pointing to the root url of the plugin without `/api`
* **slug**: will be used when querying the plugin settings via `/plugin/<plugin>/api/v1/config` inside the servers own docker network

## nginx configuration

If the plugin is running in the same Docker network, `plugin` must be added to `nginx.conf` as a new location in the main server block:

```nginx
server {
listen 80 default_server;
server_name localhost;
# ...
# The root path of the plugin API
location /plugin/plugin/api/ {
resolver 127.0.0.11 valid=30s ipv6=off;
set $pluginbackend <PluginBackendContainer>;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
default_type application/json;
proxy_pass http://$pluginbackend/;
}
}
```

:::tip
Using this configuration, nginx will not exit upon starting if the plugin backend is not reachable yet. 127.0.0.11 is the docker internal resolver.
:::

Replace `<PluginBackendContainer>` by the respective container name, and port if necessary, where the backend is accessible.
This information should be provided in the documentation of the plugin.
6 changes: 6 additions & 0 deletions documentation/docs/03-rsd-instance/05-plugins.md.license
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
SPDX-FileCopyrightText: 2024 Christian Meeßen (GFZ) <[email protected]>
SPDX-FileCopyrightText: 2024 Dusan Mijatovic (Netherlands eScience Center)
SPDX-FileCopyrightText: 2024 Helmholtz Centre Potsdam - GFZ German Research Centre for Geosciences
SPDX-FileCopyrightText: 2024 Netherlands eScience Center

SPDX-License-Identifier: CC-BY-4.0
Loading

0 comments on commit c7b0320

Please sign in to comment.