Skip to content

cld2labs/AccessIQ

Repository files navigation

Company Logo

AccessIQ — Authorization-Aware Chatbot

Intelligent Role-Based Data Access Control Blueprint


Table of Contents


Project Overview

AccessIQ is an authorization-aware chatbot for protected data access. Users authenticate with Auth0, submit prompts through a React frontend, and receive responses only after the backend validates identity, interprets intent with LangGraph, and checks authorization through MCP before touching protected data in PostgreSQL.

This makes AccessIQ suitable for:

  • Authorization demos where natural language must remain inside strict access boundaries
  • Secure application prototypes that need a clean separation between authentication, orchestration, policy, and data access
  • Security-focused chatbot workflows where the LLM can assist with intent and response wording but never grant access
  • Role- and attribute-based access control experiments using Auth0 claims plus resource metadata

Core system rule:

Auth0 -> Backend -> LangGraph -> MCP -> PostgreSQL -> Response


How It Works

  1. A user logs in through Auth0 Universal Login.
  2. Auth0 returns a JWT containing trusted identity and namespaced access claims.
  3. The React frontend sends the prompt and bearer token to the FastAPI backend.
  4. The backend validates the JWT and normalizes user context.
  5. LangGraph interprets the request and maps it to an action and resource type.
  6. The backend performs a metadata-first authorization check through the MCP service.
  7. If access is allowed, the backend queries PostgreSQL for authorized data only.
  8. The backend returns a grounded response to the frontend.
  9. If access is denied, the system returns a safe denial response without exposing protected content.

Architecture

AccessIQ uses a four-service local deployment: React frontend, FastAPI backend, dedicated MCP policy service, and PostgreSQL. Auth0 is the identity provider, while LangGraph coordinates request understanding and response generation inside the backend flow.

Architecture Diagram

graph TB
    subgraph "User Interface (port 3000)"
        A[React Frontend]
        A1[Login]
        A2[Chat UI]
        A3[Reports UI]
    end

    subgraph "Identity"
        B[Auth0]
    end

    subgraph "Backend API (port 8000)"
        C[FastAPI Backend]
        C1[JWT Validation]
        C2[LangGraph Orchestration]
        C3[Metadata-First Access Flow]
    end

    subgraph "Authorization (port 9000)"
        D[MCP Service]
        D1[RBAC + ABAC Policy]
    end

    subgraph "Data (port 5432)"
        E[PostgreSQL]
        E1[reports table]
    end

    A1 --> B
    B --> A
    A2 --> C
    A3 --> C
    C --> C1
    C1 --> C2
    C2 --> C3
    C3 --> D
    D --> C3
    C3 --> E
    E --> C
    C --> A

    style A fill:#e1f5ff,color:#000
    style B fill:#fdf2e9,color:#000
    style C fill:#fff4e1,color:#000
    style D fill:#e8f5e9,color:#000
    style E fill:#f3e5f5,color:#000
Loading

Architecture Components

Frontend (React + Vite)

  • Auth0 login/logout flow
  • Chat interface for protected requests
  • Token forwarding to the backend
  • Safe rendering of authorized data and denied states

Backend (FastAPI)

  • Validates Auth0 JWTs
  • Normalizes trusted user context
  • Invokes LangGraph for intent understanding
  • Calls MCP before protected actions
  • Queries PostgreSQL only after authorization succeeds

MCP Service

  • Central authorization decision point
  • Combines RBAC and ABAC
  • Returns allow or deny, plus filters for list access when needed

PostgreSQL

  • Stores protected reports
  • Stores authorization-relevant resource metadata such as owner_id, department, and sensitivity

Auth0

  • Handles user authentication
  • Stores access-related attributes in app_metadata
  • Injects namespaced claims into tokens via a Post Login Action

Service Components

Service Container Host Port Description
frontend frontend 3000 React client for login, chat, and reports UI
backend backend 8000 FastAPI API, LangGraph orchestration, Auth0 validation, DB access
mcp mcp 9000 Authorization service enforcing RBAC + ABAC
postgres postgres 5432 PostgreSQL database storing protected reports

Typical Flow

  1. User logs in through Auth0.
  2. Frontend calls the backend with the Auth0 bearer token.
  3. Backend validates the token and extracts role, department, and clearance_level.
  4. LangGraph interprets the request.
  5. Backend calls MCP with user, action, and resource metadata.
  6. MCP returns allow or deny.
  7. Backend reads only authorized records from PostgreSQL.
  8. Frontend renders the final response or a safe denial message.

Get Started

Prerequisites

Before you begin, make sure you have:

  • Docker Desktop with Docker Compose
  • An Auth0 tenant
  • An OpenAI API key
  • **psql** installed locally if you want to run the seed script directly from your machine

Verify Installation

