# Identity Provider

## What is Identity Provider?

An Identity Provider (IdP) is a system that creates, maintains, and manages identity information for users and provides authentication services to relying party applications. insureMO CAS can act as a standard Identity Provider, enabling third-party applications to authenticate users and obtain tokens via industry-standard protocols.

## OIDC Provider

> This section is intended for technical teams integrating third-party applications with the insureMO platform for identity authentication. The insureMO CAS service acts as a standard OpenID Connect Provider (OP), enabling third-party applications to authenticate users and obtain tokens via the standard OIDC protocol.

### Overview and Standards Compliance

insureMO CAS (Central Authentication Service) implements the standard **OpenID Connect Provider (OP)** role, allowing third-party applications (Relying Party / Service Provider) to authenticate users through the OIDC protocol.

| Standard/Specification | Compliance Status | Description |
|----------------------|-------------------|-------------|
| OpenID Connect Core 1.0 | Compliant | Supports Discovery, Authorization Code Flow, Token endpoint, UserInfo |
| OAuth 2.0 (RFC 6749) | Compliant | Supports `authorization_code` and `client_credentials` grant types |
| PKCE (RFC 7636) | Compliant | Supports S256 method; mandatory for Public Clients |
| RFC 8414 (Authorization Server Metadata) | Compliant | `/.well-known/oauth-authorization-server` |
| RFC 9728 (Protected Resource Metadata) | Compliant | `/.well-known/oauth-protected-resource` |
| JWT (RFC 7519) | Compliant | ID Token signed with RS256 |

**Core Architecture:**

```
Third-Party Application (Relying Party)
    |
    +-- 1. Discover: GET /.well-known/oauth-authorization-server
    |
    +-- 2. Authorize: GET /cas/oidc/authorize?client_id=xxx&redirect_uri=yyy&response_type=code
    |       |
    |       +-- User authenticates on the CAS login page
    |       |
    |       +-- 302 Redirect back: redirect_uri?code=AUTH_CODE&state=STATE
    |
    +-- 3. Exchange Token: POST /cas/oidc/token
    |       |  Body: grant_type=authorization_code&code=AUTH_CODE&client_id=xxx&client_secret=yyy
    |       |
    |       +-- Response: { access_token, id_token, token_type, expires_in }
    |
    +-- 4. Get User Info: GET /cas/oidc/userinfo
    |       Header: Authorization: Bearer {access_token}
    |       +-- Response: { sub, name, email, ... }
    |
    +-- 5. Validate Token: Call Validated Token API
```

### Endpoint Summary

All OIDC Provider endpoints are accessed via the gateway URL.

| Endpoint | Path | Method | Description |
|----------|------|--------|-------------|
| Authorization Server Metadata (RFC 8414) | `/.well-known/oauth-authorization-server` | GET | **Discovery endpoint** (returns all OIDC/OAuth 2.0 configuration) |
| Protected Resource Metadata (RFC 9728) | `/.well-known/oauth-protected-resource` | GET | Protected resource discovery |
| Token Validation | `/cas/validate-token` | GET | Validates token and returns user information |
| Authorization | `/cas/oidc/authorize` | GET / POST | Authorization endpoint |
| Token | `/cas/oidc/token` | POST | Token endpoint |
| UserInfo | `/cas/oidc/userinfo` | GET / POST | User information endpoint |
| Logout | `/cas/oidc/logout` | GET | Logout endpoint |

> **Important:** Use the Discovery endpoint to automatically obtain the complete OIDC/OAuth 2.0 configuration.

### Discovery Endpoint

External clients should use this endpoint to retrieve the complete OIDC Provider configuration:

```
GET {gateway_url}/.well-known/oauth-authorization-server
```

**Response Example:**

```json
{
  "issuer": "https://{gateway_url}/cas",
  "authorization_endpoint": "https://{gateway_url}/cas/oidc/authorize",
  "token_endpoint": "https://{gateway_url}/cas/oidc/token",
  "userinfo_endpoint": "https://{gateway_url}/cas/oidc/userinfo",
  "token_validation_endpoint": "https://{gateway_url}/cas/validate-token",
  "scopes_supported": ["openid", "profile", "email"],
  "response_types_supported": ["code", "token", "id_token", "token id_token"],
  "grant_types_supported": ["authorization_code", "client_credentials"],
  "token_endpoint_auth_methods_supported": ["client_secret_basic", "none"],
  "code_challenge_methods_supported": ["S256"],
  "subject_types_supported": ["public"],
  "id_token_signing_alg_values_supported": ["RS256"],
  "claims_supported": ["sub", "name", "nickname", "preferred_username", "email"]
}
```

### Client Application Registration and Configuration

