# Keycloak API Access Guide

## Current Issue: 401 Unauthorized

The application is returning 401 because of a JWT issuer mismatch. Here's what's happening and how to fix it.

### Problem

- **Keycloak issues tokens with issuer**: `http://localhost:8080/realms/b2b-flight-platform`
- **Application expects issuer**: `http://keycloak:8080/realms/b2b-flight-platform` (Docker service name)

This mismatch causes JWT validation to fail.

### Solution Options

#### Option 1: Use Keycloak from Inside Docker (Recommended for Development)

Access Keycloak using the Docker service name from within the application container:

1. **Get a token from inside the app container**:
```bash
docker-compose exec app curl -s -X POST 'http://keycloak:8080/realms/b2b-flight-platform/protocol/openid-connect/token' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'client_id=b2b-flight-backend' \
  -d 'client_secret=b2b-flight-backend-secret' \
  -d 'username=superadmin' \
  -d 'password=admin123' \
  -d 'grant_type=password'
```

2. **Use that token to access the API from outside**:
```bash
TOKEN="<token_from_step_1>"
curl -X GET 'http://localhost:8081/api/backoffice/dashboard' \
  -H "Authorization: Bearer $TOKEN"
```

#### Option 2: Configure Keycloak Frontend URL

Configure Keycloak to use a consistent URL for both internal and external access:

1. **Update docker-compose.yml** to add Keycloak frontend URL:
```yaml
keycloak:
  environment:
    KC_HOSTNAME_URL: http://localhost:8080
    KC_HOSTNAME_ADMIN_URL: http://localhost:8080
```

2. **Restart Keycloak**:
```bash
docker-compose restart keycloak
```

3. **Update application configuration** to use localhost:
```yaml
KEYCLOAK_ISSUER_URI: http://localhost:8080/realms/b2b-flight-platform
KEYCLOAK_JWK_SET_URI: http://localhost:8080/realms/b2b-flight-platform/protocol/openid-connect/certs
```

4. **Restart the app**:
```bash
docker-compose restart app
```

#### Option 3: Use host.docker.internal (macOS/Windows)

On macOS and Windows, Docker provides `host.docker.internal` to access the host machine:

1. **Update docker-compose.yml**:
```yaml
app:
  environment:
    KEYCLOAK_ISSUER_URI: http://host.docker.internal:8080/realms/b2b-flight-platform
    KEYCLOAK_JWK_SET_URI: http://host.docker.internal:8080/realms/b2b-flight-platform/protocol/openid-connect/certs
```

2. **Get token from localhost** (as usual):
```bash
curl -X POST 'http://localhost:8080/realms/b2b-flight-platform/protocol/openid-connect/token' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'client_id=b2b-flight-backend' \
  -d 'client_secret=b2b-flight-backend-secret' \
  -d 'username=superadmin' \
  -d 'password=admin123' \
  -d 'grant_type=password'
```

3. **Use the token** to access the API.

### Quick Test Script

Here's a script that gets a token from inside Docker and tests the API:

```bash
#!/bin/bash

# Get token from inside Docker (correct issuer)
TOKEN=$(docker-compose exec -T app curl -s -X POST 'http://keycloak:8080/realms/b2b-flight-platform/protocol/openid-connect/token' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'client_id=b2b-flight-backend' \
  -d 'client_secret=b2b-flight-backend-secret' \
  -d 'username=superadmin' \
  -d 'password=admin123' \
  -d 'grant_type=password' | jq -r '.access_token')

echo "Token: ${TOKEN:0:50}..."
echo ""

# Test API from outside Docker
echo "Testing Dashboard:"
curl -s -X GET 'http://localhost:8081/api/backoffice/dashboard' \
  -H "Authorization: Bearer $TOKEN" | jq '.'

echo ""
echo "Testing Agencies:"
curl -s -X GET 'http://localhost:8081/api/agencies' \
  -H "Authorization: Bearer $TOKEN" | jq '.'
```

Save this as `test-api-docker.sh`, make it executable (`chmod +x test-api-docker.sh`), and run it.

### Current Credentials

- **Keycloak Admin Console**: http://localhost:8080
  - Username: `admin`
  - Password: `admin`

- **Test User**:
  - Username: `superadmin`
  - Password: `admin123`
  - Role: `SUPER_ADMIN`

- **Client**:
  - Client ID: `b2b-flight-backend`
  - Client Secret: `b2b-flight-backend-secret`

### API Endpoints

Once authenticated, you can access:

- **Dashboard**: `GET /api/backoffice/dashboard`
- **Agencies**: `GET /api/agencies`
- **System Config**: `GET /api/backoffice/configuration`
- **Create Agency**: `POST /api/agencies`
- **Flight Search**: `POST /api/flights/search`
- **Create Booking**: `POST /api/bookings`

### Swagger UI

Access Swagger UI at: http://localhost:8081/swagger-ui.html

Note: Swagger UI will also require authentication. You'll need to:
1. Click "Authorize" button
2. Enter the Bearer token (without "Bearer" prefix)
3. Click "Authorize"

### Troubleshooting

**Still getting 401?**

1. Check the application logs:
```bash
docker-compose logs app | grep -i "jwt\|401\|issuer"
```

2. Verify the token issuer matches:
```bash
# Get token
TOKEN=$(curl -s -X POST 'http://localhost:8080/realms/b2b-flight-platform/protocol/openid-connect/token' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'client_id=b2b-flight-backend' \
  -d 'client_secret=b2b-flight-backend-secret' \
  -d 'username=superadmin' \
  -d 'password=admin123' \
  -d 'grant_type=password' | jq -r '.access_token')

# Decode and check issuer
echo $TOKEN | cut -d'.' -f2 | base64 -d 2>/dev/null | jq -r '.iss'
```

3. Check what the app expects:
```bash
docker-compose exec app env | grep ISSUER
```

The issuer in the token must match the `KEYCLOAK_ISSUER_URI` environment variable.

## Recommended Solution for Your Setup

Since you're on macOS, I recommend **Option 3** (using host.docker.internal). This will work for both getting tokens from your host machine and validating them in the Docker container.

Let me know which option you'd like to implement, and I'll help you set it up!
