OpenID Connect (OIDC) is an identity layer on top of OAuth 2.0. It lets clients verify user identity based on authentication performed by an authorization server and obtain basic profile information. Adding OIDC enables SSO with providers like Authentik, Authelia, and KeyCloak.
What it gives us:
1. Users authenticate with their existing IdP credentials
2. No need for separate username/password management
3. Modern auth best practices baked in
4. Seamless experience for users already on SSO
## OIDC Configuration
OIDC is configured separately from **AuthConfig** via **OidcConfig** in `src/common/config.rs`. This is a single-provider model -- one OIDC provider per instance:
```rust
/// OpenID Connect (OIDC) configuration
pubstructOidcConfig{
pubenabled: bool,// Whether OIDC is enabled
pubissuer_url: String,// OIDC Issuer URL
pubclient_id: String,// OIDC Client ID
pubclient_secret: String,// OIDC Client Secret
pubredirect_uri: String,// Redirect URI (default: http://localhost:8086/api/auth/oidc/callback)
pubscopes: String,// Scopes to request (default: "openid profile email")
pubfrontend_url: String,// Frontend URL for post-login redirect
pubauto_provision: bool,// Auto-create users on first login (JIT provisioning)
pubadmin_groups: String,// Comma-separated OIDC groups that map to admin role
The OIDC service lives in the infrastructure layer at `src/infrastructure/services/oidc_service.rs` and implements the **OidcServicePort** trait defined in `src/application/ports/auth_ports.rs`:
```rust
// src/application/ports/auth_ports.rs — Port trait
Follows hexagonal architecture: the port (**OidcServicePort**) is in the application layer, and the implementation (**OidcService**) is in the infrastructure layer.
## User Entity OIDC Support
The **User** entity in `src/domain/entities/user.rs` supports OIDC users via two fields:
```rust
#[derive(Debug, Clone)]
pubstructUser{
// ... standard fields ...
oidc_provider: Option<String>,// OIDC provider name (e.g., "authentik")
oidc_subject: Option<String>,// OIDC subject identifier (unique ID from provider)
OIDC endpoints in `src/interfaces/api/handlers/auth_handler.rs`:
```rust
// Public OIDC routes (no auth required) — nested under /api/auth/
.route("/status",get(get_system_status))
.route("/oidc/providers",get(oidc_providers))
.route("/oidc/authorize",get(oidc_authorize))
.route("/oidc/callback",get(oidc_callback))
.route("/oidc/exchange",post(oidc_exchange))
```
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/auth/oidc/providers` | Returns OIDC provider info (name, enabled state) |
| GET | `/api/auth/oidc/authorize` | Returns authorization URL for redirect to IdP |
| GET | `/api/auth/oidc/callback` | Receives callback redirect from IdP with auth code |
| POST | `/api/auth/oidc/exchange` | Exchanges auth code for JWT tokens |
## DTOs
DTOs in `src/application/dtos/user_dto.rs`:
```rust
// Response with authorization URL
#[derive(Debug, Clone, Serialize)]
pubstructOidcAuthorizeResponseDto{
pubauthorize_url: String,
pubstate: String,
}
// Query params received from IdP callback
#[derive(Debug, Clone, Deserialize)]
pubstructOidcCallbackQueryDto{
pubcode: String,
pubstate: String,
}
// Request to exchange code for tokens
#[derive(Debug, Clone, Deserialize)]
pubstructOidcExchangeDto{
pubcode: String,
pubstate: String,
}
// Provider info response
#[derive(Debug, Clone, Serialize)]
pubstructOidcProviderInfoDto{
pubenabled: bool,
pubprovider_name: String,
pubdisable_password_login: bool,
}
// User info from OIDC claims
#[derive(Debug, Clone, Serialize)]
pubstructOidcUserInfoDto{
pubsubject: String,
pubemail: Option<String>,
pubname: Option<String>,
pubpreferred_username: Option<String>,
pubgroups: Vec<String>,
}
```
## Frontend Integration
OIDC login is built directly into `static/login.html` and handled by `static/js/auth.js`. There is no separate `oidcAuth.js` file. The login page checks the system status endpoint to see if OIDC is enabled, then shows an SSO button accordingly.
```html
<!-- In login.html - SSO login button shown when OIDC is enabled -->
See `oidc-config-examples.md` for more provider-specific configurations.
## Additional Notes
1.**Security** -- always use HTTPS for OIDC connections. Ensure proper TLS configuration.
2.**User mapping** -- OIDC users are identified by **oidc_provider** + **oidc_subject** in the **auth.users** table. Groups from OIDC can map to admin role via **OXICLOUD_OIDC_ADMIN_GROUPS**.
3.**Single provider** -- one OIDC provider per instance. Managed via admin settings UI or environment variables.
4.**Session management** -- after OIDC authentication, the backend generates its own JWT access/refresh tokens. Sessions work identically to password-based login from that point.
5.**Access control** -- OIDC users share the same permissions model as local users. Admin role can be auto-assigned based on OIDC group membership.
6.**Testing** -- use the admin settings UI (`/admin.html`) to configure and test OIDC connections.