Install the published add_auth package through your Rails app’s Gemfile, then rehearse these changes in an isolated copy of the app. Enable only the capabilities you need. Review the release status and upgrade procedure first.
Use revocable native sessions with an explicit expiration policy and secure browser-to-app handoffs.
In the Rails app’s Gemfile, select the reviewed 0.3 release line:
gem "add_auth", "~> 0.3.0"Run bundle install from the app’s root. Confirm bundle exec ruby -e 'require "add_auth"; puts AddAuth::VERSION' reports the selected version before generating files.
Choose the client contract
Prepare the Rails authentication/session schema and HTTPS. Inventory installed client versions, token storage, callback handling, GraphQL/REST headers, widgets, push registrations, account switching and logout. The gem’s JSON endpoints are distinct from any existing app-specific v1 response envelope; keep compatibility mapping in thin host controllers.
Prepare finite mobile sessions
In the isolated destination:
bin/rails generate add_auth:mobile_sessions
RAILS_ENV=test bin/rails db:migrateReview the generated configuration. This example selects a 30-day absolute limit and 14-day inactivity limit:
AddAuth.configure do |config|
config.mobile.lifetime = 30 * 86_400
config.mobile.idle_timeout = 14 * 86_400
config.mobile.clients = %w[android ios]
config.mobile.enabled = true
endThese are explicit host-selected values, not browser timeout changes. Client identifiers select configuration and do not prove app identity. The finite profile requires fresh sign-in after expiry; rotating refresh-token families are not implemented by this profile.
Verify the JSON contract
POST /mobile/session accepts top-level email_address, password and client_id. Success returns 201 with token, token_type, expires_at, session_id and user_id. Send the bearer only in the Authorization header to approved HTTPS origins. Cookie credentials do not authorize these API routes and mobile bearers do not authorize browser pages.
GET /mobile/session checks the current session; DELETE /mobile/session revokes it. GET /mobile/sessions lists account-scoped sessions, and deleting a listed session revokes that device. Global revocation requires the configured fresh proof. Current account policy is checked when existing credentials resume.
Bind the browser return to its initiator
Configure exact callbacks in config.mobile.callbacks, indexed by registered client ID. Persist unpredictable state and an S256 verifier securely before opening provider sign-in. The browser returns only a short-lived single-use code and state. Exchange them at POST /mobile/handoff with code_verifier and client_id. A bearer never belongs in a callback URL.
Reject wrong or extra callback fields, changed origins, stale pending state, wrong client/verifier, cancellation and replay. Keep pending state across process restart with a finite cutoff. A late completion or old unauthorized response must not replace or clear a newer account session.
Use the native Apple challenge
Optional native Apple verification uses ruby-jwt and fixed issuer, audience and JWKS configuration. The server issues a client- and purpose-bound nonce challenge before the platform UI begins. Submit the signed identity token with that challenge; nonce-less legacy login must be retired or explicitly rejected. New-account enrollment requires independent email confirmation and creates no session beforehand.
Test the actual consumers
Verify Android Keystore and iOS Keychain storage, strict HTTPS, restart/cancellation, current/other-device logout, expiry, 401 cleanup, account switching and stale asynchronous writes. Clear account-scoped caches, widgets and push registrations consistently. Test old/new protocol combinations and preserve only the declared compatibility window.
Local Android/iOS consumer acceptance uses trusted loopback HTTPS and synthetic identities. App-store signing, live Apple/provider setup and physical-device verification remain application deployment responsibilities. Continue with migration recovery.