mirror of
https://github.com/we-promise/sure.git
synced 2026-07-28 04:32:12 +00:00
700ad34eb10c8abbdcd2782bd6419b577814aca5
13 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
700ad34eb1 |
feat: Introduce macOS app v0.1.0 (#2762)
* feat(desktop): scaffold Tauri 2 macOS shell with empty window * feat(desktop): server store, URL normalization, and health-check helpers * feat(desktop): IPC commands for server list/add/remove/health + active-server state Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nno38ujctqiqSoY8eFRhaf * feat(desktop): native onboarding server picker with health check and remembered servers * feat(desktop): vibrancy background, overlay titlebar, and inset traffic lights * feat(desktop): native menu bar with standard shortcuts and menu events * feat(desktop): webview→Rust bridge with native notifications * fix(desktop): gate bridge injection on PageLoadEvent::Finished Prevents double-injecting the bridge IIFE (once on Started, once on Finished), which was duplicating every native notification. * feat(desktop): Dock badge driven by webview attention count * feat(desktop): launch-at-login autostart commands * feat(desktop): sure:// deep link scheme with parse tests and navigation * feat(desktop): preferences window with server switcher and launch-at-login * docs(desktop): README for dev, release, signing/notarization, and deferred widget * fix(desktop): remove dead New Window menu item * fix(desktop): correct login route to /sessions/new Rails uses `resources :sessions` (plural), so the login page is /sessions/new, not the /session/new the plan assumed. Fixes an immediate 404 when connecting to a server. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nno38ujctqiqSoY8eFRhaf * feat(desktop): Sure-styled onboarding, draggable titlebar, and app content offset - Restyle onboarding + prefs to match Sure's auth page: solid surface background, centered logomark, .form-field-style inputs, inverse primary button; theme-aware via prefers-color-scheme (design-system tokens). - Add a draggable titlebar strip on bundled pages and inject one into the remote page so the window drags from the top everywhere. - Inject a top offset on the logged-in app-layout root so the sidebar logo clears the macOS traffic lights. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nno38ujctqiqSoY8eFRhaf * fix(desktop): de-dupe login navigation to prevent CSRF token/session race connect() navigated to /sessions/new directly AND via the active-server-changed event, which is also handled by a second listener injected into the page by bridge.js. One connect fired multiple concurrent GET /sessions/new requests, each minting a fresh session + CSRF token; the form shown and the _sure_session finally stored could come from different GETs, so the login POST failed 'Can't verify CSRF token authenticity' intermittently. Route all navigation through a single window-level guard so only the first request per server wins. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nno38ujctqiqSoY8eFRhaf * fix(desktop): enable window drag permission; offset only the icon rail - Add core:window:allow-start-dragging (+ show/set-focus, event emit/listen) to capabilities so data-tauri-drag-region actually drags the window on macOS. - Offset only the 84px left icon rail (logomark) to clear the traffic lights instead of pushing the entire app-layout down; keep main content full-height. - Drag strip z-index lowered below Sure's sticky headers so its controls stay clickable. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nno38ujctqiqSoY8eFRhaf * feat(desktop): persist active server and resume session on launch - Persist the active server to the Keychain in set_active_server; active_server falls back to it so a relaunch knows where to go. - On launch, auto-resume straight to the last server instead of showing the picker every time. - Navigate to the server root (not /sessions/new): Rails serves the dashboard when the session cookie is still valid, or redirects to login when not — so a persisted session no longer forces a re-login. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nno38ujctqiqSoY8eFRhaf * feat: desktop SSO via system browser with PKCE code exchange Passkeys/WebAuthn don't work in an embedded WKWebView, so SSO now runs in the system browser and hands a session back to the app securely. Server (Rails): - GET /auth/desktop/:provider — stashes a PKCE S256 challenge, hands off to OmniAuth (reusing the mobile auto-submit form). Passkeys work (real browser). - openid_connect — for a linked identity in a desktop flow, mints a single-use, 2-min, PKCE-bound one-time code and redirects to sure://sso/callback?code=... (unlinked identities are sent back with an error). - GET /sessions/desktop_exchange — verifies the code + PKCE verifier (secure_compare), single-use (cache delete), then create_session_for; MFA is enforced at exchange time. Sets the normal web session cookie in the webview. - Tests: happy path + single-use, wrong-verifier rejection, missing challenge. Desktop (Tauri): - start_sso command: generates PKCE, opens the browser, stores the verifier. - sure://sso/callback deep link -> webview navigates to desktop_exchange with the verifier (never sent through the deep link, so an intercepted code is useless). - bridge.ts intercepts SSO provider form submits and routes them to start_sso; password login stays in the webview. - remote.json capability: minimal IPC (drag, event bridge, prefs window, start_sso) for the remote Sure origin — no fs/shell/http. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nno38ujctqiqSoY8eFRhaf * fix(desktop): correct remote IPC capability + handle menu in Rust + drag fallback Root cause of prefs/switch-server/SSO/drag doing nothing on the logged-in page: the remote-bridge capability's remote.urls ('https://*') did not match the server origin, so all IPC (event listen, invoke, drag command) was denied. Per Tauri v2, window.__TAURI__ is injected on remote pages only with withGlobalTauri (set) AND a matching remote.urls; patterns need a path wildcard. - remote.json: urls -> https://*/**, http://*/** (+ bare host) so any server origin matches. - menu.rs: Preferences and Switch Server now show the prefs window directly in Rust (no dependency on remote-page IPC); Switch Server moved from Window to the App menu. - bridge.ts: drops the menu-event listeners (Rust owns them), adds a startDragging mousedown fallback for the drag strip, logs diagnostics, and reports start_sso success/failure to the console. - main.ts: drops the now-unused menu listeners. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nno38ujctqiqSoY8eFRhaf * fix(desktop): SSO via event (remote can't invoke commands), disk-backed server store Diagnostics confirmed window.__TAURI__ + IPC work on the remote page, but a remote origin cannot invoke custom commands ('start_sso not allowed. Plugin not found'). Events are permitted, so SSO now goes through an event. - SSO: bridge emits 'sure://start-sso'; Rust listens and runs begin_sso (opens the system browser). start_sso command kept for local use. - servers: mirror the server list + active server to a JSON file in Application Support as a fallback — Keychain items don't persist for unsigned builds, which was wiping the saved server on relaunch. - remote.json: add notification:default (Sure's PWA was requesting it and erroring). - menu: log whether the prefs window is present when Preferences/Switch Server fire, to diagnose the no-op. - main: log the persisted active server on boot. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nno38ujctqiqSoY8eFRhaf * fix(desktop): drag the top band on every page via mousedown, not a z-indexed strip The fixed drag strip sat below Sure's sticky headers (z-10) so it worked only on pages without a top header. Replace it with a document-level mousedown in the top ~34px that starts a window drag unless the target is an interactive element — so dragging works on all pages, Sure's titlebar controls stay clickable, and main content isn't pushed down. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nno38ujctqiqSoY8eFRhaf * ci(desktop): tag-triggered GitHub Actions release for universal unsigned .dmg - .github/workflows/desktop-release.yml: on a 'desktop-v*' tag, build the universal (Apple Silicon + Intel) .dmg on a macOS runner via tauri-action and publish it to a GitHub Release with unsigned-install instructions. - README: universal build command, the tag-based release process, and the Gatekeeper 'Open Anyway' / xattr steps for end users. - Drop the unused iOS/Android icon sets (macOS build only needs icon.icns). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nno38ujctqiqSoY8eFRhaf * ci(desktop): rolling desktop-latest build on desktop/ changes, not manual tags Replaces the manual desktop-v* tag release with a path-filtered workflow that builds only when desktop/ changes on main and publishes to a single rolling 'desktop-latest' prerelease with a stable Sure.dmg filename — one permanent download URL, and the file changes only when the desktop code does. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nno38ujctqiqSoY8eFRhaf * ci(desktop): tag-driven versioned releases; tag is the single source of version Revert to manual version tags (desktop-v*) for explicit version control, but derive the app/.dmg version from the tag so package.json + tauri.conf.json are synced automatically in CI — no manual version-file edits. Each tag produces its own versioned GitHub Release with the universal unsigned .dmg. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nno38ujctqiqSoY8eFRhaf * ci(desktop): release entirely from GitHub via workflow_dispatch version input Make the GitHub Action the single tool to version + deploy the desktop app: Run workflow -> enter a version -> it syncs the version, builds the universal unsigned .dmg, and creates the desktop-v<version> tag + Release. Refuses to re-release an existing version; marks pre-release versions accordingly. Tag push (desktop-v*) still works as a secondary trigger. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nno38ujctqiqSoY8eFRhaf * ci(desktop): publish releases with make_latest:false so they don't hijack the repo's Latest badge Desktop is a secondary artifact, not the main product. Build with tauri-action, then publish via action-gh-release with make_latest:false so the repo's 'Latest release' badge stays on the main app's v* release. Separate desktop-v* tag namespace already keeps it out of the v* publish workflow. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nno38ujctqiqSoY8eFRhaf * fix(desktop): address PR review feedback (security + correctness) Security: - workflow: pass workflow_dispatch version via env (no shell injection); pin all third-party actions to commit SHAs. - SSO: gate deep-link navigation and begin_sso to servers the user has saved (is_known_server), so a rogue page/deep link can't drive them. - desktop_exchange is now POST (verifier in body, not URL/logs); CSRF skipped since the single-use PKCE code is the protection. - desktop_sso_start validates the code_challenge is a 43-char base64url digest. - desktop_exchange claims the one-time code atomically (delete-and-check) to close the read/delete TOCTOU. - failure: return desktop SSO errors to the app via sure://sso/callback?error. Correctness / stability: - prefs window hides on close instead of being destroyed, so the menu can reopen it. - servers.rs: on-disk store is authoritative (file-first read), atomic writes (temp + rename). - main.ts/prefs.ts: try/catch around add/set/remove/active_server and boot; add a shared serverErrorMessage helper (no duplicated substring checks). - vite.config.ts: derive dir from import.meta.url (ESM has no __dirname). - bridge.ts: coalesce MutationObserver scans to one per frame. - README: notarization example uses the universal .dmg name. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nno38ujctqiqSoY8eFRhaf * fix(desktop): scope remote IPC to server origins at runtime, drop wildcard capability Resolves the remaining security finding: the static remote.json granted Tauri IPC to any http(s) origin (https://*). Remove it and instead add a capability scoped to each server's exact origin at runtime (CapabilityBuilder + add_capability), granting only the minimal permissions the bridge needs, for saved/active servers on startup and for the target in set_active_server. No origin outside the user's configured servers can access IPC. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nno38ujctqiqSoY8eFRhaf * fix(desktop): add runtime per-origin IPC capability (grant_server_capability) Implements the runtime-scoped capability that replaces the removed wildcard remote.json: CapabilityBuilder scoped to each server's exact origin, added via add_capability for saved/active servers at startup and in set_active_server. (Split from the previous commit, which only recorded the remote.json removal.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nno38ujctqiqSoY8eFRhaf * ci(desktop): harden release workflow (no shared caches, environment gate) Address two release-workflow security findings: - Remove cache: npm and the swatinem/rust-cache step so a poisoned Actions cache written by another workflow can't flow into a published .dmg (P0). - Add 'environment: release' to the build job so publishing can require manual approval and scope secrets to release runs (P1). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nno38ujctqiqSoY8eFRhaf * fix(desktop): remove transparency code and fix relaunch behavior * fix(desktop): fix PR review findings; adjust app notarization path, use Sure theme tokens instead of hardcoding values * ci(desktop): switch release from independant versioning to using Sure's publishing workflow, releasing and versioning with every main app release * fix(desktop): restrict CSP as much as possible while maintaining functionality; allow bundled scripts, Tauri IPC, inline styles; deny wildcards --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
2051c74559 |
fix(ds): unify SSO sign-in buttons on DS::Button; drop bespoke Google CSS (#2152)
The Google button used Google's prebuilt `gsi-material-button` (its own CSS file + hardcoded hex colors), leaving it the odd one out: capped at 400px (its `max-width` overrode `w-full`) so it sat narrower than the OpenID/GitHub buttons, and rendered as a glaring white block in dark mode with no theming. Render every SSO provider through one `DS::Button(variant: :outline, full_width: true)` so the stack is consistent and reads as secondary to the primary email "Log in" CTA. Google keeps its official multi-color "G" mark and "Sign in with Google" wording (brand-compliant) via a new `google-icon.svg` asset and an additive `icon_custom:` flag on the button (defaults false — no change to any existing button). Delete `google-sign-in.css` and its import. |
||
|
|
f6e7234ead |
Enable Google SSO account creation in Flutter app (#1164)
* Add Google SSO onboarding flow for Flutter mobile app Previously, mobile users attempting Google SSO without a linked OIDC identity received an error telling them to link from the web app first. This adds the same account linking/creation flow that exists on the PWA. Backend changes: - sessions_controller: Cache pending OIDC auth with a linking code and redirect back to the app instead of returning an error - api/v1/auth_controller: Add sso_link endpoint to link Google identity to an existing account via email/password, and sso_create_account endpoint to create a new SSO-only account (respects JIT config) - routes: Add POST auth/sso_link and auth/sso_create_account Flutter changes: - auth_service: Detect account_not_linked callback status, add ssoLink and ssoCreateAccount API methods - auth_provider: Track SSO onboarding state, expose linking/creation methods and cancelSsoOnboarding - sso_onboarding_screen: New screen with tabs to link existing account or create new account, pre-filled with Google profile data - main.dart: Show SsoOnboardingScreen when ssoOnboardingPending is true https://claude.ai/code/session_011ag1qSfriUg6j7TqFgbS5c * Fix broken SSO tests: use MemoryStore cache and correct redirect param - Sessions test: check `status` param instead of `error` since handle_mobile_sso_onboarding sends linking info with status key - API auth tests: swap null_store for MemoryStore so cache-based linking code validation works in test environment https://claude.ai/code/session_011ag1qSfriUg6j7TqFgbS5c * Delay linking-code consumption until SSO link/create succeeds Split validate_and_consume_linking_code into validate_linking_code (read-only) and consume_linking_code! (delete). The code is now only consumed after password verification (sso_link) or successful user save (sso_create_account), so recoverable errors no longer burn the one-time code and force a full Google SSO roundtrip. https://claude.ai/code/session_011ag1qSfriUg6j7TqFgbS5c * Make linking-code consumption atomic to prevent race conditions Move consume_linking_code! (backed by Rails.cache.delete) to after recoverable checks (bad password, policy rejection) but before side-effecting operations (identity/user creation). Only the first caller to delete the cache key gets true, so concurrent requests with the same code cannot both succeed. - sso_link: consume after password auth, before OidcIdentity creation - sso_create_account: consume after allow_account_creation check, before User creation - Bad password still preserves the code for retry - Add single-use regression tests for both endpoints https://claude.ai/code/session_011ag1qSfriUg6j7TqFgbS5c * Add missing sso_create_account test coverage for blank code and validation failure - Test blank linking_code returns 400 (bad_request) with proper error - Test duplicate email triggers user.save failure → 422 with validation errors https://claude.ai/code/session_011ag1qSfriUg6j7TqFgbS5c * Verify cache payload in mobile SSO onboarding test with MemoryStore The test environment uses :null_store which silently discards cache writes, so handle_mobile_sso_onboarding's Rails.cache.write was never verified. Swap in a MemoryStore for this test and assert the full cached payload (provider, uid, email, name, device_info, allow_account_creation) at the linking_code key from the redirect URL. https://claude.ai/code/session_011ag1qSfriUg6j7TqFgbS5c * Add rswag/OpenAPI specs for sso_link and sso_create_account endpoints POST /api/v1/auth/sso_link: documents linking_code + email/password params, 200 (tokens), 400 (missing code), 401 (invalid creds/expired). POST /api/v1/auth/sso_create_account: documents linking_code + optional first_name/last_name params, 200 (tokens), 400 (missing code), 401 (expired code), 403 (creation disabled), 422 (validation errors). Note: RAILS_ENV=test bundle exec rake rswag:specs:swaggerize should be run to regenerate docs/api/openapi.yaml once the runtime environment matches the Gemfile Ruby version. https://claude.ai/code/session_011ag1qSfriUg6j7TqFgbS5c * Preserve OIDC issuer through mobile SSO onboarding flow handle_mobile_sso_onboarding now caches the issuer from auth.extra.raw_info.iss so it survives the linking-code round trip. build_omniauth_hash populates extra.raw_info.iss from the cached issuer so OidcIdentity.create_from_omniauth stores it correctly. Previously the issuer was always nil for mobile SSO-created identities because build_omniauth_hash passed an empty raw_info OpenStruct. https://claude.ai/code/session_011ag1qSfriUg6j7TqFgbS5c * Block MFA users from bypassing second factor via sso_link sso_link authenticated with email/password but never checked user.otp_required?, allowing MFA users to obtain tokens without a second factor. The mobile SSO callback already rejects MFA users with "mfa_not_supported"; apply the same guard in sso_link before consuming the linking code or creating an identity. Returns 401 with mfa_required: true, consistent with the login action's MFA response shape. https://claude.ai/code/session_011ag1qSfriUg6j7TqFgbS5c * Fix NoMethodError in SSO link MFA test Replace non-existent User.generate_otp_secret class method with ROTP::Base32.random(32), matching the pattern used in User#setup_mfa!. https://claude.ai/code/session_011ag1qSfriUg6j7TqFgbS5c * Assert linking code survives rejected SSO create account Add cache persistence assertion to "should reject SSO create account when not allowed" test, verifying the linking code is not consumed on the 403 path. This mirrors the pattern used in the invalid-password sso_link test. The other rejection tests (expired/missing linking code) don't have a valid cached code to check, so no assertion is needed there. https://claude.ai/code/session_011ag1qSfriUg6j7TqFgbS5c --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
ca3abd5d8b |
Add Google Sign-In (SSO) support to Flutter mobile app (#860)
* Add mobile SSO support to sessions controller
Add /auth/mobile/:provider route and mobile_sso_start action that
captures device params in session and renders an auto-submitting POST
form to OmniAuth (required by omniauth-rails_csrf_protection).
Modify openid_connect callback to detect mobile_sso session, issue
Doorkeeper tokens via MobileDevice, and redirect to sureapp://oauth/callback
with tokens. Handles MFA users and unlinked accounts with error redirects.
Validates provider name against configured SSO providers and device info
before proceeding.
* Add SSO auth flow to Flutter service and provider
Add buildSsoUrl() and handleSsoCallback() to AuthService for
constructing the mobile SSO URL and parsing tokens from the deep
link callback.
Add startSsoLogin() and handleSsoCallback() to AuthProvider for
launching browser-based SSO and processing the redirect.
* Register deep link listener for SSO callback
Listen for sureapp://oauth/* deep links via app_links package,
handling both cold start (getInitialLink) and warm (uriLinkStream)
scenarios. Routes callbacks to AuthProvider.handleSsoCallback().
* Add Google Sign-In button to Flutter login screen
Add "or" divider and outlined Google Sign-In button that triggers
browser-based SSO via startSsoLogin('google_oauth2').
Add app_links and url_launcher dependencies to pubspec.yaml.
* Fix mobile SSO failure handling to redirect back to app
When OmniAuth fails during mobile SSO flow, redirect to
sureapp://oauth/callback with the error instead of the web login page.
Cleans up mobile_sso session data on failure.
* Address PR review feedback for mobile SSO flow
- Use strong params for device info in mobile_sso_start
- Guard against nil session data in handle_mobile_sso_callback
- Add error handling for AppLinks initialization and stream
- Handle launchUrl false return value in SSO login
- Use user-friendly error messages instead of exposing exceptions
- Reject empty token strings in SSO callback validation
* Consolidate mobile device token logic into MobileDevice model
Extract duplicated device upsert and token issuance code from
AuthController and SessionsController into MobileDevice. Add
CALLBACK_URL constant and URL builder helpers to eliminate repeated
deep-link strings. Add mobile SSO integration tests covering the
full flow, MFA rejection, unlinked accounts, and failure handling.
* Fix CI: resolve Brakeman redirect warnings and rubocop empty line
Move mobile SSO redirect into a private controller method with an
inline string literal so Brakeman can statically verify the target.
Remove unused URL builder helpers from MobileDevice. Fix extra empty
line at end of AuthController class body.
* Use authorization code exchange for mobile SSO and add signup error handling
Replace passing plaintext tokens in mobile SSO redirect URLs with a
one-time authorization code pattern. Tokens are now stored server-side
in Rails.cache (5min TTL) and exchanged via a secure POST to
/api/v1/auth/sso_exchange. Also wraps device/token creation in the
signup action with error handling and sanitizes device error messages.
* Add error handling for login device registration and blank SSO code guard
* Address PR #860 review: fix SSO race condition, add OpenAPI spec, and cleanup
- Fix race condition in sso_exchange by checking Rails.cache.delete return
value to ensure only one request can consume an authorization code
- Use strong parameters (params.require) for sso_exchange code param
- Move inline HTML from mobile_sso_start to a proper view template
- Clear stale session[:mobile_sso] flag on web login paths to prevent
abandoned mobile flows from hijacking subsequent web SSO logins
- Add OpenAPI/rswag spec for all auth API endpoints
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix mobile SSO test to match authorization code exchange pattern
The test was asserting tokens directly in the callback URL, but the code
uses an authorization code exchange pattern. Updated to exchange the code
via the sso_exchange API endpoint. Also swaps in a MemoryStore for this
test since the test environment uses null_store which discards writes.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Refactor mobile OAuth to use single shared application
Replace per-device Doorkeeper::Application creation with a shared
"Sure Mobile" OAuth app. Device tracking uses mobile_device_id on
access tokens instead of oauth_application_id on mobile_devices.
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
|
||
|
|
b23711ae0d |
Add configurable multi-provider SSO, SSO-only mode, and JIT controls via auth.yml (#441)
* Add configuration and logic for dynamic SSO provider support and stricter JIT account creation - Introduced `config/auth.yml` for centralized auth configuration and documentation. - Added support for multiple SSO providers, including Google, GitHub, and OpenID Connect. - Implemented stricter JIT SSO account creation modes (`create_and_link` vs `link_only`). - Enabled optional restriction of JIT creation by allowed email domains. - Enhanced OmniAuth initializer for dynamic provider setup and better configurability. - Refined login UI to handle local login disabling and emergency super-admin override. - Updated account creation flow to respect JIT mode and domain checks. - Added tests for SSO account creation, login form visibility, and emergency overrides. # Conflicts: # app/controllers/sessions_controller.rb * remove non-translation * Refactor authentication views to use translation keys and update locale files - Extracted hardcoded strings in `oidc_accounts/link.html.erb` and `sessions/new.html.erb` into translation keys for better localization support. - Added missing translations for English and Spanish in `sessions` and `oidc_accounts` locale files. * Enhance OmniAuth provider configuration and refine local login override logic - Updated OmniAuth initializer to support dynamic provider configuration with `name` and scoped parameters for Google and GitHub. - Improved local login logic to enforce stricter handling of super-admin override when local login is disabled. - Added test for invalid super-admin override credentials. * Document Google sign-in configuration for local development and self-hosted environments --------- Co-authored-by: Josh Waldrep <joshua.waldrep5+github@gmail.com> |
||
|
|
768e85ce08 |
Add OpenID Connect login support (#77)
* Add OpenID Connect login support * Add docs for OIDC config with Google Auth * Use Google styles for log in - Add support for linking existing account - Force users to sign-in with passoword first, when linking existing accounts - Add support to create new user when using OIDC - Add identities to user to prevent account take-ver - Make tests mocking instead of being integration tests - Manage session handling correctly - use OmniAuth.config.mock_auth instead of passing auth data via request env * Conditionally render Oauth button - Set a config item `configuration.x.auth.oidc_enabled` - Hide button if disabled --------- Signed-off-by: Juan José Mata <juanjo.mata@gmail.com> Signed-off-by: soky srm <sokysrm@gmail.com> Co-authored-by: sokie <sokysrm@gmail.com> |
||
|
|
1e01840fee |
Chromium E2E test fixes (#2108)
* Change test password to avoid chromium conflicts * Update integration tests * Centralize all test password references * Remove unrelated schema changes |
||
|
|
19cc63c8f4 |
Use Redis for ActiveJob and ActionCable (#2004)
* Use Redis for ActiveJob and ActionCable * Fix alwaysApply setting * Update queue names and weights * Tweak weights * Update job queues * Update docker setup guide * Remove deprecated upgrade columns from users table * Refactor Redis configuration for Sidekiq and caching in production environment * Add Sidekiq Sentry monitoring * queue naming fix * Clean up schema |
||
|
|
842e37658c |
Multi-factor authentication (#1817)
* Initial pass * Tests for MFA and locale cleanup * Brakeman * Update two-factor authentication status styling * Update app/models/user.rb Co-authored-by: Zach Gollwitzer <zach@maybe.co> Signed-off-by: Josh Pigford <josh@joshpigford.com> * Refactor MFA verification and session handling in tests --------- Signed-off-by: Josh Pigford <josh@joshpigford.com> Co-authored-by: Zach Gollwitzer <zach@maybe.co> |
||
|
|
b611dfdf37 | Add back good job dashboard with auth (#1364) | ||
|
|
1d20de770f |
User Onboarding + Bug Fixes (#1352)
* Bump min supported date to 20 years * Add basic onboarding * User onboarding * Complete onboarding flow * Cleanup, add user profile update test |
||
|
|
1ffa13f3b3 |
Use DB for auth sessions (#1233)
* DB sessions * Validations for profile image |
||
|
|
75ded1c18f | Set last_login_at only at login instead of every single action (#1017) |