OIDC client applications are configured by tenant administrators through the Portal management interface. Upon registration, you will receive a `client_id` and `client_secret` (if applicable).

**Navigation:** Log in to Portal -> **SSO Config -> Applications** -> Create an OIDC-type application.

| Parameter | JSON Field | Type | Required | Description |
|-----------|------------|------|----------|-------------|
| Client ID | `client_id` | string | System-generated | Unique client identifier, auto-generated by the system |
| Client Secret | `client_secret` | string | System-generated | Client secret; not available for Public Client (`auth_method=none`) |
| Sign-in Redirect URL | `signin_redirect_url` | string | Required for authorization_code | OIDC authorization code callback URL |
| Sign-out Redirect URL | `signout_redirect_url` | string | No | OIDC logout callback URL |
| Grant Type | `grant_type` | string | Yes | `authorization_code` / `client_credentials` / `password` |
| Token Endpoint Auth Method | `token_endpoint_auth_method` | string | Yes | `client_secret_basic` (default) / `private_key_jwt` / `none` (Public Client) |
| User Source ID | `user_source_id` | string | No | Default: `"mo"` |
| Default User | `default_user` | string | Required for client_credentials | Machine user identifier for M2M scenarios |
| Allowed Access Tenants | `allowed_access_tenants` | string | No | Comma-separated list of tenant codes |
| Tenant Code | `tenant_code` | string | Yes | Tenant to which the client belongs |
| Application Name | `app_name` | string | No | Application name (for management identification) |

| Type | `token_endpoint_auth_method` | `client_secret` | PKCE | Use Case |
|------|---------------------------|----------------|------|---------|
| Confidential Client | `client_secret_basic` | Available | Optional | Server-side applications (Web backend) |
| Public Client | `none` | Not available | **Mandatory** | SPA, mobile apps, CLI tools |

### Authorization Code Flow

The Authorization Code Flow is the most commonly used and secure OIDC authentication flow, suitable for applications with a server-side component.

```mermaid
sequenceDiagram
    participant User as User Browser
    participant App as Third-Party App (Backend)
    participant CAS as CAS (OIDC Provider)

    User->>App: 1. Visit app
    App-->>User: 2. 302 redirect to CAS<br/>GET /cas/oidc/authorize?client_id=xxx&redirect_uri=yyy&response_type=code&state=zzz
    User->>CAS: 3. CAS login page<br/>(User enters credentials)
    CAS-->>User: 4. 302 redirect back to app<br/>redirect_uri?code=AUTH_CODE&state=zzz
    User->>App: 5. Callback with code
    App->>CAS: 6. Exchange code for token<br/>POST /cas/oidc/token
    CAS-->>App: { access_token, id_token, ... }
    App-->>User: 7. Return user data
```

**Step 1: Initiate Authorization Request**

The third-party application redirects the user's browser to the CAS authorization endpoint:

```
GET {gateway_url}/cas/oidc/authorize
    ?client_id={client_id}
    &redirect_uri={redirect_uri}
    &response_type=code
    &scope=openid+profile+email
    &state={random_state}
```

| Parameter | Required | Description |
|-----------|----------|-------------|
| `client_id` | Yes | Client ID obtained during registration |
| `redirect_uri` | Yes | Must match the `signin_redirect_url` configured during registration |
| `response_type` | Yes | Fixed value: `code` |
| `scope` | Yes | Requested scopes; supports `openid`, `profile`, `email` |
| `state` | Yes | Random string for CSRF protection; returned as-is in the callback |

**PKCE Parameters (Required for Public Client):**

| Parameter | Description |
|-----------|-------------|
| `code_challenge` | S256 method: `BASE64URL(SHA256(code_verifier))` |
| `code_challenge_method` | Fixed value: `S256` |

**Step 2:** CAS displays the login page. The user enters their credentials to complete authentication.

**Step 3:** After successful authentication, CAS redirects the user's browser back to the `redirect_uri`:

```
{redirect_uri}?code={authorization_code}&state={original_state}
```

- `authorization_code`: One-time authorization code, valid for approximately 250 seconds
- `state`: The `state` value passed in the original request, returned as-is

**Step 4: Exchange Authorization Code for Tokens**

```
POST {gateway_url}/cas/oidc/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code={authorization_code}
&client_id={client_id}
&client_secret={client_secret}
&redirect_uri={redirect_uri}
```

**Public Client (no client_secret) must include PKCE parameters:**

```
&code_verifier={original_code_verifier}
```

**Alternatively, use HTTP Basic Auth to pass client credentials:**

```
Authorization: Basic {base64(client_id:client_secret)}
```

Response (HTTP 200):

```json
{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 7200,
  "id_token": "eyJhbGciOiJSUzI1NiIs..."
}
```

