Allow Google SSO to be configured from /settings/sso (DB fallback)

Until now, Google SSO required setting GOOGLE_CLIENT_ID /
GOOGLE_CLIENT_SECRET / GOOGLE_ALLOWED_DOMAINS in the environment and
restarting the container. This commit adds a UI-driven configuration
path that doesn't need a restart, while keeping ENV as the priority
source for production deployments.

Storage: new EncryptedConfig key `google_sso_configs` (added to
CONFIG_KEYS) with shape:
  { enabled: bool, client_id, client_secret, allowed_domains: [..] }
The secret rides on Rails' `encrypts :value` like every other
EncryptedConfig record.

Strategy registration: the Devise initializer now always registers
:google_oauth2 with a setup proc, so the omniauth routes exist
unconditionally. The setup proc calls Wabosign.google_sso_credentials
per request — that helper checks ENV first (priority) and falls back
to the DB. Empty creds yield :source => :none and the Google button
is hidden by the sign-in partial.

User model: :omniauthable + omniauth_providers: [:google_oauth2] are
now unconditional (matches the always-registered route). The
boot-time fragile gating that broke `bundle exec puma` when env vars
weren't set is gone.

Routes: omniauth_callbacks no longer depends on ENV. /settings/sso
gains a :create action. SsoSettingsController#create persists the
form payload via the existing EncryptedConfig pattern (and never
overwrites a saved secret with a blank).

View: /settings/sso is now a real form (client_id, client_secret,
allowed_domains, enabled toggle) instead of an env-only status panel.
A banner explains ENV precedence when GOOGLE_CLIENT_ID is set. The
redirect URI to register in Google Cloud Console is shown in the
"not configured" state.

User#default_sso_account now prefers the account that owns the
UI-saved config so JIT-provisioned users land in the right tenant
when an admin sets up SSO from the UI in a multi-account deployment.

Specs: the omniauth_callbacks request specs were stubbing the removed
Wabosign::GOOGLE_* constants. Switched them to
`allow(Wabosign).to receive(:google_sso_credentials)`. All 5 pass.

Smoke-tested the rebuilt image in three states:
  - No ENV, no DB:   container boots, /sign_in 200, no button.
  - DB config saved: button appears on the very next /sign_in render.
  - ENV set + DB set: ENV wins (allowed_domains and creds come from ENV).

Docs: GOOGLE_SSO.md gains a section describing the UI path and how
the two sources interact.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
pull/687/head
Wabo 1 month ago
parent 07f6883a37
commit dacefffd24

