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

Documentation and Cros Proxy option #9

Merged
merged 11 commits into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
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
4 changes: 3 additions & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
GENERATE_SOURCEMAP=false
GENERATE_SOURCEMAP=false
# REACT_APP_CORS_PROXY=https://corsproxy.io/?url=
# REACT_APP_BASENAME=/
71 changes: 67 additions & 4 deletions SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,73 @@ To run the software in local run:

After the initialization the page will be available to http://localhost:3000

### Note:
To run every functionality of the software in local environment you need to install any browser plug-in that suppresses CORS such as "CORS Everywere" for Firefox.

## Build
To build the project to HTML run the following command:
## Build and deploy

### Page options
In the .env file there are two option that can be optionally set:
```
# REACT_APP_CORS_PROXY=https://corsproxy.io/?url=
# REACT_APP_BASENAME=/
```

- REACT_APP_CORS_PROXY: sets an url of a service that provide proxy suppression.
- REACT_APP_BASENAME: sets a base name if the page in not served under '/' .

### Build
To build the project to an HTML optimized version run the following command:

> npm run build

A directory named "build" will be created containing a web page that can be hosted from a web server like Nginx or similar.

### Host with Nginx
After the Nginx, the domain and certificates setup you need to determinate where the page HTML files needs to be copied.
You can find the path searching for the configuration contained in /etc/nginx/sites-enabled/ where the filename matches your domain.
You will find the html path under the "root" option like this example:

```
server {
listen 80;
listen [::]:80;

root /var/www/your_domain/html;
index index.html index.htm index.nginx-debian.html;

server_name your_domain www.your_domain;

location / {
try_files $uri $uri/ =404;
}
}
```

You can copy the content of the directory "build" inside the html one.

## CORS restriction
To run every the app without cors restriction you have two possibilities: one is to install any browser plug-in that suppresses CORS such as "CORS Everywere" for Firefox or use a self hosted or remote cors proxy server.

### Nginx as a Forwarder Proxy
Nginx can be used as a forward proxy on the same host using adding a server or a route that handle the traffic.
Below you can find an example of configuration that exposes the port 8888 to proxy the traffic.
```
server {
listen 8888;

location / {
resolver 8.8.8.8;

proxy_pass $arg_url;
}
}
```

An example url of proxied GET request using this configuration:
peppelinux marked this conversation as resolved.
Show resolved Hide resolved
> localhost:8888?url=https://oidc.registry.servizicie.interno.gov.it/.well-known/openid-federation

### A self hosted service
A simple self hosted proxy can be also used like the one contained in the bin directary that can be launched using the command:
> npm run proxy

### A third party service
There are other third party service on-line that can be used to proxy the request like corsproxy.io or corsmirror.com that can be used valoraizing the variiable 'REACT_APP_CORS_PROXY' in .env .
27 changes: 27 additions & 0 deletions bin/proxy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const express = require('express');
const axios = require('axios');

const app = express();
const port = 3000;

app.get('/proxy', (req, res) => {
if (
!req.query.url ||
!req.query.url.startsWith('https://') ||
req.query.url.includes('localhost') ||
req.query.url.match(/(\d{1,3}\.){3}\d{1,3}/)

) {
res.send('Please provide a valid url').status(400);
return;
}

axios.get(req.query.url)
.then(response => res.send(response.data))
.catch(error => res.send(error));
});

app.listen(
port,
() => console.log(`Proxy listening on port ${port}`)
);
89 changes: 1 addition & 88 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"@types/react-dom": "^18.3.1",
"axios": "^1.7.7",
"bootstrap-italia": "^2.11.0",
"express": "^4.21.2",
"formatjs": "^0.1.1",
"jose": "^5.9.6",
"react": "^18.3.1",
Expand All @@ -34,7 +35,8 @@
"test": "react-scripts test",
"eject": "react-scripts eject",
"test-lib": "jest ./src/lib",
"lint": "npx prettier . --write"
"lint": "npx prettier . --write",
"proxy": "node bin/proxy.js"
},
"eslintConfig": {
"plugins": ["no-secrets"],
Expand Down
2 changes: 1 addition & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const root = ReactDOM.createRoot(
);
root.render(
<React.StrictMode>
<Router>
<Router basename={process.env.REACT_APP_BASENAME}>
<App />
</Router>
</React.StrictMode>,
Expand Down
8 changes: 5 additions & 3 deletions src/lib/openid-federation/trustChain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ import { Graph } from "../grap-data/types";
import { updateGraph, genNode } from "../grap-data/utils";
import { setEntityType } from "./utils";

const cors_proxy = process.env.REACT_APP_CORS_PROXY || "";

const getSubordinateStatement = async (
fetchEndpoint: string,
sub: string,
ec: EntityConfiguration,
): Promise<SubordianteStatement> => {
const completeFetchEndpoint = `${fetchEndpoint}?sub=${sub}`;
const response = await axios.get(completeFetchEndpoint);
const response = await axios.get(cors_proxy + completeFetchEndpoint);
const payload = jose.decodeJwt(response.data) as SubordinateStatementPayload;
const header = jose.decodeProtectedHeader(response.data) as JWTHeader;

Expand All @@ -47,7 +49,7 @@ const getEntityConfigurations = async (
): Promise<EntityConfiguration> => {
const subjectWellKnown = subject.endsWith("/") ? subject : subject + "/";

const { data: jwt } = await axios.get(subjectWellKnown + wellKnownEndpoint);
const { data: jwt } = await axios.get(cors_proxy + subjectWellKnown + wellKnownEndpoint);

const header = jose.decodeProtectedHeader(jwt) as JWTHeader;
const payload = jose.decodeJwt(jwt) as EntityConfigurationPayload;
Expand Down Expand Up @@ -77,7 +79,7 @@ export const discovery = async (currenECUrl: string): Promise<NodeInfo> => {
};

if (federationListEndpoint) {
const response = await axios.get(federationListEndpoint);
const response = await axios.get(cors_proxy + federationListEndpoint);
nodeInfo.immDependants = response.data;
}

Expand Down
3 changes: 0 additions & 3 deletions src/lib/openid-federation/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as jose from "jose";
import { Tree } from "@easygrating/easytree";
import { NodeInfo, EntityConfigurationPayload, EntityType } from "./types";

export const jsonToPublicKey = (jwk: { [key: string]: any }) => {
Expand Down Expand Up @@ -27,8 +26,6 @@ export const jsonToPublicKey = (jwk: { [key: string]: any }) => {
throw new Error(`Unsupported key type ${jwk.kty}`);
};

export const getTreeRoot = (tree: Tree<NodeInfo>): Tree<NodeInfo> =>
tree.parent ? getTreeRoot(tree.parent) : tree;
export const getFetchEndpoint = (payload: EntityConfigurationPayload) =>
payload.metadata?.federation_entity?.federation_fetch_endpoint;
export const hasFetchEndpoint = (payload: EntityConfigurationPayload) =>
Expand Down
Loading