### PKCE Support

CAS fully supports PKCE (Proof Key for Code Exchange, RFC 7636) to enhance the security of authorization codes, particularly for public clients that cannot securely store a `client_secret`.

| Client Type | PKCE Required | Description |
|-------------|--------------|-------------|
| Confidential Client (has client_secret) | Optional | Can include PKCE for enhanced security |
| Public Client (no client_secret, auth_method=none) | **Mandatory** | Must use PKCE; otherwise the token request will be rejected |
| Private Key JWT Client | Optional | Can include PKCE for enhanced security |

| Method | Description |
|--------|-------------|
| `S256` | Recommended: `BASE64URL(SHA256(code_verifier))` |
| `plain` | Supported: `code_verifier` as-is; lower security |

> If `code_challenge_method` is not specified, `S256` is used by default.

### Client Credentials Flow

Suitable for direct service-to-service (M2M) calls without user involvement.

```
POST {gateway_url}/cas/oidc/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id={client_id}
&client_secret={client_secret}
```

**Prerequisites:**

- The client's `grant_type` must include `client_credentials`
- A `default_user` (machine user identifier) must be configured; this user will be the identity subject of the token

**Response:**

```json
{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 7200,
  "id_token": "eyJhbGciOiJSUzI1NiIs..."
}
```

### Token Response

**Success Response (HTTP 200):**

| Field | Type | Description |
|-------|------|-------------|
| `access_token` | string | Opaque access token or JWT |
| `token_type` | string | Fixed value: `"Bearer"` |
| `expires_in` | integer | Token validity period (seconds); default 7200 (2 hours), configurable per tenant |
| `id_token` | string | OpenID Connect ID Token (JWT format, signed with RS256) |

**Error Response:**

| Error Code | Description |
|------------|-------------|
| `invalid_grant` | Authorization code is invalid, expired, or PKCE verification failed |
| `invalid_request` | Missing required parameters or incorrect client_id format |
| `invalid_client` | Client authentication failed |
| `server_error` | Internal server error; please retry later |

### Token Claims

**ID Token Claims (JWT signed with RS256):**

| Claim | Type | Description | Example |
|-------|------|-------------|---------|
| `sub` | string | Subject (unique user identifier) | `"2002554412"` (user ID) |
| `aud` | string | Audience | `["{client_id}"]` |
| `exp` | integer | Expiration time | Unix timestamp |
| `name` | string | Full name | `"john.doe"` |
| `nickname` | string | Nickname | `"john.doe"` |
| `preferred_username` | string | Preferred username | `"john.doe"` |
| `email` | string | Email address | `"john.doe@insuremo.com"` |
| `userName` | string | Username (platform extension) | `"john.doe"` |
| `tenant` | string | Tenant code (platform extension) | `"mo-fo"` |

**JWT Header:**

```json
{
  "alg": "RS256",
  "kid": "key-id-from-kms",
  "typ": "JWT"
}
```

> `kid` (Key ID) identifies the signing key and supports key rotation scenarios.

**Access Token Claims (JWT signed with RS256):**

| Claim | Type | Description |
|-------|------|-------------|
| `sub` | string | User ID (machine user ID for client_credentials flow) |
| `exp` | integer | Expiration time (Unix timestamp) |
| `iat` | integer | Issued at time (Unix timestamp) |
| `scope` | string | Authorization scope; fixed value: `"openid email profile"` |

### Token Signing and Verification

| Property | Value |
|----------|-------|
| Algorithm | RS256 (RSA + SHA-256) |
| Key Type | RSA |

The recommended method for token verification is the **Validated Token API**:

```
GET {gateway_url}/cas/validate-token
Authorization: Bearer {access_token}
```

This endpoint performs complete token verification (signature, expiration, etc.) on the CAS server side and returns user information. Third-party applications do not need to obtain public keys or verify JWT signatures themselves.

### UserInfo Endpoint

```
GET {gateway_url}/cas/oidc/userinfo
Authorization: Bearer {access_token}
```

**Response (HTTP 200):**

```json
{
  "sub": "2002554412",
  "name": "john.doe",
  "nickname": "john.doe",
  "preferred_username": "john.doe",
  "email": "john.doe@insuremo.com"
}
```

### Application Integration Guide

**Standard Integration Process:**

1. **Log in to insureMO Portal** with a tenant administrator account, navigate to **SSO Config -> Applications**, and prepare the following:
   - Application name
   - Callback URL (`redirect_uri`)
   - Required grant type (`authorization_code` / `client_credentials`)
   - Client type (Confidential / Public)
   - Tenant code

2. **Obtain client credentials**:
   - `client_id` -- Unique client identifier
   - `client_secret` -- Client secret (not available for Public Client)