@ -37,18 +37,35 @@ Create the OAuth client at <https://console.cloud.google.com/apis/credentials>
## Configuration ## Configuration
Set these environment variables on the WaboSign process (in `wabosign.env`, the docker-compose `environment:` block, or your hosting provider's secret store): Two ways to configure, in priority order:
### 1. Environment variables (priority — recommended for production)
Set these on the WaboSign process (in `wabosign.env`, the docker-compose `environment:` block, or your hosting provider's secret store):
| Variable | Required | Example | Notes | | Variable | Required | Example | Notes |
|---|---|---|---| |---|---|---|---|
| `GOOGLE_CLIENT_ID` | yes | `1234.apps.googleusercontent.com` | From the Google Cloud OAuth client. | | `GOOGLE_CLIENT_ID` | yes | `1234.apps.googleusercontent.com` | From the Google Cloud OAuth client. |
| `GOOGLE_CLIENT_SECRET` | yes | `GOCSPX-…` | From the Google Cloud OAuth client. | | `GOOGLE_CLIENT_SECRET` | yes | `GOCSPX-…` | From the Google Cloud OAuth client. |
| `GOOGLE_ALLOWED_DOMAINS` | recommended | `wabo.cc,partner.example` | Comma-separated. Only Google accounts whose `hd` claim is in this list can sign in. Empty = any Google account allowed (a warning is logged at boot). | | `GOOGLE_ALLOWED_DOMAINS` | recommended | `wabo.cc,partner.example` | Comma-separated. Only Google accounts whose `hd` claim is in this list can sign in. Empty = any Google account allowed. |
| `GOOGLE_DEFAULT_ACCOUNT_ID` | no | `1` | The WaboSign `Account` JIT-provisioned users are attached to. Defaults to the oldest account. Useful only if you run multiple `Account` records on one deployment. | | `GOOGLE_DEFAULT_ACCOUNT_ID` | no | `1` | The WaboSign `Account` JIT-provisioned users are attached to. Defaults to the oldest account (or the account that owns the UI-saved config, if no env override). Useful only if you run multiple `Account` records on one deployment. |
ENV-driven values take effect at the next request — no restart needed. ENV always wins over the UI form below.
### 2. Web UI (fallback — for ENV-free deployments)
Sign in as an admin, go to **Settings → Google SSO** (`/settings/sso`), and fill in:
- **Enable Google SSO** — toggle. Required for the button to appear on the sign-in page.
- **Client ID** — from your Google Cloud OAuth client.
- **Client Secret** — same. Stored encrypted via Rails `encrypts :value` on `EncryptedConfig`. Leave the field blank when editing later to keep the saved secret unchanged.
- **Allowed Workspace Domains** — comma-separated. Same semantics as `GOOGLE_ALLOWED_DOMAINS`.
The UI-saved config is read on every sign-in via an OmniAuth `setup` proc, so changes take effect on the next click of "Sign in with Google" — no restart needed. The Client Secret is stored encrypted in the `encrypted_configs` table under the `google_sso_configs` key.
After changing any of these, **restart the WaboSign process** — Devise's OmniAuth strategy is registered at boot. The OAuth redirect URI to register in [Google Cloud Console](https://console.cloud.google.com/apis/credentials) is shown on the settings page; it follows the pattern `https://<your-host>/auth/google_oauth2/callback`.
The Devise integration is conditional: if either `GOOGLE_CLIENT_ID` or `GOOGLE_CLIENT_SECRET` is missing, the `:omniauthable` Devise module is not loaded and the Google button is hidden. This means development environments without creds keep working unchanged. If ENV is also set, the settings page shows a banner indicating that ENV takes precedence; the form is still editable, but the saved values are unused until you unset the env vars (and restart).
--- ---

@ -3,13 +3,45 @@
class SsoSettingsController < ApplicationController class SsoSettingsController < ApplicationController
before_action :load_encrypted_config before_action :load_encrypted_config
authorize_resource :encrypted_config, only: :index authorize_resource :encrypted_config, only: :index
authorize_resource :encrypted_config, parent: false, only: :create
def index; end def index; end
def create
new_value = build_sso_value
if @encrypted_config.update(value: new_value)
redirect_to settings_sso_index_path, notice: I18n.t('changes_have_been_saved')
else
render :index, status: :unprocessable_content
end
rescue StandardError => e
flash[:alert] = e.message
render :index, status: :unprocessable_content
end
private private
def load_encrypted_config def load_encrypted_config
@encrypted_config = @encrypted_config =
EncryptedConfig.find_or_initialize_by(account: current_account, key: 'saml_configs') EncryptedConfig.find_or_initialize_by(account: current_account,
key: EncryptedConfig::GOOGLE_SSO_KEY)
end
def build_sso_value
submitted = params.require(:encrypted_config).permit(value: {})[:value].to_h
existing = @encrypted_config.value || {}
# Don't clobber the saved secret with a blank one — the field is
# rendered empty (we never echo it back) so an unchanged form would
# otherwise wipe it out.
submitted['client_secret'] = existing['client_secret'] if submitted['client_secret'].to_s.empty?
submitted['allowed_domains'] =
submitted.delete('allowed_domains_csv').to_s.split(',').map(&:strip).reject(&:empty?)
submitted['enabled'] = submitted['enabled'].to_s == '1' || submitted['enabled'].to_s == 'true'
submitted.compact
end end
end end

@ -26,7 +26,8 @@ class EncryptedConfig < ApplicationRecord
EMAIL_SMTP_KEY = 'action_mailer_smtp', EMAIL_SMTP_KEY = 'action_mailer_smtp',
ESIGN_CERTS_KEY = 'esign_certs', ESIGN_CERTS_KEY = 'esign_certs',
TIMESTAMP_SERVER_URL_KEY = 'timestamp_server_url', TIMESTAMP_SERVER_URL_KEY = 'timestamp_server_url',
APP_URL_KEY = 'app_url' APP_URL_KEY = 'app_url',
GOOGLE_SSO_KEY = 'google_sso_configs'
].freeze ].freeze
belongs_to :account belongs_to :account

