Skip to main content

Integration

This guide explains how product teams can integrate Auth0 authentication into their React applications.

Pre-requisites

  1. Ensure the product is registered with Aventian.

  2. Request the following values from the Aventian Team:

    • domain
    • clientId
    • audience
  3. Ask Aventian Team to add your product URLs into Auth0 allowed URLs.

Installation

Install the Auth0 React SDK:

npm install @auth0/auth0-react

Setup Auth0 Outlet

import { AppState, Auth0Provider } from '@auth0/auth0-react';
import { Outlet, useNavigate } from 'react-router-dom';

const Auth0Outlet = () => {
const navigate = useNavigate();
const onRedirectCallback = (appState?: AppState) => {
console.log(appState);
navigate(appState?.returnTo ?? window.location.pathname);
};
return (
<Auth0Provider
domain={import.meta.env.VITE_APP_AUTH0_DOMAIN}
clientId={import.meta.env.VITE_APP_AUTH0_CLIENT_ID}
authorizationParams={{
redirect_uri: window.location.origin,
audience: import.meta.env.VITE_APP_AUTH0_AUDIENCE,
}}
onRedirectCallback={onRedirectCallback}
>
<Outlet />
</Auth0Provider>
);
};

export default Auth0Outlet;

Add Auth0 Outlet to Root Router

import {
createBrowserRouter,
createRoutesFromElements,
RouterProvider,
Route,
} from 'react-router';
import {
ErrorBoundary,
NotFound,
} from '@modules/shared/components/index';
import {
Auth0Outlet,
PublicOutlet,
SecuredOutlet,
} from '@routes/outlets/index';

const router = createBrowserRouter(
createRoutesFromElements(
<Route errorElement={<ErrorBoundary />}>
<Route path="/" element={<Auth0Outlet />}>
<Route path="/" element={<SecuredOutlet />}>
<Route path="private" element={<div>Private</div>} />
</Route>

<Route path="/" element={<PublicOutlet />}>
<Route path="public" element={<div>Public</div>} />
</Route>
<Route path="*" element={<NotFound />} />
</Route>
</Route>,
),
);

export default function AppRoute() {
return <RouterProvider router={router} />;
}

Securing Routes with useAuth0

import { useAuth0 } from '@auth0/auth0-react';
import React, { useEffect } from 'react';
import { Outlet } from 'react-router';
import { Spin } from 'antd';
import { LoadingOutlined } from '@ant-design/icons';

const onRedirectingLoader = () => {
return <Spin spinning={true} fullscreen={true}></Spin>;
};

const SecuredOutlet: React.FC = () => {
const {
isLoading,
isAuthenticated,
loginWithRedirect,
} = useAuth0();

useEffect(() => {
if (!isLoading && !isAuthenticated) {
loginWithRedirect({
appState: {
returnTo: location.pathname + location.search,
onRedirecting: () => onRedirectingLoader(),
},
});
}
}, [isLoading, isAuthenticated]);

return (
<Spin
indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />}
spinning={isLoading || !isAuthenticated}
fullscreen={isLoading || !isAuthenticated}
>
{!isLoading &&
isAuthenticated && <Outlet />}
</Spin>
);
};

export default SecuredOutlet;

Logout

For logout, use the Aventian React library: 👉 Profile Dropdown Widget

Token Verification (Frontend)

Use the Aventian-provided API for verifying tokens and fetching user details: 👉 User Details API

Code Example

Node JS

const axios = require('axios');

async function getUserDetails() {
try {
const response = await axios.get(
'https://aventian.uc.r.appspot.com/api/v2/auth/get-user-details',
{
headers: {
'accept': 'application/json',
'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjM0NTYiLCJyb2xlIjoiZGVtbzEiLCJleHAiOjE3MDAwMDAwMDB9.abc123XYZ456fakeSignature789'
}
}
);
console.log(response.data);
} catch (error) {
console.error('Error:', error.response ? error.response.data : error.message);
}
}

getUserDetails();

Python

import requests

url = "https://aventian.uc.r.appspot.com/api/v2/auth/get-user-details"
headers = {
"accept": "application/json",
"Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjM0NTYiLCJyb2xlIjoiZGVtbzEiLCJleHAiOjE3MDAwMDAwMDB9.abc123XYZ456fakeSignature789"
}

response = requests.get(url, headers=headers)

print(response.json())

Response

