mirror of
https://github.com/we-promise/sure.git
synced 2026-04-09 07:14:47 +00:00
Add support for displaying and managing legacy SSO providers (#628)
* feat: add support for displaying and managing legacy SSO providers - Introduced UI section for environment/YAML-configured SSO providers. - Added warnings and guidance on migrating legacy providers to database-backed configuration. - Enhanced localization with new keys for legacy provider management. - Updated form and toggle components for improved usability. * Expand SSO documentation: add SAML 2.0 support, JIT provisioning settings, super-admin setup steps, audit logging, and user administration details. * Update JIT provisioning docs: clarify role mapping behavior and add examples; note new `logout_idp` audit log event. --------- Co-authored-by: Josh Waldrep <joshua.waldrep5+github@gmail.com>
This commit is contained in:
@@ -7,6 +7,12 @@ module Admin
|
||||
def index
|
||||
authorize SsoProvider
|
||||
@sso_providers = policy_scope(SsoProvider).order(:name)
|
||||
|
||||
# Load runtime providers (from YAML/env) that might not be in the database
|
||||
# This helps show users that legacy providers are active but not manageable via UI
|
||||
@runtime_providers = Rails.configuration.x.auth.sso_providers || []
|
||||
db_provider_names = @sso_providers.pluck(:name)
|
||||
@legacy_providers = @runtime_providers.reject { |p| db_provider_names.include?(p[:name].to_s) }
|
||||
end
|
||||
|
||||
def show
|
||||
|
||||
@@ -55,9 +55,13 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= form.check_box :enabled,
|
||||
label: "Enable this provider",
|
||||
checked: sso_provider.enabled? %>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="space-y-1">
|
||||
<p class="text-sm font-medium text-primary"><%= t("admin.sso_providers.form.enabled_label") %></p>
|
||||
<p class="text-xs text-secondary"><%= t("admin.sso_providers.form.enabled_help") %></p>
|
||||
</div>
|
||||
<%= form.toggle :enabled %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-primary pt-4 space-y-4">
|
||||
|
||||
@@ -62,6 +62,44 @@
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if @legacy_providers.any? %>
|
||||
<%= settings_section title: t("admin.sso_providers.index.legacy_providers_title"), collapsible: true, open: true do %>
|
||||
<div class="bg-amber-50 border border-amber-200 rounded-lg p-3 mb-4">
|
||||
<div class="flex gap-2">
|
||||
<%= icon "alert-triangle", class: "w-5 h-5 text-amber-600 shrink-0" %>
|
||||
<p class="text-sm text-amber-800">
|
||||
<%= t("admin.sso_providers.index.legacy_providers_notice") %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="divide-y divide-primary">
|
||||
<% @legacy_providers.each do |provider| %>
|
||||
<div class="flex items-center justify-between py-3 first:pt-0 last:pb-0">
|
||||
<div class="flex items-center gap-3">
|
||||
<% provider_icon = provider[:icon].presence || "key" %>
|
||||
<%= icon provider_icon, class: "w-5 h-5 text-secondary" %>
|
||||
<div>
|
||||
<p class="font-medium text-primary"><%= provider[:label].presence || provider[:name] %></p>
|
||||
<p class="text-sm text-secondary">
|
||||
<%= provider[:strategy].to_s.titleize %> · <%= provider[:name] %>
|
||||
<% if provider[:issuer].present? %>
|
||||
· <span class="text-xs"><%= provider[:issuer] %></span>
|
||||
<% end %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-amber-100 text-amber-800">
|
||||
<%= t("admin.sso_providers.index.env_configured") %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<%= settings_section title: "Configuration Mode", collapsible: true, open: false do %>
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-center justify-between">
|
||||
|
||||
@@ -18,6 +18,9 @@ en:
|
||||
actions: "Actions"
|
||||
enabled: "Enabled"
|
||||
disabled: "Disabled"
|
||||
legacy_providers_title: "Environment-Configured Providers"
|
||||
legacy_providers_notice: "These providers are configured via environment variables or YAML and cannot be managed through this interface. To manage them here, migrate them to database-backed providers by enabling AUTH_PROVIDERS_SOURCE=db and recreating them in the UI."
|
||||
env_configured: "Env/YAML"
|
||||
new:
|
||||
title: "Add SSO Provider"
|
||||
description: "Configure a new single sign-on authentication provider"
|
||||
@@ -51,6 +54,7 @@ en:
|
||||
icon_placeholder: "e.g., key, google, github"
|
||||
icon_help: "Lucide icon name (optional)"
|
||||
enabled_label: "Enable this provider"
|
||||
enabled_help: "Users can sign in with this provider when enabled"
|
||||
issuer_label: "Issuer"
|
||||
issuer_placeholder: "https://accounts.google.com"
|
||||
issuer_help: "OIDC issuer URL (will validate .well-known/openid-configuration endpoint)"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Configuring OpenID Connect and SSO providers
|
||||
# Configuring OpenID Connect, SAML, and SSO Providers
|
||||
|
||||
This guide shows how to enable OpenID Connect (OIDC) and other single sign-on (SSO) providers for Sure using Google, GitHub, or another OIDC‑compatible identity provider (e.g. Keycloak, Authentik).
|
||||
This guide shows how to enable OpenID Connect (OIDC), SAML 2.0, and other single sign-on (SSO) providers for Sure using Google, GitHub, or another identity provider (e.g. Keycloak, Authentik, Okta, Azure AD).
|
||||
|
||||
It also documents the new `config/auth.yml` and environment variables that control:
|
||||
|
||||
@@ -174,6 +174,26 @@ To enable Google:
|
||||
|
||||
- `http://localhost:3000/auth/<provider_name>/callback`
|
||||
|
||||
### 3.5 Bootstrapping the first super‑admin
|
||||
|
||||
The first `super_admin` must be set via Rails console. Access the console in your container/pod or directly on the server:
|
||||
|
||||
```bash
|
||||
bin/rails console
|
||||
```
|
||||
|
||||
Then promote a user:
|
||||
|
||||
```ruby
|
||||
# Set super_admin role
|
||||
User.find_by(email: "admin@example.com").update!(role: :super_admin)
|
||||
|
||||
# Verify
|
||||
User.find_by(email: "admin@example.com").role # => "super_admin"
|
||||
```
|
||||
|
||||
Once set, super‑admins can promote other users via the web UI at `/admin/users`.
|
||||
|
||||
---
|
||||
|
||||
## 4. Example configurations
|
||||
@@ -419,6 +439,20 @@ To switch back to YAML-based configuration:
|
||||
2. Restart the application
|
||||
3. Providers will be loaded from `config/auth.yml`
|
||||
|
||||
### 6.6 JIT provisioning settings
|
||||
|
||||
Each provider has a **Default Role** field (defaults to `member`) that sets the role for JIT-created users.
|
||||
|
||||
**Role mapping from IdP groups:**
|
||||
|
||||
Expand **"Role Mapping"** in the admin UI to map IdP group names to Sure roles. Enter comma-separated group names for each role:
|
||||
|
||||
- **Super Admin Groups**: `Platform-Admins, IdP-Superusers`
|
||||
- **Admin Groups**: `Team-Leads, Managers`
|
||||
- **Member Groups**: `Everyone` or leave blank
|
||||
|
||||
Mapping is case-sensitive and matches exact group claim values from the IdP. When a user belongs to multiple mapped groups, the highest role wins (`super_admin` > `admin` > `member`). If no groups match, the Default Role is used.
|
||||
|
||||
---
|
||||
|
||||
## 7. Troubleshooting
|
||||
@@ -484,4 +518,50 @@ Each provider requires a callback URL configured in your identity provider:
|
||||
|
||||
---
|
||||
|
||||
## 9. SAML 2.0 Support
|
||||
|
||||
Sure supports SAML 2.0 via database-backed providers. Select **"SAML 2.0"** as the strategy when adding a provider at `/admin/sso_providers`.
|
||||
|
||||
Configure with either:
|
||||
- **IdP Metadata URL** (recommended) - auto-fetches configuration
|
||||
- **Manual config** - IdP SSO URL + certificate
|
||||
|
||||
In your IdP, set:
|
||||
- **ACS URL**: `https://yourdomain.com/auth/<provider_name>/callback`
|
||||
- **Entity ID**: `https://yourdomain.com` (your `APP_URL`)
|
||||
- **Name ID**: Email Address
|
||||
|
||||
---
|
||||
|
||||
## 10. User Administration
|
||||
|
||||
Super‑admins can manage user roles at `/admin/users`.
|
||||
|
||||
Roles: `member` (standard), `admin` (family admin), `super_admin` (platform admin).
|
||||
|
||||
Note: Super‑admins cannot change their own role.
|
||||
|
||||
---
|
||||
|
||||
## 11. Audit Logging
|
||||
|
||||
SSO events are logged to `sso_audit_logs`: `login`, `login_failed`, `logout`, `logout_idp` (federated logout), `link`, `unlink`, `jit_account_created`.
|
||||
|
||||
Query via console:
|
||||
|
||||
```ruby
|
||||
SsoAuditLog.by_event("login").recent.limit(50)
|
||||
SsoAuditLog.by_event("login_failed").where("created_at > ?", 24.hours.ago)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 12. User SSO Identity Management
|
||||
|
||||
Users manage linked SSO identities at **Settings > Security**.
|
||||
|
||||
SSO-only users (no password) cannot unlink their last identity.
|
||||
|
||||
---
|
||||
|
||||
For additional help, see the main [hosting documentation](../README.md) or open an issue on GitHub.
|
||||
|
||||
Reference in New Issue
Block a user