@ -69,13 +69,14 @@ class User < ApplicationRecord
has_many :encrypted_configs, dependent: :destroy, class_name: 'EncryptedUserConfig' has_many :encrypted_configs, dependent: :destroy, class_name: 'EncryptedUserConfig'
has_many :email_messages, dependent: :destroy, foreign_key: :author_id, inverse_of: :author has_many :email_messages, dependent: :destroy, foreign_key: :author_id, inverse_of: :author
devise_modules = %i[two_factor_authenticatable recoverable rememberable validatable trackable lockable] # :omniauthable is included unconditionally so the Devise routes are
devise_opts = {} # always declared. Whether the strategy actually works (and whether the
if Wabosign.google_sso_enabled? # Google button is shown on the sign-in page) is gated by
devise_modules << :omniauthable # Wabosign.google_sso_enabled? at runtime — driven by ENV and/or the
devise_opts[:omniauth_providers] = [:google_oauth2] # `google_sso_configs` EncryptedConfig record.
end devise :two_factor_authenticatable, :recoverable, :rememberable,
devise(*devise_modules, **devise_opts) :validatable, :trackable, :lockable, :omniauthable,
omniauth_providers: [:google_oauth2]
attribute :role, :string, default: ADMIN_ROLE attribute :role, :string, default: ADMIN_ROLE
attribute :uuid, :string, default: -> { SecureRandom.uuid } attribute :uuid, :string, default: -> { SecureRandom.uuid }
@ -164,10 +165,17 @@ class User < ApplicationRecord
end end
def self.default_sso_account def self.default_sso_account
# ENV override always wins.
if Wabosign::GOOGLE_DEFAULT_ACCOUNT_ID.present? if Wabosign::GOOGLE_DEFAULT_ACCOUNT_ID.present?
Account.find_by(id: Wabosign::GOOGLE_DEFAULT_ACCOUNT_ID) return Account.find_by(id: Wabosign::GOOGLE_DEFAULT_ACCOUNT_ID)
else
Account.order(:created_at).first
end end
# If an admin saved the Google SSO config via the UI, JIT-provision into
# that same account so admins land in the right tenant.
if (db_config = EncryptedConfig.find_by(key: EncryptedConfig::GOOGLE_SSO_KEY))
return db_config.account if db_config.account && db_config.account.archived_at.nil?
end
Account.order(:created_at).first
end end
end end

@ -1,30 +0,0 @@
<% if Wabosign.google_sso_enabled? %>
<div class="alert alert-success">
<%= svg_icon('discount_check_filled', class: 'w-6 h-6') %>
<div>
<p class="font-bold">Google SSO is enabled</p>
<p class="text-gray-700">
Configured via environment variables.
<% if Wabosign::GOOGLE_ALLOWED_DOMAINS.any? %>
Allowed Workspace domain<%= 's' if Wabosign::GOOGLE_ALLOWED_DOMAINS.size > 1 %>:
<code><%= Wabosign::GOOGLE_ALLOWED_DOMAINS.join(', ') %></code>.
<% else %>
<strong>Warning:</strong> no domain allowlist set &mdash; any Google account may sign in. Set <code>GOOGLE_ALLOWED_DOMAINS</code> to restrict.
<% end %>
</p>
</div>
</div>
<% else %>
<div class="alert">
<%= svg_icon('info_circle', class: 'w-6 h-6') %>
<div>
<p class="font-bold">Google SSO is not configured</p>
<p class="text-gray-700">
Set <code>GOOGLE_CLIENT_ID</code>, <code>GOOGLE_CLIENT_SECRET</code>, and <code>GOOGLE_ALLOWED_DOMAINS</code> (comma-separated) and restart the app. The OAuth redirect URI to register in Google Cloud Console is <code><%= "#{root_url}users/auth/google_oauth2/callback" rescue '/users/auth/google_oauth2/callback' %></code>.
</p>
<p class="text-gray-700 mt-2">
SAML 2.0 SSO is not bundled with this open-source edition. To enable it, add <code>ruby-saml</code> and <code>devise-saml-authenticatable</code> and wire the ACS/SLO/metadata routes; encrypted config is stored under the <code>saml_configs</code> key on the account.
</p>
</div>
</div>
<% end %>