3. **Configure your application**:
   - Use the Discovery endpoint to automatically retrieve the CAS OIDC configuration
   - Configure the Token endpoint, Authorization endpoint, etc.
   - Use the Validated Token API for token verification

4. **Implement the OIDC authorization flow**:
   - Confidential Client: Standard Authorization Code Flow
   - Public Client: Authorization Code Flow + PKCE
   - M2M scenario: Client Credentials Flow

**Configuration with Common OIDC Libraries:**

Most standard OIDC libraries support automatic configuration via the Discovery URL. Simply provide the following:

- **Issuer URL**: `https://{gateway_url}/cas`
- **Client ID**: Client ID obtained during registration
- **Client Secret**: Client secret obtained during registration (not needed for Public Client)
- **Redirect URI**: Callback URL configured during registration

The library will automatically retrieve `authorization_endpoint`, `token_endpoint`, and other configurations from the Discovery endpoint.

**Token Verification:**

When verifying tokens issued by CAS, consuming applications can:

1. **Call the Validated Token API**: `GET {gateway_url}/cas/validate-token` with `Authorization: Bearer {access_token}`. CAS performs server-side verification and returns user information.
2. **Call the UserInfo endpoint** (optional): `GET {gateway_url}/cas/oidc/userinfo` with `Authorization: Bearer {access_token}` to retrieve the latest user profile information.

### Known Limitations

| Limitation | Description | Plan |
|-----------|-------------|------|
| JWKS endpoint not yet available | `/cas/oidc/.well-known/jwks.json` is not yet implemented; JWT signature verification cannot be performed via this endpoint | Planned for a future release; use the Validated Token API (`/cas/validate-token`) for now |
| ID Token missing `iss` claim | The `issuer` claim is not explicitly set in the current ID Token | Can be inferred from the `issuer` field in the Discovery response |

## FAQ

### OIDC Integration

**Q1: Does the insureMO OIDC implementation comply with OpenID Connect standards?**

**Yes.** The CAS service implements the standard OIDC Provider role, supporting:
- Standard Discovery endpoint (`/.well-known/oauth-authorization-server`, RFC 8414)
- Standard Authorization Code Flow
- Standard Token endpoint (`/cas/oidc/token`)
- Standard UserInfo endpoint (`/cas/oidc/userinfo`)
- Validated Token API (`/cas/validate-token`)
- PKCE support (RFC 7636)

Third-party applications can use any standard OIDC library for integration.

**Q2: Can applications verify tokens using only platform-provided endpoints and public keys?**

**Not currently supported.** The JWKS endpoint is not yet implemented; it is planned for a future release.

Use the **Validated Token API** (`GET /cas/validate-token`) for token verification. CAS performs server-side verification and returns user information; applications do not need to obtain public keys.

**Q3: How do I register a client application?**

Log in to insureMO Portal with a tenant administrator account, navigate to **SSO Config -> Applications**, and complete the OIDC client registration. Upon completion, you will receive a `client_id` and `client_secret` (not available for Public Client).

**Q4: What is the validity period of an Authorization Code?**

The authorization code is valid for approximately **250 seconds** (about 4 minutes). Call the Token endpoint to exchange the code promptly after obtaining it.

**Q5: What is the validity period of an Access Token?**

The default is **7200 seconds** (2 hours), configurable per tenant. The actual validity period is returned in the `expires_in` field of the Token response.

**Q6: Which Grant Types are supported?**

| Grant Type | Description |
|-----------|-------------|
| `authorization_code` | Authorization Code flow, suitable for Web applications with a backend |
| `client_credentials` | Client Credentials flow, suitable for M2M scenarios |

**Q7: What is the difference between the CAS exchange_code flow and the standard OIDC authorization code?**

These are two completely independent mechanisms:

| | Standard OIDC Authorization Code | CAS Exchange Code |
|--|------------------------------|---------------------|
| Purpose | Third-party application OIDC integration | Internal platform identity propagation |
| Endpoints | `/cas/oidc/authorize` + `/cas/oidc/token` | `/cas/exchange-code/get` + `/cas/exchange-code/consume` |
| Protocol | Standard OIDC | insureMO proprietary protocol |

For third-party application integration, use the standard OIDC Authorization Code flow.

**Q8: What are the requirements for the PKCE code_verifier?**

- Length: 43-128 characters (45+ recommended)
- Character set: `[A-Za-z0-9-._~]`
- Must be stored securely on the client side (e.g., in sessionStorage) and must not be exposed to the server

**Q9: How should I handle Token expiration?**

When an Access Token expires, the application should re-initiate the OIDC authorization flow to obtain a new token. It is recommended to initiate re-authentication before the `expires_in` period elapses, with a buffer for safety.
