Skip to content

Commit 25e8a52

Browse files
authored
Refactor to generic OIDC config (netbirdio#66)
Cleans up config.json providing generic OIDC properties. This allows for using other IDP providers besides Auth0. The change is backward compatible with the previous versions.
1 parent 2b26198 commit 25e8a52

8 files changed

+136
-64
lines changed

docker/init_react_envs.sh

+38-15
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,62 @@
11
#!/bin/bash
22
set -e
33

4-
if [[ -z "${AUTH0_DOMAIN}" ]]; then
5-
echo "AUTH0_DOMAIN environment variable must be set"
6-
exit 1
4+
if [[ -z "${AUTH_AUTHORITY}" ]]; then
5+
if [[ -z "${AUTH0_DOMAIN}" ]]; then
6+
echo "AUTH_AUTHORITY or AUTH0_DOMAIN environment variable must be set"
7+
exit 1
8+
fi
79
fi
810

9-
if [[ -z "${AUTH0_CLIENT_ID}" ]]; then
10-
echo "AUTH0_CLIENT_ID environment variable must be set"
11-
exit 1
11+
if [[ -z "${AUTH_CLIENT_ID}" ]]; then
12+
if [[ -z "${AUTH0_CLIENT_ID}" ]]; then
13+
echo "AUTH_CLIENT_ID or AUTH0_CLIENT_ID environment variable must be set"
14+
exit 1
15+
fi
1216
fi
1317

14-
if [[ -z "${AUTH0_AUDIENCE}" ]]; then
15-
echo "AUTH0_AUDIENCE environment variable must be set"
16-
exit 1
18+
if [[ -z "${AUTH_AUDIENCE}" ]]; then
19+
if [[ -z "${AUTH0_AUDIENCE}" ]]; then
20+
echo "AUTH_AUDIENCE or AUTH0_AUDIENCE environment variable must be set"
21+
exit 1
22+
fi
23+
fi
24+
25+
if [[ -z "${AUTH_SUPPORTED_SCOPES}" ]]; then
26+
if [[ -z "${AUTH0_DOMAIN}" ]]; then
27+
echo "AUTH_SUPPORTED_SCOPES environment variable must be set"
28+
exit 1
29+
fi
30+
fi
31+
32+
if [[ -z "${USE_AUTH0}" ]]; then
33+
if [[ -z "${AUTH0_DOMAIN}" ]]; then
34+
echo "USE_AUTH0 environment variable must be set"
35+
exit 1
36+
fi
1737
fi
1838

1939
if [[ -z "${NETBIRD_MGMT_API_ENDPOINT}" ]]; then
2040
echo "NETBIRD_MGMT_API_ENDPOINT environment variable must be set"
2141
exit 1
2242
fi
2343

24-
AUTH0_DOMAIN=${AUTH0_DOMAIN}
25-
AUTH0_CLIENT_ID=${AUTH0_CLIENT_ID}
26-
AUTH0_AUDIENCE=${AUTH0_AUDIENCE}
27-
NETBIRD_MGMT_API_ENDPOINT=$(echo $NETBIRD_MGMT_API_ENDPOINT | sed -E 's/(:80|:443)$//')
28-
NETBIRD_MGMT_GRPC_API_ENDPOINT=${NETBIRD_MGMT_GRPC_API_ENDPOINT}
44+
export AUTH_AUTHORITY=${AUTH_AUTHORITY:-https://$AUTH0_DOMAIN}
45+
export AUTH_CLIENT_ID=${AUTH_CLIENT_ID:-$AUTH0_CLIENT_ID}
46+
export AUTH_AUDIENCE=${AUTH_AUDIENCE:-$AUTH0_AUDIENCE}
47+
export USE_AUTH0=${USE_AUTH0:-true}
48+
export AUTH_SUPPORTED_SCOPES=${AUTH_SUPPORTED_SCOPES:-openid profile email api offline_access email_verified}
49+
50+
export NETBIRD_MGMT_API_ENDPOINT=$(echo $NETBIRD_MGMT_API_ENDPOINT | sed -E 's/(:80|:443)$//')
51+
export NETBIRD_MGMT_GRPC_API_ENDPOINT=${NETBIRD_MGMT_GRPC_API_ENDPOINT}
2952

3053
REPO="https://github.com/netbirdio/netbird/"
3154
# this command will fetch the latest release e.g. v0.6.3
3255
export NETBIRD_LATEST_VERSION=$(basename $(curl -fs -o/dev/null -w %{redirect_url} ${REPO}releases/latest))
3356
echo "NetBird latest version: ${NETBIRD_LATEST_VERSION}"
3457

3558
# replace ENVs in the config
36-
ENV_STR="\$\$AUTH0_DOMAIN \$\$AUTH0_CLIENT_ID \$\$AUTH0_AUDIENCE \$\$NETBIRD_MGMT_API_ENDPOINT \$\$NETBIRD_MGMT_GRPC_API_ENDPOINT \$\$NETBIRD_LATEST_VERSION"
59+
ENV_STR="\$\$USE_AUTH0 \$\$AUTH_AUDIENCE \$\$AUTH_AUTHORITY \$\$AUTH_CLIENT_ID \$\$AUTH_SUPPORTED_SCOPES \$\$NETBIRD_MGMT_API_ENDPOINT \$\$NETBIRD_MGMT_GRPC_API_ENDPOINT \$\$NETBIRD_LATEST_VERSION"
3760
MAIN_JS=$(find /usr/share/nginx/html/static/js/main.*js)
3861
OIDC_TRUSTED_DOMAINS="/usr/share/nginx/html/OidcTrustedDomains.js"
3962
cp "$MAIN_JS" "$MAIN_JS".copy

run-local-keycloak.sh

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/bash
2+
3+
MGMT_PORT=$1
4+
5+
npm run build
6+
docker build -f docker/Dockerfile -t netbird/dashboard-local:latest .
7+
8+
docker rm -f netbird-dashboard
9+
docker run -d --name netbird-dashboard \
10+
-p 3000:80 -p 443:443 \
11+
-e AUTH_AUDIENCE=netbird \
12+
-e AUTH_AUTHORITY=http://localhost:8080/realms/netbird \
13+
-e AUTH_CLIENT_ID=netbird \
14+
-e USE_AUTH0=false \
15+
-e AUTH_SUPPORTED_SCOPES='openid profile email' \
16+
-e NETBIRD_MGMT_API_ENDPOINT=http://localhost:$MGMT_PORT \
17+
-e NETBIRD_MGMT_GRPC_API_ENDPOINT=http://localhost:$MGMT_PORT \
18+
netbird/dashboard-local:latest

run-local-legacy.sh

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/bin/bash
2+
3+
MGMT_PORT=$1
4+
5+
npm run build
6+
docker build -f docker/Dockerfile -t netbird/dashboard-local:latest .
7+
8+
docker rm -f netbird-dashboard
9+
docker run -d --name netbird-dashboard \
10+
-p 3000:80 -p 443:443 \
11+
-e AUTH0_AUDIENCE=http://localhost:3000/ \
12+
-e AUTH0_DOMAIN=netbird-localdev.eu.auth0.com \
13+
-e AUTH0_CLIENT_ID=kBRMAOqIZ7hvpVCaypQLCJvTzkYYIXVt \
14+
-e NETBIRD_MGMT_API_ENDPOINT=http://localhost:$MGMT_PORT \
15+
-e NETBIRD_MGMT_GRPC_API_ENDPOINT=http://localhost:$MGMT_PORT \
16+
netbird/dashboard-local:latest

run-local.sh

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/bash
2+
3+
MGMT_PORT=$1
4+
5+
npm run build
6+
docker build -f docker/Dockerfile -t netbird/dashboard-local:latest .
7+
8+
docker rm -f netbird-dashboard
9+
docker run -d --name netbird-dashboard \
10+
-p 3000:80 -p 443:443 \
11+
-e AUTH_AUDIENCE=http://localhost:3000/ \
12+
-e AUTH_AUTHORITY=https://netbird-localdev.eu.auth0.com \
13+
-e AUTH_CLIENT_ID=kBRMAOqIZ7hvpVCaypQLCJvTzkYYIXVt \
14+
-e USE_AUTH0=true \
15+
-e AUTH_SUPPORTED_SCOPES='openid profile email api offline_access email_verified' \
16+
-e NETBIRD_MGMT_API_ENDPOINT=http://localhost:$MGMT_PORT \
17+
-e NETBIRD_MGMT_GRPC_API_ENDPOINT=http://localhost:$MGMT_PORT \
18+
netbird/dashboard-local:latest

src/components/Navbar.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const Navbar = () => {
3737
{ label: (<Link to="/users">Users</Link>), key: '/users' }
3838
] as ItemType[])
3939
const logoutWithRedirect = () =>
40-
logout("",{client_id:config.clientId});
40+
logout("/",{client_id:config.clientId});
4141
useEffect(() => {
4242
const fs = menuItems.filter(m => m?.key !== userEmailKey && m?.key !== userLogoutKey && m?.key !== userDividerKey)
4343
if (screens.xs === true) {

src/config.json

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
{
2-
"domain": "$AUTH0_DOMAIN",
3-
"clientId": "$AUTH0_CLIENT_ID",
4-
"audience": "$AUTH0_AUDIENCE",
2+
"auth0Auth": "$USE_AUTH0",
3+
"authAuthority": "$AUTH_AUTHORITY",
4+
"authClientId": "$AUTH_CLIENT_ID",
5+
"authScopesSupported": "$AUTH_SUPPORTED_SCOPES",
6+
"authAudience": "$AUTH_AUDIENCE",
7+
58
"apiOrigin": "$NETBIRD_MGMT_API_ENDPOINT",
69
"grpcApiOrigin": "$NETBIRD_MGMT_GRPC_API_ENDPOINT",
710
"latestVersion": "$NETBIRD_LATEST_VERSION"

src/config.ts

+5-13
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,15 @@ if (process.env.NODE_ENV !== 'production') {
88
}
99

1010
export function getConfig() {
11-
// Configure the audience here. By default, it will take whatever is in the config
12-
// (specified by the `audience` key) unless it's the default value of "YOUR_API_IDENTIFIER" (which
13-
// is what you get sometimes by using the Auth0 sample download tool from the quickstart page, if you
14-
// don't have an API).
15-
// If this resolves to `null`, the API page changes to show some helpful info about what to do
16-
// with the audience.
17-
const audience =
18-
configJson.audience && configJson.audience !== "YOUR_API_IDENTIFIER"
19-
? configJson.audience
20-
: null;
2111

2212
return {
23-
domain: configJson.domain,
24-
clientId: configJson.clientId,
13+
auth0Auth: configJson.auth0Auth == "true", //due to substitution we can't use boolean in the config
14+
authority: configJson.authAuthority,
15+
clientId: configJson.authClientId,
16+
scopesSupported: configJson.authScopesSupported,
2517
apiOrigin: configJson.apiOrigin,
2618
grpcApiOrigin: configJson.grpcApiOrigin,
2719
latestVersion: configJson.latestVersion,
28-
...(audience ? { audience } : null),
20+
audience: configJson.authAudience,
2921
};
3022
}

src/index.tsx

+34-32
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,37 @@ import './index.css';
44
import App from './App';
55
import reportWebVitals from './reportWebVitals';
66
import history from "./utils/history";
7-
import { getConfig } from "./config";
8-
import {OidcProvider, useOidc} from '@axa-fr/react-oidc';
7+
import {getConfig} from "./config";
8+
import {OidcProvider} from '@axa-fr/react-oidc';
99
import {BrowserRouter} from "react-router-dom";
1010
import Loading from "./components/Loading";
1111
import LoginError from "./components/LoginError";
12+
import {AuthorityConfiguration} from "@axa-fr/react-oidc/dist/vanilla/oidc";
1213

1314
const config = getConfig();
1415

15-
const authority = 'https://' + config.domain
16+
// Unfortunately Auth0 https://<DOMAIN>/.well-known/openid-configuration doesn't contain end_session_endpoint that
17+
// is required for doing logout. Therefore, we need to hardcode the config for auth
18+
const auth0AuthorityConfig: AuthorityConfiguration = {
19+
authorization_endpoint: config.authority + "/authorize",
20+
token_endpoint: config.authority + "/oauth/token",
21+
revocation_endpoint: config.authority + "/oauth/revoke",
22+
end_session_endpoint: config.authority + "/v2/logout",
23+
userinfo_endpoint: config.authority + "/userinfo"
24+
} as AuthorityConfiguration
25+
1626
const providerConfig = {
17-
authority: authority,
27+
authority: config.authority,
1828
client_id: config.clientId,
19-
redirect_uri: window.location.origin+'#callback',
29+
redirect_uri: window.location.origin + '/#callback',
2030
refresh_time_before_tokens_expiration_in_second: 30,
21-
silent_redirect_uri: window.location.origin + '#silent-callback',
22-
scope: 'openid profile email api offline_access email_verified',
31+
silent_redirect_uri: window.location.origin + '/#silent-callback',
32+
scope: config.scopesSupported,
2333
// disabling service worker
2434
// service_worker_relative_url:'/OidcServiceWorker.js',
2535
service_worker_only: false,
26-
authority_configuration: {
27-
authorization_endpoint: authority + "/authorize",
28-
token_endpoint: authority + "/oauth/token",
29-
revocation_endpoint: authority + "/oauth/revoke",
30-
end_session_endpoint: authority + "/v2/logout",
31-
userinfo_endpoint: authority + "/userinfo"
32-
},
33-
...(config.audience ? {extras:{ audience: config.audience}} : null)
36+
authority_configuration: config.auth0Auth ? auth0AuthorityConfig : undefined,
37+
...(config.audience ? {extras: {audience: config.audience}} : null)
3438
};
3539

3640
const root = ReactDOM.createRoot(
@@ -40,23 +44,21 @@ const root = ReactDOM.createRoot(
4044
const loadingComponent = () => <Loading padding="3em" width="50px" height="50px"/>
4145

4246
root.render(
43-
44-
<OidcProvider
45-
configuration={providerConfig}
46-
callbackSuccessComponent={loadingComponent}
47-
authenticatingErrorComponent={LoginError}
48-
authenticatingComponent={loadingComponent}
49-
sessionLostComponent={loadingComponent}
50-
loadingComponent={loadingComponent}
51-
onSessionLost={()=>{
52-
history.push("/peers")
53-
}}
54-
>
55-
<BrowserRouter>
56-
<App/>
57-
</BrowserRouter>
58-
</OidcProvider>
59-
47+
<OidcProvider
48+
configuration={providerConfig}
49+
callbackSuccessComponent={loadingComponent}
50+
authenticatingErrorComponent={LoginError}
51+
authenticatingComponent={loadingComponent}
52+
sessionLostComponent={loadingComponent}
53+
loadingComponent={loadingComponent}
54+
onSessionLost={() => {
55+
history.push("/peers")
56+
}}
57+
>
58+
<BrowserRouter>
59+
<App/>
60+
</BrowserRouter>
61+
</OidcProvider>
6062
);
6163

6264
// If you want to start measuring performance in your app, pass a function

0 commit comments

Comments
 (0)