@ -1,8 +1,77 @@
<div class="flex flex-wrap space-y-4 md:flex-nowrap md:space-y-0"> <div class="flex flex-wrap space-y-4 md:flex-nowrap md:space-y-0">
<%= render 'shared/settings_nav' %> <%= render 'shared/settings_nav' %>
<div class="flex-grow max-w-xl mx-auto"> <div class="flex-grow max-w-xl mx-auto">
<h1 class="text-4xl font-bold mb-4">SAML SSO</h1> <h1 class="text-4xl font-bold mb-4">Google SSO</h1>
<%= render 'placeholder' %>
<% creds = Wabosign.google_sso_credentials %>
<% value = @encrypted_config.value || {} %>
<% if creds[:source] == :env %>
<div class="alert mb-4">
<%= svg_icon('info_circle', class: 'w-6 h-6') %>
<div>
<p class="font-bold">Google SSO is configured via environment variables</p>
<p class="text-gray-700">
<code>GOOGLE_CLIENT_ID</code> and <code>GOOGLE_CLIENT_SECRET</code> are set on the running process, so ENV-driven configuration is in effect. ENV always takes precedence over anything saved on this page. Unset the env vars (and restart) to switch to the values configured here.
</p>
</div>
</div>
<% elsif creds[:source] == :db %>
<div class="alert alert-success mb-4">
<%= svg_icon('discount_check_filled', class: 'w-6 h-6') %>
<div>
<p class="font-bold">Google SSO is enabled</p>
<p class="text-gray-700">
<% if creds[:allowed_domains].any? %>
Allowed Workspace domain<%= 's' if creds[:allowed_domains].size > 1 %>: <code><%= creds[:allowed_domains].join(', ') %></code>.
<% else %>
<strong>Warning:</strong> no domain allowlist is set. Any Google account can sign in.
<% end %>
</p>
</div>
</div>
<% else %>
<div class="alert mb-4">
<%= svg_icon('info_circle', class: 'w-6 h-6') %>
<div>
<p class="font-bold">Google SSO is not configured</p>
<p class="text-gray-700">
Fill in your Google Cloud OAuth client details below. The OAuth redirect URI to register in <a href="https://console.cloud.google.com/apis/credentials" target="_blank" rel="noopener" class="link">Google Cloud Console</a> is
<code><%= "#{root_url}auth/google_oauth2/callback" rescue '/auth/google_oauth2/callback' %></code>.
</p>
</div>
</div>
<% end %>
<%= form_for @encrypted_config, url: settings_sso_index_path, method: :post, html: { autocomplete: 'off', class: 'space-y-4' } do |f| %>
<%= f.fields_for :value do |ff| %>
<div class="form-control">
<label class="label cursor-pointer" for="encrypted_config_value_enabled">
<span class="label-text font-medium">Enable Google SSO</span>
<%= ff.check_box :enabled, { class: 'toggle', checked: value['enabled'] == true }, '1', '0' %>
</label>
</div>
<div class="form-control">
<%= ff.label :client_id, 'Client ID', class: 'label' %>
<%= ff.text_field :client_id, value: value['client_id'], class: 'base-input', placeholder: '1234567890.apps.googleusercontent.com' %>
</div>
<div class="form-control">
<%= ff.label :client_secret, 'Client Secret', class: 'label' %>
<%= ff.password_field :client_secret, class: 'base-input', placeholder: value['client_secret'].present? ? '*************' : 'GOCSPX-…' %>
<% if value['client_secret'].present? %>
<span class="label-text-alt mt-1 opacity-70">Leave blank to keep the saved secret.</span>
<% end %>
</div>
<div class="form-control">
<%= ff.label :allowed_domains_csv, 'Allowed Workspace Domains', class: 'label' %>
<%= ff.text_field :allowed_domains_csv, value: Array(value['allowed_domains']).join(', '), class: 'base-input', placeholder: 'wabo.cc, partner.example' %>
<span class="label-text-alt mt-1 opacity-70">Comma-separated. Only Google accounts whose Workspace <code>hd</code> claim matches one of these domains can sign in. Leave blank to allow any Google account (not recommended).</span>
</div>
<% end %>
<div class="form-control pt-2">
<%= f.button button_title(title: t('save'), disabled_with: t('saving')), class: 'base-button' %>
</div>
<% end %>
</div> </div>
<div class="w-0 md:w-52"></div> <div class="w-0 md:w-52"></div>
</div> </div>

