Skip to content

Repository description for oidc-auth-demo-app: Demo web application that contrasts guest and authenticated service access, featuring a React SPA frontend and a Spring Boot backend API secured via OIDC login/logout.

License

Notifications You must be signed in to change notification settings

rhofkens/oidc-auth-react-springboot-demo

Repository files navigation

AI-Developed OIDC Auth Demo (React + Spring Boot)

CI License: MIT React Spring Java TypeScript

What This Project Does

This project is a minimal web application designed to visually demonstrate the difference between guest and authenticated user access to backend services using OpenID Connect (OIDC). It serves as a practical example and base implementation for integrating standard OIDC authentication flows in a modern web stack.

Key Features:

  • Guest vs. Authenticated Views: Clearly shows different UI states and data access based on whether the user is logged in or browsing as a guest.
  • OIDC Integration: Implements standard OIDC Authorization Code flow with PKCE for secure authentication against an OIDC provider (configured for Zitadel).
  • Frontend-Backend Interaction: Features a React frontend that interacts with a Spring Boot backend API.
  • Protected Resources: Includes a public API endpoint accessible to everyone and a private endpoint requiring authentication.
  • Session Management: Demonstrates handling of authentication tokens and session persistence across browser refreshes.

Technology Stack:

  • Backend: Java 21, Spring Boot 3.4.4, Spring Security 6 (Resource Server), Maven
  • Frontend: React 19, TypeScript, Vite, Tailwind CSS, shadcn/ui, oidc-client-ts
  • Authentication: OIDC (Authorization Code + PKCE), JWT validation

Why and How This Project Was Developed

This project was developed with a specific goal: to create an enterprise-grade, reusable authentication package using a fully automated AI-native coding workflow.

  • Goal: The primary objective was to build a robust foundation for OIDC authentication that adheres to modern best practices, achieves high test coverage (≥80%), includes comprehensive documentation, and can be readily adapted for real-world enterprise projects. A secondary goal was to establish and refine a clear, repeatable workflow for AI-driven software development using VScode and Roo Code.
  • Process:
    • The initial Product Requirements Document (PRD), Architecture Guidelines, Coding Guidelines, and High-Level Plan were drafted using ChatGPT with o3.
    • From that point, the entire implementation followed a strictly automated flow defined in .clinerules and .roomodes, executed by Roo Code.
    • While highly automated, the workflow incorporated deliberate human review checkpoints at key stages (e.g., after planning subtasks for each implementation step). This ensured alignment and allowed for course correction where needed, keeping the human developer in control.
  • AI Models Used: The core coding tasks were performed by Large Language Models, specifically Anthropic's Sonnet 3.7 and Google's Gemini Pro (preview-03-25). While both were effective, the code generated by Gemini Pro was often preferred, though it came at a higher operational cost.
  • Outcome: The development process achieved a high degree of automation (estimated at 97%+), successfully producing the target application according to the predefined specifications and quality gates. It validated the AI-native workflow as a viable approach for building quality software components efficiently.

Prerequisites

  • JDK 21
  • Node.js 20
  • pnpm (latest version)

Project Structure

This is a monorepo containing:

  • backend/: Spring Boot 3.4.4 application (Java 21)
  • frontend/: React 19 application with TypeScript, Vite, and Tailwind CSS
  • docs/: Project documentation, including PRD, architecture, guidelines, and implementation plans.

Getting Started

Backend

cd backend
# Ensure .env file is configured (see Environment Variables section)
./mvnw spring-boot:run

The backend will start on http://localhost:8080.

Frontend

cd frontend
pnpm install
# Ensure .env file is configured (see Environment Variables section)
pnpm dev

The frontend development server will start on http://localhost:5173.

Note: The frontend dev server includes a proxy configuration that forwards all /api requests to the backend server running on port 8080. Make sure the backend server is running when developing the frontend.

Guest Mode Caching

The frontend implements a caching mechanism for the public health check endpoint in guest mode.

  • The response from /api/v1/public/health is stored in the browser's sessionStorage.
  • If the backend is unavailable when the page loads, the UI will display the last known status from the cache ("stale data") instead of showing an error immediately.
  • During development, if you need to clear this cache to fetch fresh data, you can do so via your browser's developer tools (usually under the "Application" or "Storage" tab, look for sessionStorage).

Environment Variables

This project uses environment variables for configuration, particularly for OIDC authentication details.

Frontend Configuration (Vite):

  • The frontend uses a standard .env file located at frontend/.env.
  • A template file frontend/.env.example lists the required variables (like VITE_ZITADEL_ISSUER_URI, VITE_ZITADEL_CLIENT_ID).
  • To configure:
    1. Copy frontend/.env.example to frontend/.env.
    2. Edit frontend/.env with your actual Zitadel frontend application details.