{
"id": 1233,
"name": "Json Holder",
"email": "json.holder@gmail.com",
"profile_picture": "https://toppng.com/uploads/preview/gravatar-logo-11609363449s2hnzzbhe9.png",
"team_id": 1,
"team_name": "Dummy Team",
"team_key": "dummy",
"api_key": "X-API-KEY",
"roles": [
{
"id": 3,
"name": "Admin",
"product_id": 2,
"description": "Built-in Role"
}
],
"team_logo": "https://toppng.com/uploads/preview/gravatar-logo-11609363449s2hnzzbhe9.png",
"team_owner_id": 3,
"permissions": [
"project:color:own",
"project:favourite:own",
"project:folder:manage",
"team:all:projects",
"team:notification:manage",
"team:project:create",
"team:settings:customfields:create",
"team:settings:customfields:delete",
"team:settings:customfields:edit",
"team:settings:customfields:view",
"team:settings:optionalfields:edit",
"team:settings:view"
]
}

Request Authentication & Authorization (Backend)

Use the Aventian-provided API for verifying tokens and X-API-Key to authorize requests: 👉 Verify User Request API

Code Example

Node JS

const axios = require('axios');

async function verifyAuth() {
try {
const response = await axios.get(
'https://aventian.uc.r.appspot.com/api/v2/auth/verify',
{
headers: {
'accept': '*/*',
'X-Api-Key': 'X-API-KEY',
'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjM0NTYiLCJyb2xlIjoiZGVtbzEiLCJleHAiOjE3MDAwMDAwMDB9.abc123XYZ456fakeSignature789'
}
}
);
console.log(response.data);
} catch (error) {
console.error('Error:', error.response ? error.response.data : error.message);
}
}

verifyAuth();

Python

import requests

url = "https://aventian.uc.r.appspot.com/api/v2/auth/verify"
headers = {
"accept": "*/*",
"X-Api-Key": "X-API-KEY",
"Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjM0NTYiLCJyb2xlIjoiZGVtbzEiLCJleHAiOjE3MDAwMDAwMDB9.abc123XYZ456fakeSignature789"
}

response = requests.get(url, headers=headers)

print(response.json())

Response

{
"id": 1233,
"name": "Json Holder",
"email": "json.holder@gmail.com",
"roles": [
{
"id": 3,
"name": "Admin",
"description": "Built-in Role"
}
],
"api_key": "X-API-KEY",
"team_id": 4,
"team_key": "dummy",
"team_name": "Dummy Team",
"permissions": [
"project:color:own",
"project:favourite:own",
"project:folder:manage",
"team:all:projects",
"team:notification:manage",
"team:project:create",
"team:settings:customfields:create",
"team:settings:customfields:delete",
"team:settings:customfields:edit",
"team:settings:customfields:view",
"team:settings:optionalfields:edit",
"team:settings:view"
],
"encrypted_team_db_config": "U2FsdGVkX19Lzb3NGIDCEALhW8ckwJ5UHGU497IzhNOK/LFkSX4rZNudjqoL10mdqdhDy+DT7YzIQNFd/1vXxNv4lYtpEtEo/Qc+ZOWXZX9Pwn5dNJzESvUnfzcqsix/KrqnFfF6xIgKOq1F3xs/6LzicsulN5rdPakqPOWVIARHVn4VQ8inCqQwgiVLecZ52qFFp4uG1Wknn9YoPZGohysAqEy4Xpc3V3HKwzqRhG9n",
"cache_hit": true
}

The service ensures the provided token and API key are both valid and associated with the same user and team.

Summary & Next Steps

You're now set up to:

  • Authenticate users via Auth0 in a React SPA.
  • Protect routes with a secure outlet pattern.
  • Retrieve user profile + roles/permissions via the User Details API.
  • Server‑side verify requests with both JWT (Authorization header) and X-Api-Key for defense in depth.

Recommended next steps:

  1. Implement refresh / silent auth flows (Auth0 getAccessTokenSilently).
  2. Cache user + permission data client-side with a short TTL to reduce network calls.
  3. Enforce permission checks in UI components (e.g. feature flags / guard hooks).
  4. Add backend middleware to centralize verify + permission mapping.
  5. Rotate API keys periodically and monitor for unusual usage.

Troubleshooting

IssueHint
Infinite redirect loopEnsure callback URL is whitelisted in Auth0 and returnTo path exists.
401 from verify endpointToken expired or audience mismatch—confirm Auth0 API audience value.
403 after verifyAPI key valid but missing required role/permission—inspect permissions array.