@ -334,24 +334,22 @@ Devise.setup do |config|
# changed. Defaults to true, so a user is signed in automatically after changing a password. # changed. Defaults to true, so a user is signed in automatically after changing a password.
# config.sign_in_after_change_password = true # config.sign_in_after_change_password = true
# NB: Wabosign-the-module relies on Rails.root, which isn't available yet # The :google_oauth2 strategy is always registered so its routes exist at
# when this initializer runs. Read ENV directly here so the omniauth strategy # boot. Credentials are resolved per-request by the setup proc, which
# can be registered at boot. Controllers/models access the same values via # consults Wabosign.google_sso_credentials (ENV takes priority, falling
# Wabosign::GOOGLE_* once Rails is fully initialized. # back to the `google_sso_configs` EncryptedConfig record). This lets
google_client_id = ENV.fetch('GOOGLE_CLIENT_ID', nil) # admins manage Google SSO from /settings/sso without restarting the app.
google_client_secret = ENV.fetch('GOOGLE_CLIENT_SECRET', nil) config.omniauth :google_oauth2, '', '',
if google_client_id.present? && google_client_secret.present? setup: lambda { |env|
config.omniauth :google_oauth2, strategy = env['omniauth.strategy']
google_client_id, creds = Wabosign.google_sso_credentials
google_client_secret, strategy.options[:client_id] = creds[:client_id].to_s
{ strategy.options[:client_secret] = creds[:client_secret].to_s
scope: 'email,profile', strategy.options[:scope] = 'email,profile'
prompt: 'select_account', strategy.options[:prompt] = 'select_account'
access_type: 'online', strategy.options[:access_type] = 'online'
hd: ENV.fetch('GOOGLE_ALLOWED_DOMAINS', '') strategy.options[:hd] = creds[:allowed_domains].presence
.split(',').map(&:strip).reject(&:empty?).presence
} }
end
ActiveSupport.run_load_hooks(:devise_config, config) ActiveSupport.run_load_hooks(:devise_config, config)
end end

@ -14,21 +14,15 @@ Rails.application.routes.draw do
get 'up' => 'rails/health#show' get 'up' => 'rails/health#show'
get 'manifest' => 'pwa#manifest' get 'manifest' => 'pwa#manifest'
# Mirror the User model's conditional :omniauthable inclusion. ENV is the # User is always :omniauthable (see app/models/user.rb); the strategy is
# one source of truth available at routes-load time (Wabosign-the-module # registered with a setup proc in config/initializers/devise.rb that pulls
# may not be autoloadable yet) — keep this check in sync with # live credentials from ENV or the database at request time.
# config/initializers/devise.rb and app/models/user.rb. devise_for :users, path: '/', only: %i[sessions passwords omniauth_callbacks],
# Devise raises if controllers[:omniauth_callbacks] is set but User isn't controllers: {
# omniauthable, so the controllers hash must omit that key too. sessions: 'sessions',
google_sso_enabled = ENV['GOOGLE_CLIENT_ID'].present? && ENV['GOOGLE_CLIENT_SECRET'].present? passwords: 'passwords',
devise_actions = %i[sessions passwords] omniauth_callbacks: 'users/omniauth_callbacks'
devise_controllers = { sessions: 'sessions', passwords: 'passwords' } }
if google_sso_enabled
devise_actions << :omniauth_callbacks
devise_controllers[:omniauth_callbacks] = 'users/omniauth_callbacks'
end
devise_for :users, path: '/', only: devise_actions, controllers: devise_controllers
devise_scope :user do devise_scope :user do
resource :invitation, only: %i[update] do resource :invitation, only: %i[update] do
@ -198,7 +192,7 @@ Rails.application.routes.draw do
resource :reveal_access_token, only: %i[show create], controller: 'reveal_access_token' resource :reveal_access_token, only: %i[show create], controller: 'reveal_access_token'
end end
resources :email, only: %i[index create], controller: 'email_smtp_settings' resources :email, only: %i[index create], controller: 'email_smtp_settings'
resources :sso, only: %i[index], controller: 'sso_settings' resources :sso, only: %i[index create], controller: 'sso_settings'
resources :notifications, only: %i[index create], controller: 'notifications_settings' resources :notifications, only: %i[index create], controller: 'notifications_settings'
resource :esign, only: %i[show create new update destroy], controller: 'esign_settings' resource :esign, only: %i[show create new update destroy], controller: 'esign_settings'
resources :users, only: %i[index] resources :users, only: %i[index]