docker --version
docker compose version
docker ps
psql --version

Quick Start (Docker Deployment)

1. Clone the Repository

git clone <your-repo-url>
cd <repo-folder>

2. Configure the Environment

Create both environment files:

cp .env.example .env
cp backend/.env.example backend/.env

Populate the files with your Auth0, database, MCP, and OpenAI values.

Root .env:

VITE_AUTH0_DOMAIN=your-tenant.us.auth0.com
VITE_AUTH0_CLIENT_ID=YOUR_AUTH0_SPA_CLIENT_ID
VITE_AUTH0_AUDIENCE=https://api.yourapp.local
VITE_AUTH0_REDIRECT_URI=http://localhost:3000
VITE_API_BASE_URL=http://localhost:8000

POSTGRES_DB=appdb
POSTGRES_USER=app
POSTGRES_PASSWORD=app
POSTGRES_PORT=5432

MCP_PORT=9000
MCP_LOG_LEVEL=INFO
MCP_POLICY_MODE=development

backend/.env:

AUTH0_DOMAIN=your-tenant.us.auth0.com
AUTH0_AUDIENCE=https://api.yourapp.local
AUTH0_ISSUER=https://your-tenant.us.auth0.com/
AUTH0_CLIENT_ID=YOUR_AUTH0_M2M_CLIENT_ID
AUTH0_CLIENT_SECRET=YOUR_AUTH0_M2M_CLIENT_SECRET
AUTH0_CLAIM_NAMESPACE=https://your-app.example

DATABASE_URL=postgresql+psycopg://app:app@postgres:5432/appdb

MCP_BASE_URL=http://mcp:9000
MCP_TIMEOUT_SECONDS=5

OPENAI_API_KEY=YOUR_OPENAI_API_KEY
OPENAI_MODEL=gpt-4o-mini

LANGGRAPH_DEBUG=false
APP_ENV=development
APP_PORT=8000
LOG_LEVEL=INFO

3. Configure Auth0

Create these Auth0 resources:

  1. A Single Page Application for the React frontend
  2. An API for the FastAPI backend audience
  3. A Machine to Machine Application for Auth0 Management API access

Auth0 SPA settings:

  • Allowed Callback URLs: http://localhost:3000
  • Allowed Logout URLs: http://localhost:3000
  • Allowed Web Origins: http://localhost:3000
  • Allowed Origins (CORS): http://localhost:3000

For each test user, set access attributes in app_metadata:

{
  "app_metadata": {
    "role": "employee",
    "department": "sales",
    "clearance_level": 1
  }
}

Supported roles in this project:

  • admin
  • manager
  • employee

4. Configure the Auth0 Post Login Action

Use [auth0/actions/post-login.js](/Users/csuftitan/Desktop/c2l/MCPRBAC/auth0/actions/post-login.js) as your Auth0 Post Login Action.

The action should:

  • read event.user.app_metadata
  • require role, department, and clearance_level
  • inject namespaced claims into the ID token and access token
  • deny login if required metadata is missing

Add an Auth0 Action secret:

  • AUTH0_CLAIM_NAMESPACE

Set it to the same value used in [backend/.env.example](/Users/csuftitan/Desktop/c2l/MCPRBAC/backend/.env.example), for example:

https://your-app.example

Then bind the action to the Post Login flow in Auth0.

5. Build and Start the Application

docker compose -f compose.yml up --build

Detached mode:

docker compose -f compose.yml up -d --build

6. Initialize and Seed the Database

In a second terminal:

./scripts/seed_sample_data.sh

This will:

  • create the reports table from [scripts/init.sql](/Users/csuftitan/Desktop/c2l/MCPRBAC/scripts/init.sql)
  • seed sample reports from [scripts/seed_sample_data.sql](/Users/csuftitan/Desktop/c2l/MCPRBAC/scripts/seed_sample_data.sql)

7. Access the Application

Once the stack is running:

8. Verify Services

curl http://localhost:8000/health
curl http://localhost:9000/health
docker compose -f compose.yml ps

Useful logs:

docker compose -f compose.yml logs -f
docker compose -f compose.yml logs -f backend
docker compose -f compose.yml logs -f frontend
docker compose -f compose.yml logs -f mcp

9. Stop the Application

docker compose -f compose.yml down

Local Development Setup

Run the services directly on your machine if you do not want to use Docker for frontend and backend iteration.

Backend

cd backend
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

Frontend

cd frontend
npm install
npm run dev -- --host 0.0.0.0 --port 3000

MCP

cd mcp
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --reload --host 0.0.0.0 --port 9000

PostgreSQL can still run through Docker if preferred.


Project Structure

