Share
## https://sploitus.com/exploit?id=EF265F74-C4A5-5AEB-B284-BDDD596A2412
# OIDC SSO Proof of Concept

Proof of concept for bidirectional SSO between a .NET app (Auth0) and a Python FastAPI app (Keycloak) using OIDC Authorization Code flow.

See [spec.md](./spec.md) for detailed requirements UI flows.

## Architecture Overview

```mermaid
graph TB
        Auth0[Auth0]
        Keycloak[Keycloak Docker
localhost:8080]
        AppA[App A
ASP.NET Core 8
localhost:5001]
        AppB[App B
FastAPI
localhost:8000]

    AppA -->|OIDC| Auth0
    AppB -->|OIDC| Keycloak
    Auth0 |Brokered OIDC| Keycloak
    AppA |SSO Nav| AppB
```

## Setup Guide

### 1) Prerequisites

- Docker Desktop or Docker Engine with `docker compose`
- An Auth0 free tenant (sign up at https://auth0.com/)
- A tunnel for Keycloak (ngrok, Cloudflare Tunnel, or localhost.run)
- Auth0 CLI (`auth0`) logged in
- Python 3.12+

### 2) Auth0: Tenant and Organization

1. Create a free Auth0 tenant.
2. Create an Organization (or use an existing one).
3. Record the Organization ID as `AUTH0_ORGANIZATION_ID` in `.env`.
4. In the Organization's Connections tab, enable the default database connection.

### 3) Auth0: App A (OIDC client)

1. Applications -> Create Application -> Regular Web Applications.
2. Name: `OIDC SSO POC - App A`.
3. Configure settings:
   - Allowed Callback URLs: `https://localhost:5001/callback`
   - Allowed Logout URLs: `https://localhost:5001`
   - Allowed Web Origins: `https://localhost:5001`
4. **Important**: In "Login Experience" select "Business users" under "Types of users". This enables the Organization feature for multi-tenanting.
5. Enable this application in the Organization's Connections.
6. Record the Domain, Client ID, and Client Secret.
7. Record the Application ID as `AUTH0_APP_A_ID`  in `.env`.

### 4) Keycloak public URL (required for Auth0)

Auth0 must reach Keycloak over the public internet for the B->A flow.

1. Start a tunnel to port 8080.
2. Copy the public URL (for example `https://abc123.ngrok-free.app`).
3. You will use this URL in Auth0 and in `KEYCLOAK_DOMAIN`.

### 5) Auth0: Keycloak broker application

1. Applications -> Create Application -> Regular Web Applications.
2. Name: `OIDC SSO POC - Keycloak Broker`.
3. Configure settings using the public Keycloak URL:
   - Allowed Callback URLs: `https:///realms/sso-poc/broker/auth0/endpoint`
   - Allowed Web Origins: `https://`
4. Save and record:
   - Client ID as `AUTH0_BROKER_CLIENT_ID`
   - Client Secret as `AUTH0_BROKER_CLIENT_SECRET`
   - Application ID as `AUTH0_KEYCLOAK_BROKER_APP_ID`
5. In "Login Experience" select "Business users" under "Types of users"

### 6) Auth0: Create a test user

1. User Management -> Users -> Create User.
2. Email: `loris@fundapps.co` (must match the mock user store).
3. Set a password and mark email as verified.

### 7) Auth0: Enterprise connection (Keycloak)

1. Authentication -> Enterprise -> OpenID Connect.
2. Create a connection:
   - Name: `keycloak-sso` (matches `AUTH0_KEYCLOAK_CONNECTION_NAME`)
   - Issuer URL: `https:///realms/sso-poc/.well-known/openid-configuration`
   - Client ID: `auth0-broker`
   - Client Secret: copy from the Keycloak realm export for `auth0-broker`.
3. Enable this connection for the `OIDC SSO POC - App A` application.
4. In the Organization's Connections tab, enable this enterprise connection.

### 8) Local configuration

1. Copy `.env.example` to `.env`.
2. Fill in Auth0 values:
   - `AUTH0_DOMAIN`, `AUTH0_CLIENT_ID`, `AUTH0_CLIENT_SECRET`
   - `AUTH0_BROKER_CLIENT_ID`, `AUTH0_BROKER_CLIENT_SECRET`
   - `AUTH0_ORGANIZATION_ID`
   - `AUTH0_KEYCLOAK_CONNECTION_NAME=keycloak-sso`
   - `AUTH0_KEYCLOAK_BROKER_APP_ID` (Auth0 app ID for the Keycloak Broker app)
   - `AUTH0_APP_A_ID` (Auth0 app ID for the App A application)
3. Set `KEYCLOAK_CLIENT_SECRET` to a random string.
4. Set `KEYCLOAK_DOMAIN` to your public Keycloak URL.

### 9) Automated tunnel + Auth0 update

The helper script starts a localhost.run tunnel, updates `KEYCLOAK_DOMAIN` in `.env`,
updates the Auth0 App A application, the Auth0 broker app, and the enterprise connection,
then starts containers.

```bash
python3 ./start_poc.py
```

For safety, use dry-run to capture the URL and update `.env` only:

```bash
python3 ./start_poc.py --dry-run
```

### 10) Test flows

1. Visit `https://localhost:5001` (accept the cert warning).
2. Log in with `loris@fundapps.co`.
3. Click "Go to Python App" and confirm no login prompt.
4. Visit `http://localhost:8000` directly and log in with Keycloak user `loris`.
5. Click "Go to .NET App" and confirm no login prompt.

## Simplifying Local User Setup

Current setup requires:
- Auth0 user `loris@fundapps.co`
- Keycloak user `loris`
- Both apps have a fixed mock user store

If this is too cumbersome, a simpler option is to make both apps accept any user
that has a verified email claim, and display a warning banner when the email is
not in the mock store. This removes the need to pre-create matching local users
for basic demo flows while still showing how authorization data could be enforced.

## Notes

- This is a proof of concept and not production-ready.
- Auth0 cannot reach `localhost`, so B->A flow requires a public Keycloak URL.
- App A uses a self-signed HTTPS certificate.