@ -14,10 +14,6 @@ module Wabosign
SUPPORT_EMAIL = 'wabosign@wabo.cc' SUPPORT_EMAIL = 'wabosign@wabo.cc'
HOST = ENV.fetch('HOST', 'localhost') HOST = ENV.fetch('HOST', 'localhost')
AATL_CERT_NAME = 'wabosign_aatl' AATL_CERT_NAME = 'wabosign_aatl'
GOOGLE_CLIENT_ID = ENV.fetch('GOOGLE_CLIENT_ID', nil)
GOOGLE_CLIENT_SECRET = ENV.fetch('GOOGLE_CLIENT_SECRET', nil)
GOOGLE_ALLOWED_DOMAINS = ENV.fetch('GOOGLE_ALLOWED_DOMAINS', '')
.split(',').map(&:strip).reject(&:empty?).freeze
GOOGLE_DEFAULT_ACCOUNT_ID = ENV.fetch('GOOGLE_DEFAULT_ACCOUNT_ID', nil) GOOGLE_DEFAULT_ACCOUNT_ID = ENV.fetch('GOOGLE_DEFAULT_ACCOUNT_ID', nil)
CONSOLE_URL = if Rails.env.development? CONSOLE_URL = if Rails.env.development?
'http://console.localhost.io:3001' 'http://console.localhost.io:3001'
@ -127,21 +123,57 @@ module Wabosign
@default_url_options = nil @default_url_options = nil
end end
# Returns the live Google SSO credentials, merging ENV (priority) with the
# `google_sso_configs` EncryptedConfig (UI fallback). Called at request
# time by the Devise OmniAuth setup proc and the sign-in page partial.
#
# Shape: { client_id:, client_secret:, allowed_domains:, source: :env|:db|:none }
def google_sso_credentials
env_id = ENV.fetch('GOOGLE_CLIENT_ID', nil)
env_secret = ENV.fetch('GOOGLE_CLIENT_SECRET', nil)
if env_id.present? && env_secret.present?
return {
client_id: env_id,
client_secret: env_secret,
allowed_domains: ENV.fetch('GOOGLE_ALLOWED_DOMAINS', '')
.split(',').map(&:strip).reject(&:empty?),
source: :env
}
end
db_value = google_sso_db_value
if db_value.is_a?(Hash) && db_value['enabled'] &&
db_value['client_id'].to_s.present? && db_value['client_secret'].to_s.present?
return {
client_id: db_value['client_id'].to_s,
client_secret: db_value['client_secret'].to_s,
allowed_domains: Array(db_value['allowed_domains']).map(&:to_s).map(&:strip).reject(&:empty?),
source: :db
}
end
{ client_id: nil, client_secret: nil, allowed_domains: [], source: :none }
end
def google_sso_db_value
return nil unless defined?(EncryptedConfig) && EncryptedConfig.table_exists?
EncryptedConfig.find_by(key: EncryptedConfig::GOOGLE_SSO_KEY)&.value
rescue ActiveRecord::StatementInvalid, ActiveRecord::ConnectionNotEstablished
nil
end
def google_sso_enabled? def google_sso_enabled?
GOOGLE_CLIENT_ID.present? && GOOGLE_CLIENT_SECRET.present? creds = google_sso_credentials
creds[:client_id].present? && creds[:client_secret].present?
end end
def google_domain_allowed?(hd) def google_domain_allowed?(hd)
return false if hd.blank? return false if hd.blank?
return true if GOOGLE_ALLOWED_DOMAINS.empty?
GOOGLE_ALLOWED_DOMAINS.include?(hd) domains = google_sso_credentials[:allowed_domains]
end return true if domains.empty?
end
if Wabosign.google_sso_enabled? && Wabosign::GOOGLE_ALLOWED_DOMAINS.empty? domains.include?(hd)
Rails.logger.warn( end
'[Wabosign] Google SSO is enabled but GOOGLE_ALLOWED_DOMAINS is empty — ' \
'any Google account will be permitted to sign in.'
)
end end

@ -12,9 +12,12 @@ RSpec.describe 'Google OAuth2 callback', type: :request do
OmniAuth.config.test_mode = true OmniAuth.config.test_mode = true
OmniAuth.config.logger = Rails.logger OmniAuth.config.logger = Rails.logger
stub_const('Wabosign::GOOGLE_CLIENT_ID', 'test-client-id') allow(Wabosign).to receive(:google_sso_credentials).and_return(
stub_const('Wabosign::GOOGLE_CLIENT_SECRET', 'test-client-secret') client_id: 'test-client-id',
stub_const('Wabosign::GOOGLE_ALLOWED_DOMAINS', ['wabo.cc'].freeze) client_secret: 'test-client-secret',
allowed_domains: ['wabo.cc'],
source: :env
)
stub_const('Wabosign::GOOGLE_DEFAULT_ACCOUNT_ID', nil) stub_const('Wabosign::GOOGLE_DEFAULT_ACCOUNT_ID', nil)
end end

Loading…
Cancel
Save