Refactor to generic OIDC config (#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.
This commit is contained in:
Misha Bragin
2022-08-15 19:32:01 +02:00
committed by GitHub
parent 2b26198741
commit 25e8a52465
8 changed files with 136 additions and 64 deletions

View File

@@ -1,19 +1,39 @@
#!/bin/bash
set -e
if [[ -z "${AUTH0_DOMAIN}" ]]; then
echo "AUTH0_DOMAIN environment variable must be set"
exit 1
if [[ -z "${AUTH_AUTHORITY}" ]]; then
if [[ -z "${AUTH0_DOMAIN}" ]]; then
echo "AUTH_AUTHORITY or AUTH0_DOMAIN environment variable must be set"
exit 1
fi
fi
if [[ -z "${AUTH0_CLIENT_ID}" ]]; then
echo "AUTH0_CLIENT_ID environment variable must be set"
exit 1
if [[ -z "${AUTH_CLIENT_ID}" ]]; then
if [[ -z "${AUTH0_CLIENT_ID}" ]]; then
echo "AUTH_CLIENT_ID or AUTH0_CLIENT_ID environment variable must be set"
exit 1
fi
fi
if [[ -z "${AUTH0_AUDIENCE}" ]]; then
echo "AUTH0_AUDIENCE environment variable must be set"
exit 1
if [[ -z "${AUTH_AUDIENCE}" ]]; then
if [[ -z "${AUTH0_AUDIENCE}" ]]; then
echo "AUTH_AUDIENCE or AUTH0_AUDIENCE environment variable must be set"
exit 1
fi
fi
if [[ -z "${AUTH_SUPPORTED_SCOPES}" ]]; then
if [[ -z "${AUTH0_DOMAIN}" ]]; then
echo "AUTH_SUPPORTED_SCOPES environment variable must be set"
exit 1
fi
fi
if [[ -z "${USE_AUTH0}" ]]; then
if [[ -z "${AUTH0_DOMAIN}" ]]; then
echo "USE_AUTH0 environment variable must be set"
exit 1
fi
fi
if [[ -z "${NETBIRD_MGMT_API_ENDPOINT}" ]]; then
@@ -21,11 +41,14 @@ if [[ -z "${NETBIRD_MGMT_API_ENDPOINT}" ]]; then
exit 1
fi
AUTH0_DOMAIN=${AUTH0_DOMAIN}
AUTH0_CLIENT_ID=${AUTH0_CLIENT_ID}
AUTH0_AUDIENCE=${AUTH0_AUDIENCE}
NETBIRD_MGMT_API_ENDPOINT=$(echo $NETBIRD_MGMT_API_ENDPOINT | sed -E 's/(:80|:443)$//')
NETBIRD_MGMT_GRPC_API_ENDPOINT=${NETBIRD_MGMT_GRPC_API_ENDPOINT}
export AUTH_AUTHORITY=${AUTH_AUTHORITY:-https://$AUTH0_DOMAIN}
export AUTH_CLIENT_ID=${AUTH_CLIENT_ID:-$AUTH0_CLIENT_ID}
export AUTH_AUDIENCE=${AUTH_AUDIENCE:-$AUTH0_AUDIENCE}
export USE_AUTH0=${USE_AUTH0:-true}
export AUTH_SUPPORTED_SCOPES=${AUTH_SUPPORTED_SCOPES:-openid profile email api offline_access email_verified}
export NETBIRD_MGMT_API_ENDPOINT=$(echo $NETBIRD_MGMT_API_ENDPOINT | sed -E 's/(:80|:443)$//')
export NETBIRD_MGMT_GRPC_API_ENDPOINT=${NETBIRD_MGMT_GRPC_API_ENDPOINT}
REPO="https://github.com/netbirdio/netbird/"
# this command will fetch the latest release e.g. v0.6.3
@@ -33,7 +56,7 @@ export NETBIRD_LATEST_VERSION=$(basename $(curl -fs -o/dev/null -w %{redirect_ur
echo "NetBird latest version: ${NETBIRD_LATEST_VERSION}"
# replace ENVs in the config
ENV_STR="\$\$AUTH0_DOMAIN \$\$AUTH0_CLIENT_ID \$\$AUTH0_AUDIENCE \$\$NETBIRD_MGMT_API_ENDPOINT \$\$NETBIRD_MGMT_GRPC_API_ENDPOINT \$\$NETBIRD_LATEST_VERSION"
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"
MAIN_JS=$(find /usr/share/nginx/html/static/js/main.*js)
OIDC_TRUSTED_DOMAINS="/usr/share/nginx/html/OidcTrustedDomains.js"
cp "$MAIN_JS" "$MAIN_JS".copy

18
run-local-keycloak.sh Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/bash
MGMT_PORT=$1
npm run build
docker build -f docker/Dockerfile -t netbird/dashboard-local:latest .
docker rm -f netbird-dashboard
docker run -d --name netbird-dashboard \
-p 3000:80 -p 443:443 \
-e AUTH_AUDIENCE=netbird \
-e AUTH_AUTHORITY=http://localhost:8080/realms/netbird \
-e AUTH_CLIENT_ID=netbird \
-e USE_AUTH0=false \
-e AUTH_SUPPORTED_SCOPES='openid profile email' \
-e NETBIRD_MGMT_API_ENDPOINT=http://localhost:$MGMT_PORT \
-e NETBIRD_MGMT_GRPC_API_ENDPOINT=http://localhost:$MGMT_PORT \
netbird/dashboard-local:latest

16
run-local-legacy.sh Executable file
View File

@@ -0,0 +1,16 @@
#!/bin/bash
MGMT_PORT=$1
npm run build
docker build -f docker/Dockerfile -t netbird/dashboard-local:latest .
docker rm -f netbird-dashboard
docker run -d --name netbird-dashboard \
-p 3000:80 -p 443:443 \
-e AUTH0_AUDIENCE=http://localhost:3000/ \
-e AUTH0_DOMAIN=netbird-localdev.eu.auth0.com \
-e AUTH0_CLIENT_ID=kBRMAOqIZ7hvpVCaypQLCJvTzkYYIXVt \
-e NETBIRD_MGMT_API_ENDPOINT=http://localhost:$MGMT_PORT \
-e NETBIRD_MGMT_GRPC_API_ENDPOINT=http://localhost:$MGMT_PORT \
netbird/dashboard-local:latest

18
run-local.sh Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/bash
MGMT_PORT=$1
npm run build
docker build -f docker/Dockerfile -t netbird/dashboard-local:latest .
docker rm -f netbird-dashboard
docker run -d --name netbird-dashboard \
-p 3000:80 -p 443:443 \
-e AUTH_AUDIENCE=http://localhost:3000/ \
-e AUTH_AUTHORITY=https://netbird-localdev.eu.auth0.com \
-e AUTH_CLIENT_ID=kBRMAOqIZ7hvpVCaypQLCJvTzkYYIXVt \
-e USE_AUTH0=true \
-e AUTH_SUPPORTED_SCOPES='openid profile email api offline_access email_verified' \
-e NETBIRD_MGMT_API_ENDPOINT=http://localhost:$MGMT_PORT \
-e NETBIRD_MGMT_GRPC_API_ENDPOINT=http://localhost:$MGMT_PORT \
netbird/dashboard-local:latest

View File

@@ -37,7 +37,7 @@ const Navbar = () => {
{ label: (<Link to="/users">Users</Link>), key: '/users' }
] as ItemType[])
const logoutWithRedirect = () =>
logout("",{client_id:config.clientId});
logout("/",{client_id:config.clientId});
useEffect(() => {
const fs = menuItems.filter(m => m?.key !== userEmailKey && m?.key !== userLogoutKey && m?.key !== userDividerKey)
if (screens.xs === true) {

View File

@@ -1,7 +1,10 @@
{
"domain": "$AUTH0_DOMAIN",
"clientId": "$AUTH0_CLIENT_ID",
"audience": "$AUTH0_AUDIENCE",
"auth0Auth": "$USE_AUTH0",
"authAuthority": "$AUTH_AUTHORITY",
"authClientId": "$AUTH_CLIENT_ID",
"authScopesSupported": "$AUTH_SUPPORTED_SCOPES",
"authAudience": "$AUTH_AUDIENCE",
"apiOrigin": "$NETBIRD_MGMT_API_ENDPOINT",
"grpcApiOrigin": "$NETBIRD_MGMT_GRPC_API_ENDPOINT",
"latestVersion": "$NETBIRD_LATEST_VERSION"

View File

@@ -8,23 +8,15 @@ if (process.env.NODE_ENV !== 'production') {
}
export function getConfig() {
// Configure the audience here. By default, it will take whatever is in the config
// (specified by the `audience` key) unless it's the default value of "YOUR_API_IDENTIFIER" (which
// is what you get sometimes by using the Auth0 sample download tool from the quickstart page, if you
// don't have an API).
// If this resolves to `null`, the API page changes to show some helpful info about what to do
// with the audience.
const audience =
configJson.audience && configJson.audience !== "YOUR_API_IDENTIFIER"
? configJson.audience
: null;
return {
domain: configJson.domain,
clientId: configJson.clientId,
auth0Auth: configJson.auth0Auth == "true", //due to substitution we can't use boolean in the config
authority: configJson.authAuthority,
clientId: configJson.authClientId,
scopesSupported: configJson.authScopesSupported,
apiOrigin: configJson.apiOrigin,
grpcApiOrigin: configJson.grpcApiOrigin,
latestVersion: configJson.latestVersion,
...(audience ? { audience } : null),
audience: configJson.authAudience,
};
}

View File

@@ -4,33 +4,37 @@ import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import history from "./utils/history";
import { getConfig } from "./config";
import {OidcProvider, useOidc} from '@axa-fr/react-oidc';
import {getConfig} from "./config";
import {OidcProvider} from '@axa-fr/react-oidc';
import {BrowserRouter} from "react-router-dom";
import Loading from "./components/Loading";
import LoginError from "./components/LoginError";
import {AuthorityConfiguration} from "@axa-fr/react-oidc/dist/vanilla/oidc";
const config = getConfig();
const authority = 'https://' + config.domain
// Unfortunately Auth0 https://<DOMAIN>/.well-known/openid-configuration doesn't contain end_session_endpoint that
// is required for doing logout. Therefore, we need to hardcode the config for auth
const auth0AuthorityConfig: AuthorityConfiguration = {
authorization_endpoint: config.authority + "/authorize",
token_endpoint: config.authority + "/oauth/token",
revocation_endpoint: config.authority + "/oauth/revoke",
end_session_endpoint: config.authority + "/v2/logout",
userinfo_endpoint: config.authority + "/userinfo"
} as AuthorityConfiguration
const providerConfig = {
authority: authority,
authority: config.authority,
client_id: config.clientId,
redirect_uri: window.location.origin+'#callback',
redirect_uri: window.location.origin + '/#callback',
refresh_time_before_tokens_expiration_in_second: 30,
silent_redirect_uri: window.location.origin + '#silent-callback',
scope: 'openid profile email api offline_access email_verified',
silent_redirect_uri: window.location.origin + '/#silent-callback',
scope: config.scopesSupported,
// disabling service worker
// service_worker_relative_url:'/OidcServiceWorker.js',
service_worker_only: false,
authority_configuration: {
authorization_endpoint: authority + "/authorize",
token_endpoint: authority + "/oauth/token",
revocation_endpoint: authority + "/oauth/revoke",
end_session_endpoint: authority + "/v2/logout",
userinfo_endpoint: authority + "/userinfo"
},
...(config.audience ? {extras:{ audience: config.audience}} : null)
authority_configuration: config.auth0Auth ? auth0AuthorityConfig : undefined,
...(config.audience ? {extras: {audience: config.audience}} : null)
};
const root = ReactDOM.createRoot(
@@ -40,23 +44,21 @@ const root = ReactDOM.createRoot(
const loadingComponent = () => <Loading padding="3em" width="50px" height="50px"/>
root.render(
<OidcProvider
configuration={providerConfig}
callbackSuccessComponent={loadingComponent}
authenticatingErrorComponent={LoginError}
authenticatingComponent={loadingComponent}
sessionLostComponent={loadingComponent}
loadingComponent={loadingComponent}
onSessionLost={()=>{
history.push("/peers")
}}
>
<BrowserRouter>
<App/>
</BrowserRouter>
</OidcProvider>
<OidcProvider
configuration={providerConfig}
callbackSuccessComponent={loadingComponent}
authenticatingErrorComponent={LoginError}
authenticatingComponent={loadingComponent}
sessionLostComponent={loadingComponent}
loadingComponent={loadingComponent}
onSessionLost={() => {
history.push("/peers")
}}
>
<BrowserRouter>
<App/>
</BrowserRouter>
</OidcProvider>
);
// If you want to start measuring performance in your app, pass a function