Backend Configuration (Spring Boot):

  • The backend reads configuration from actual environment variables set in your system or terminal session. It does not automatically read from .env files.
  • The .env.example file in the project root serves as a template listing the variables the backend expects (like ZITADEL_AUTHDEMO_ISSUER_URI, ZITADEL_AUTHDEMO_BACKEND_CLIENT_ID, ZITADEL_AUTHDEMO_CLIENT_SECRET).
  • To configure:
    1. Refer to .env.example for the required variable names.
    2. Set these variables in your environment before launching the backend. Examples:
      • Linux/macOS (bash/zsh):
        export ZITADEL_AUTHDEMO_ISSUER_URI="https://your-issuer..."
        export ZITADEL_AUTHDEMO_BACKEND_CLIENT_ID="your-backend-id"
        export ZITADEL_AUTHDEMO_CLIENT_SECRET="your-secret"
        cd backend
        ./mvnw spring-boot:run
      • Windows (PowerShell):
        $env:ZITADEL_AUTHDEMO_ISSUER_URI="https://your-issuer..."
        $env:ZITADEL_AUTHDEMO_BACKEND_CLIENT_ID="your-backend-id"
        $env:ZITADEL_AUTHDEMO_CLIENT_SECRET="your-secret"
        cd backend
        ./mvnw spring-boot:run
    3. Alternatively, configure them via your IDE's run configuration settings.

Important: Environment variables (especially secrets like ZITADEL_AUTHDEMO_CLIENT_SECRET) should be handled securely. The .env files are listed in .gitignore and should never be committed to the repository.

Running with OIDC

The frontend application uses the OpenID Connect (OIDC) Authorization Code flow with Proof Key for Code Exchange (PKCE) for user authentication. This is implemented using the oidc-client-ts library.

To run the application with OIDC authentication enabled, you need to configure the following environment variables in the frontend/.env file (refer to frontend/.env.example for the format):

  • VITE_ZITADEL_ISSUER_URI: The URI of your Zitadel instance.
  • VITE_ZITADEL_CLIENT_ID: The Client ID of your Zitadel application.
  • VITE_ZITADEL_SCOPES: The OIDC scopes required by the application (e.g., openid profile email private.read).

Additionally, ensure your Zitadel client application is configured with the following settings:

  • Application Type: User Agent
  • Authentication Method: None (PKCE is used)
  • Redirect URIs: http://localhost:5173/auth/callback
  • Post Logout URIs: http://localhost:5173/

Testing

Backend

Run the tests:

cd backend
./mvnw test

Run tests with coverage report:

cd backend
./mvnw verify

This will run the tests and generate a coverage report in backend/target/site/jacoco/. You can open backend/target/site/jacoco/index.html in a browser to view the detailed coverage report.

To check if coverage meets the required threshold (80%):

cd backend
./mvnw verify -Pcoverage-check

Frontend

Run the tests:

cd frontend
pnpm test

Run tests in watch mode during development:

cd frontend
pnpm test:watch

Run tests with coverage report:

cd frontend
pnpm test:coverage

This will run the tests and generate a coverage report in frontend/coverage/. You can open frontend/coverage/index.html in a browser to view the detailed coverage report.

The coverage thresholds are configured to require at least 80% coverage for statements, branches, functions, and lines.

Development

  • The backend uses Spotless for code formatting. Run ./mvnw spotless:apply to format the code.
  • The frontend uses ESLint and Prettier for linting and formatting. Run pnpm lint and pnpm format to lint and format the code.
  • Pre-commit hooks are set up using lint-staged and husky to ensure code quality before commits.

API Endpoints

Health Check (Public)

curl -X GET http://localhost:8080/api/v1/public/health

Example response:

{
  "message": "Service up"
}

### Private Info (Requires Authentication)

```bash
# Replace <your_jwt_token> with a valid access token obtained via OIDC login
curl -H "Authorization: Bearer <your_jwt_token>" http://localhost:8080/api/v1/private/info

Example response (if authorized):

{
  "message": "Hello John Doe (from UserInfo)",
  "email": "user@example.com"
}

Note: The actual message will contain the first and last name retrieved from the OIDC provider's UserInfo endpoint.

You can obtain a test token by logging into the frontend application, which stores the access token. You can inspect network requests or use browser developer tools to find the token.

About

Repository description for oidc-auth-demo-app: Demo web application that contrasts guest and authenticated service access, featuring a React SPA frontend and a Spring Boot backend API secured via OIDC login/logout.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages