How to Integrate Fabrixly-IDS with React and Node.js
This guide walks you through integrating Fabrixly-IDS authentication in a React single-page application (SPA) backed by a Node.js / Express API server.
ποΈ Architecture Overview
- Frontend (React): Handles login redirection, parses the OIDC callback, stores the tokens, and attaches the JWT
access_tokento API calls. - Identity Server (Fabrixly-IDS): Authenticates users and issues standard OIDC JWT tokens.
- Backend (Node.js): Validates incoming JWT tokens in the
Authorizationheader and serves protected API responses.
Part A: Frontend Setup (React)
For React, we use the standard, secure react-oidc-context library which supports Authorization Code Flow with PKCE.
1. Install Dependencies
npm install oidc-client-ts react-oidc-context
2. Configure the AuthProvider
Wrap your application in the AuthProvider from react-oidc-context.
Create src/main.jsx:
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.jsx";
import { AuthProvider } from "react-oidc-context";
const oidcConfig = {
authority: "https://ids.fabrixly.com/oidc",
client_id: "your-react-client-id", // Registered in Admin Console
redirect_uri: "http://localhost:5173/callback",
response_type: "code",
scope: "openid profile email offline_access",
onSigninCallback: () => {
// Clear URL parameters after successful login redirect
window.history.replaceState({}, document.title, window.location.pathname);
}
};
ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
<AuthProvider {...oidcConfig}>
<App />
</AuthProvider>
</React.StrictMode>
);
3. Implement Login & User Profile
Create src/App.jsx:
import React, { useEffect, useState } from "react";
import { useAuth } from "react-oidc-context";
function App() {
const auth = useAuth();
const [apiMessage, setApiMessage] = useState("");
if (auth.isLoading) return <div>Loading auth...</div>;
if (auth.error) return <div>Authentication Error: {auth.error.message}</div>;
const callProtectedApi = async () => {
try {
const response = await fetch("http://localhost:3000/api/protected", {
headers: {
Authorization: `Bearer ${auth.user?.access_token}`
}
});
const data = await response.json();
setApiMessage(data.message || data.error);
} catch (err) {
setApiMessage("Failed to connect to Node.js backend");
}
};
if (auth.isAuthenticated) {
return (
<div style={{ padding: "40px" }}>
<h1>Welcome, {auth.user?.profile.name}! π</h1>
<p>Email: {auth.user?.profile.email}</p>
<button onClick={() => auth.removeUser()}>Log Out</button>
<hr />
<button onClick={callProtectedApi}>Call Node.js Protected API</button>
{apiMessage && <p><strong>API Response:</strong> {apiMessage}</p>}
</div>
);
}
return (
<div style={{ padding: "40px", textAlign: "center" }}>
<h1>React + Fabrixly-IDS π</h1>
<button onClick={() => auth.signinRedirect()}>Sign In with Fabrixly</button>
</div>
);
}
export default App;
Part B: Backend Setup (Node.js + Express)
The backend acts as a Resource Server that validates OIDC JWT access tokens issued by Fabrixly-IDS using standard JSON Web Key Sets (JWKS).
1. Install Dependencies
npm install express cors jsonwebtoken jwks-rsa
2. Implement JWT Validation Middleware
Create server.js:
const express = require("express");
const cors = require("cors");
const jwt = require("jsonwebtoken");
const jwksClient = require("jwks-rsa");
const app = express();
app.use(cors());
app.use(express.json());
const IDS_ISSUER = "https://ids.fabrixly.com/oidc";
// Configure JWKS client to retrieve cryptographic signing keys dynamically
const client = jwksClient({
jwksUri: `${IDS_ISSUER}/jwks`,
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 10
});
function getKey(header, callback) {
client.getSigningKey(header.kid, (err, key) => {
if (err) return callback(err);
const signingKey = key.getPublicKey();
callback(null, signingKey);
});
}
// Authentication Middleware
const requireAuth = (req, res, next) => {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith("Bearer ")) {
return res.status(401).json({ error: "Missing or invalid authorization token" });
}
const token = authHeader.split(" ")[1];
jwt.verify(token, getKey, {
issuer: IDS_ISSUER,
algorithms: ["RS256"]
}, (err, decoded) => {
if (err) {
return res.status(403).json({ error: "Token validation failed: " + err.message });
}
req.user = decoded; // Contains sub (userId), email, scope, etc.
next();
});
};
// Protected API Endpoint
app.get("/api/protected", requireAuth, (req, res) => {
res.json({
message: `Hello from Node.js! Your user ID is ${req.user.sub}.`
});
});
app.listen(3000, () => console.log("Backend running on http://localhost:3000"));
Part C: Registering the Client in Admin Console
- Navigate to the Clients section of your Fabrixly-IDS Admin Console.
- Click Create Client and fill in the properties:
- Client Name:
React Client App - Grant Types:
authorization_code,refresh_token - Response Types:
code - Redirect URIs:
http://localhost:5173/callback - Token Endpoint Auth Method:
none(required for SPAs / public clients)
- Client Name:
- Save the configurations. You're ready to test!