Setting up multiple Okta orgs with the same Omniauth Oauth2 Strategy in Rails

Hello There,

I want to share what I did in order to support a second Okta Organization in a Ruby on Rails application using omniauth_oktaoauth gem.

I started with a basic spec to make sure I dont break anything:

RSpec.describe 'Sign in with Okta', type: :request do
  describe "Using Okta" do
    let(:user) { User.find_by email: user_email }
    let(:okta_oauth) do
      {
        provider: okta_provider.to_s,
        uid: "123456789",
        info: {
          name: "John Doe",
          email: user_email,
        }
      }
    end

    before(:each) do
      OmniAuth.config.test_mode = true
      OmniAuth.config.mock_auth[okta_provider] = OmniAuth::AuthHash.new(okta_oauth)
    end

    context "When using existing configuration" do
      let(:okta_provider) { :oktaoauth }
      let(:user_email) { "john.okta@existing.domain" }

      it "keeps working" do
        post "/users/auth/oktaoauth"
        follow_redirect!
        expect(user.email).to eq(user_email)
      end
    end
  end
end

With this, I proceed to write another spec to ensure the new option would work:

context "When using second okta org" do
  let(:okta_provider) { :second_okta }
  let(:user_email) { "john.okta@new.domain" }

  it "signs the right user in" do
    post "/users/auth/second_okta"
    follow_redirect!

    expect(user.email).to eq(user_email)
  end
end

After this, I started to use the normal steps:

# user.rb
devise :omniauthable, omniauth_providers: [:oktaoauth, :second_okta]

Then, modify the initializer to tell omniauth about the new strategy

# config/initializers/okta.rb
....
config.omniauth(:second_okta,
                Rails.configuration.second_okta.client_id,
                Rails.configuration.second_okta.client_secret,
                name: "second_okta",
                request_path: "/users/auth/second_okta",
                callback_path: "/users/auth/second_okta/callback",
                scope: "openid profile email",
                fields: %w[profile email],
                client_options: {
                  site: Rails.configuration.second_okta.url,
                  authorize_url: "#{Rails.configuration.second_okta.auth_issuer}/v1/authorize",
                  token_url: "#{Rails.configuration.second_okta.auth_issuer}/v1/token"
                },
                redirect_uri: "#{Rails.configuration.app.base_domain}/users/auth/second_okta/callback",
                issuer: Rails.configuration.second_okta.auth_issuer,
                strategy_class: OmniAuth::Strategies::Oktaoauth)

At the beginning, it looked easy to add a second option using the same strategy, but after dealing with omniauth internals and omniauth_oktaoauth source code itself, I found that I needed to specify name and strategy_class to override defaults, there's something inside the source code that did not work out of the box, I had to specify request_path and callback_path explicitly (I'll dig deeper later and send a patch if it's a bug).

After making those changes, it worked just fine.

Thanks!