AccessIQ/
├── auth0/
│   └── actions/
│       └── post-login.js
├── backend/
│   ├── app/
│   │   ├── api/routes/
│   │   ├── db/
│   │   ├── schemas/
│   │   └── services/
│   ├── tests/
│   ├── Dockerfile
│   ├── requirements.txt
│   └── .env.example
├── docs/
│   ├── architecture.md
│   ├── auth0.md
│   ├── backend.md
│   ├── api.md
│   ├── mcp.md
│   ├── database.md
│   ├── frontend.md
│   ├── deployment.md
│   ├── env.md
│   ├── langgraph.md
│   └── security.md
├── frontend/
│   ├── src/
│   │   ├── components/
│   │   ├── lib/
│   │   ├── pages/
│   │   └── App.jsx
│   ├── Dockerfile
│   ├── package.json
│   └── vite.config.js
├── mcp/
│   ├── app/
│   ├── tests/
│   ├── Dockerfile
│   └── requirements.txt
├── scripts/
│   ├── init.sql
│   ├── seed_sample_data.sql
│   └── seed_sample_data.sh
├── compose.yml
├── .env.example
└── README.md

Usage Guide

Authenticate

  1. Open http://localhost:3000.
  2. Click the login button.
  3. Complete Auth0 Universal Login.
  4. Return to the app with a valid session.

Use the chatbot

  1. Enter a request such as Show me the HR team report.
  2. The frontend sends the prompt and bearer token to POST /chat.
  3. The backend validates the token, checks MCP, and returns the result.
  4. If authorized, you see grounded content.
  5. If denied, you see a safe access-denied response.

Browse reports

  • GET /reports
  • GET /reports/{id}
  • DELETE /reports/{id} for authorized users only

Admin flow

  • POST /admin/users creates Auth0 users through the backend using the Auth0 Management API

Useful protected endpoints:

  • GET /me
  • POST /chat
  • GET /reports
  • GET /reports/{report_id}
  • DELETE /reports/{report_id}
  • POST /admin/users

Authorization Model

AccessIQ uses RBAC + ABAC through the MCP service.

RBAC

  • admin has broad access
  • manager is department-scoped
  • employee is owner-scoped

ABAC

Authorization decisions also depend on:

  • department
  • clearance_level
  • owner_id
  • sensitivity

Important system rules:

  • Auth0 is the only identity source
  • MCP is the only authorization authority
  • Backend enforces all protected access
  • LangGraph interprets requests but does not grant access
  • The LLM never decides permissions
  • Deny by default when inputs or policy are unclear

Auth0 Configuration

AccessIQ expects custom namespaced claims from Auth0. A typical token should include:

{
  "sub": "auth0|123",
  "https://your-app.example/role": "manager",
  "https://your-app.example/department": "sales",
  "https://your-app.example/clearance_level": 2
}

The backend normalizes these into:

{
  "id": "auth0|123",
  "role": "manager",
  "department": "sales",
  "clearance_level": 2
}

Minimum practical Auth0 Management API scopes for the backend admin user-creation flow:

  • create:users
  • read:users
  • update:users

Environment Variables

Root .env

This file is shared by:

  • frontend
  • postgres
  • mcp
  • backend for shared values
Variable Description
VITE_AUTH0_DOMAIN Auth0 tenant domain used by the frontend
VITE_AUTH0_CLIENT_ID Auth0 SPA client ID
VITE_AUTH0_AUDIENCE Backend API audience
VITE_AUTH0_REDIRECT_URI Local frontend callback URL
VITE_API_BASE_URL Browser-reachable backend URL
POSTGRES_DB PostgreSQL database name
POSTGRES_USER PostgreSQL username
POSTGRES_PASSWORD PostgreSQL password
POSTGRES_PORT PostgreSQL host port
MCP_PORT MCP service port
MCP_LOG_LEVEL MCP log level
MCP_POLICY_MODE MCP runtime mode

backend/.env

This file is backend-only and contains trusted service configuration.

Variable Description
AUTH0_DOMAIN Auth0 tenant domain
AUTH0_AUDIENCE Expected API audience
AUTH0_ISSUER Expected Auth0 issuer URL
AUTH0_CLIENT_ID Backend-related Auth0 client ID
AUTH0_CLIENT_SECRET Backend-related Auth0 client secret
AUTH0_CLAIM_NAMESPACE Namespace for custom claims
DATABASE_URL PostgreSQL connection string
MCP_BASE_URL MCP base URL
MCP_TIMEOUT_SECONDS MCP request timeout
OPENAI_API_KEY LLM provider API key
OPENAI_MODEL LLM model name
LANGGRAPH_DEBUG LangGraph debug flag
APP_ENV App environment
APP_PORT Backend listen port
LOG_LEVEL Backend log level

Inference Metrics

The table below summarizes the current OpenAI cloud inference benchmark for AccessIQ using the chatbot request path averaged over 3 runs.

Provider Model Deployment Context Window Avg Input Tokens Avg Output Tokens Avg Tokens / Request P50 Latency (ms) P95 Latency (ms) Throughput (req/s) Hardware
OpenAI (Cloud) gpt-4o-mini API (Cloud) 128K 1,417 162 1,579 3,180 5,950 0.241 N/A

Notes:

  • Input Tokens are the tokens sent into the final OpenAI response-generation step, including the response-writer instructions, the user's prompt, and the authorized data prepared by the backend after LangGraph orchestration, MCP authorization, and database retrieval.
  • Output Tokens are the tokens generated by OpenAI in the final natural-language response returned to the user.
  • MCP is part of the backend enforcement flow in AccessIQ, not an OpenAI tool call in the current implementation, so MCP authorization and database retrieval are part of the overall request path but are not themselves counted as model tokens.
  • Token counts and latency may vary slightly per run due to model non-determinism and differences in authorized data returned to the response generator.
  • gpt-4o-mini is configured through OPENAI_API_KEY and OPENAI_MODEL in backend/.env.

Model Capabilities

GPT-4o-mini

OpenAI's cost-efficient multimodal model, used here through the OpenAI API for AccessIQ response generation.

Attribute Details
Parameters Not publicly disclosed
Architecture Multimodal Transformer (text + image input, text output)
Context Window 128,000 tokens input / 16,384 tokens max output
Reasoning Mode Standard inference
Tool / Function Calling Supported
Structured Output JSON mode and schema-constrained output supported
Multilingual Broad multilingual support
Pricing $0.15 / 1M input tokens, $0.60 / 1M output tokens
Fine-Tuning Supported via OpenAI API
License Proprietary (OpenAI Terms of Use)
Deployment Cloud-only
Knowledge Cutoff October 2023

Comparison Summary

Capability GPT-4o-mini
Natural-language response generation Yes
Function / tool calling Yes
JSON structured output Yes
Cloud deployment Yes
On-prem / air-gapped deployment No
Multimodal support Yes
Native context window 128K

LLM Provider Configuration

OpenAI

Set the following values in backend/.env:

OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-4o-mini
OPENAI_TIMEOUT_SECONDS=10

Recommended model:

  • gpt-4o-mini

OPENAI_API_KEY enables the final natural-language response writer, while OPENAI_MODEL selects the OpenAI model used for that final response generation step.


Technology Stack

Backend

  • FastAPI for API routing and request handling
  • Uvicorn as the ASGI server
  • LangGraph for chatbot orchestration
  • SQLAlchemy / psycopg for PostgreSQL access
  • Auth0 JWT validation for trusted user identity

Frontend

  • React 18
  • Vite
  • Auth0 SPA integration

Infrastructure

  • Docker Compose for local multi-service orchestration
  • PostgreSQL 16 for protected resource storage
  • Dedicated MCP service for centralized authorization
  • Auth0 for authentication and claim injection

Troubleshooting

Common Issues

Login succeeds but backend rejects the token

Check:

  • AUTH0_AUDIENCE matches VITE_AUTH0_AUDIENCE
  • AUTH0_ISSUER is exactly https://<tenant-domain>/
  • AUTH0_CLAIM_NAMESPACE matches the Auth0 Action secret
  • the Post Login Action is attached to the Post Login flow

Login fails immediately after Auth0 authentication

The Post Login Action fails closed when required app_metadata is missing. Confirm the user has:

  • role
  • department
  • clearance_level

Frontend cannot reach backend

Check:

  • VITE_API_BASE_URL=http://localhost:8000
  • backend container is running
  • frontend is running on http://localhost:3000

Backend cannot create Auth0 users

Check:

  • Auth0 Management API scopes

Database seeding fails

Check:

  • PostgreSQL container is running
  • your .env Postgres values are correct
  • psql is available locally if you use ./scripts/seed_sample_data.sh

Protected access looks wrong

Check:

  • the user claims in Auth0
  • the report metadata in PostgreSQL
  • the MCP service health and logs
  • whether the request should be department-scoped, owner-scoped, or denied

License

This project is licensed under our LICENSE file for details.


Disclaimer

AccessIQ is provided as-is for demonstration and educational purposes. While we strive for accuracy:

  • Authorization behavior, generated responses, and orchestration flows should be reviewed by a qualified engineer before use in production systems
  • Do not rely solely on AI-generated responses without testing, validation, and policy review
  • Do not submit confidential or proprietary data to third-party API providers without reviewing their data handling policies
  • The quality of generated responses depends on the underlying model, prompts, authorization inputs, and available data

For full disclaimer details, see DISCLAIMER.md.

About

MCP-based authorization for protected data access using RBAC and ABAC.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors