Skip to content

Vendor omniauth-gitlab gem to provide backwards compatibility

Stan Hu requested to merge sh-vendor-omniauth-gitlab into master

What does this MR do and why?

This commit vendors the omniauth-gem v4.0.0 to support:

  1. OmniAuth v1 and v2. OmniAuth v2 disables GET requests by default and defaults to POST. GitLab already has patched v1 to use POST, but other dependencies need to be updated: https://gitlab.com/gitlab-org/gitlab/-/issues/30073.

  2. oauth2 v1.4.9 and up. v1.4.9 fixed relative URL handling.

    However, this breaks the default GitLab.com configuration and existing configurations that use the /api/v4 suffix in the site parameter (as described in https://docs.gitlab.com/ee/integration/gitlab.html).

    omniauth-gitlab v4.0.0 fixed the first issue, but the second issue requires an admin to update site to drop the suffix.

    This fork restores backwards compatibility that was removed in omniauth-gitlab v2.0.0: https://github.com/linchus/omniauth-gitlab/commit/bb4cec2c9f8f067fdfe1f9aa219973e5d8e4a0a3

Relates to https://gitlab.com/gitlab-org/gitlab/-/issues/361284

How to set up and validate locally

  1. Follow the instructions in https://docs.gitlab.com/ee/integration/gitlab.html to set up a new OAuth application.

  2. Quick reference settings to add to gitlab/config.yml for the GDK:

development:
  <<: *base
  omniauth:
    providers:
    - { name: 'gitlab',
	app_id: 'YOUR-CLIENT-ID',
        app_secret: 'YOUR-CLIENT-SECRET' }
        args: { scope: "read_user", client_options: { site: "https://gitlab.example.org" } } }
  1. Navigate to your GDK and into /-/profile/account. Click on Connect GitLab.com.
  2. Your user should be linked. Sign out and click on Log in with GitLab.com.

I tested the following scenarios:

  1. No args (GitLab.com)
  2. args with client_options.site: https://gitlab.example.org/api/v4 (legacy mode)
  3. args with client_options.site: https://gitlab.example.org (new)

Diff to upstream version v4.0.0

The diff
Only in vendor/gems/omniauth-gitlab: Gemfile.lock
Only in /home/peter/devel/omniauth-gitlab: .git
Only in /home/peter/devel/omniauth-gitlab: .github
diff -ru /home/peter/devel/omniauth-gitlab/.gitignore vendor/gems/omniauth-gitlab/.gitignore
--- /home/peter/devel/omniauth-gitlab/.gitignore	2022-06-30 13:01:21.077556106 +0200
+++ vendor/gems/omniauth-gitlab/.gitignore	2022-06-30 13:00:16.694402636 +0200
@@ -4,7 +4,6 @@
 .config
 .yardoc
 .rvmrc
-Gemfile.lock
 InstalledFiles
 _yardoc
 coverage
Only in vendor/gems/omniauth-gitlab: .gitlab-ci.yml
diff -ru /home/peter/devel/omniauth-gitlab/lib/omniauth/strategies/gitlab.rb vendor/gems/omniauth-gitlab/lib/omniauth/strategies/gitlab.rb
--- /home/peter/devel/omniauth-gitlab/lib/omniauth/strategies/gitlab.rb	2022-06-30 13:01:21.077556106 +0200
+++ vendor/gems/omniauth-gitlab/lib/omniauth/strategies/gitlab.rb	2022-06-30 13:00:16.694402636 +0200
@@ -1,9 +1,12 @@
+# frozen_string_literal: true
 
 require 'omniauth-oauth2'
 
 module OmniAuth
   module Strategies
     class GitLab < OmniAuth::Strategies::OAuth2
+      API_SUFFIX_REGEX = %r{/api/v(\d+)/?$}.freeze
+
       option :client_options, site: 'https://gitlab.com'
 
       option :redirect_url
@@ -24,11 +27,15 @@
       end
 
       def raw_info
-        @raw_info ||= access_token.get('api/v4/user').parsed
+        @raw_info ||= access_token.get(user_endpoint_url).parsed
       end
 
       private
 
+      def user_endpoint_url
+        options.client_options.site.match(API_SUFFIX_REGEX) ? 'user' : 'api/v4/user'
+      end
+
       def callback_url
         options.redirect_url || (full_host + script_name + callback_path)
       end
diff -ru /home/peter/devel/omniauth-gitlab/omniauth-gitlab.gemspec vendor/gems/omniauth-gitlab/omniauth-gitlab.gemspec
--- /home/peter/devel/omniauth-gitlab/omniauth-gitlab.gemspec	2022-06-30 13:01:21.077556106 +0200
+++ vendor/gems/omniauth-gitlab/omniauth-gitlab.gemspec	2022-06-30 13:00:16.694402636 +0200
@@ -12,12 +12,11 @@
   gem.summary       = 'This is the strategy for authenticating to your GitLab service'
   gem.homepage      = 'https://github.com/linchus/omniauth-gitlab'
 
-  gem.files         = `git ls-files`.split($/)
-  gem.executables   = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
-  gem.test_files    = gem.files.grep(%r{^(test|spec|features)/})
+  gem.files         = Dir['lib/**/*.rb']
+  gem.test_files    = Dir['spec/**/*.rb']
   gem.require_paths = ['lib']
 
-  gem.add_dependency 'omniauth', '~> 2.0'
+  gem.add_dependency 'omniauth', '~> 1.0'
   gem.add_dependency 'omniauth-oauth2', '~> 1.7.1'
   gem.add_development_dependency 'rspec', '~> 3.1'
   gem.add_development_dependency 'rspec-its', '~> 1.0'
Only in /home/peter/devel/omniauth-gitlab: .project
diff -ru /home/peter/devel/omniauth-gitlab/README.md vendor/gems/omniauth-gitlab/README.md
--- /home/peter/devel/omniauth-gitlab/README.md	2022-06-30 13:03:56.563478888 +0200
+++ vendor/gems/omniauth-gitlab/README.md	2022-06-30 13:00:16.694402636 +0200
@@ -1,5 +1,24 @@
 # Omniauth::Gitlab
 
+This is fork of [omniauth-gitlab](https://github.com/linchus/omniauth-gitlab) to support:
+
+1. OmniAuth v1 and v2. OmniAuth v2 disables GET requests by default
+   and defaults to POST. GitLab already has patched v1 to use POST,
+   but other dependencies need to be updated:
+   https://gitlab.com/gitlab-org/gitlab/-/issues/30073.
+
+2. [`oauth2`](https://github.com/oauth-xx/oauth2) v1.4.9 and up.
+   [v1.4.9 fixed relative URL handling](https://github.com/oauth-xx/oauth2/pull/469).
+
+   However, this breaks the default GitLab.com configuration and
+   existing configurations that use the `/api/v4` suffix in the `site`
+   parameter.
+   [omniauth-gitlab v4.0.0 fixed the first issue](https://github.com/linchus/omniauth-gitlab/pull/22),
+   but the second issue requires an admin to update `site` to drop the suffix.
+
+   This fork restores backwards compatibility that was removed in omniauth-gitlab v2.0.0:
+   https://github.com/linchus/omniauth-gitlab/commit/bb4cec2c9f8f067fdfe1f9aa219973e5d8e4a0a3
+
 [![Join the chat at https://gitter.im/linchus/omniauth-gitlab](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/linchus/omniauth-gitlab?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 
 This is the OAuth2 strategy for authenticating to your GitLab service.
@@ -34,7 +53,7 @@
       provider :gitlab, ENV['GITLAB_KEY'], ENV['GITLAB_SECRET'],
         {
            client_options: {
-             site: 'https://gitlab.YOURDOMAIN.com'
+             site: 'https://gitlab.YOURDOMAIN.com/api/v4'
            }
         }
     end
Only in /home/peter/devel/omniauth-gitlab: .rspec
diff -ru /home/peter/devel/omniauth-gitlab/spec/omniauth/strategies/gitlab_spec.rb vendor/gems/omniauth-gitlab/spec/omniauth/strategies/gitlab_spec.rb
--- /home/peter/devel/omniauth-gitlab/spec/omniauth/strategies/gitlab_spec.rb	2022-06-30 13:03:56.563478888 +0200
+++ vendor/gems/omniauth-gitlab/spec/omniauth/strategies/gitlab_spec.rb	2022-06-30 13:00:16.694402636 +0200
@@ -50,9 +50,31 @@
   end
 
   describe '#raw_info' do
-    it 'sent request to current user endpoint' do
-      expect(access_token).to receive(:get).with('api/v4/user').and_return(response)
-      expect(subject.raw_info).to eq(parsed_response)
+    context 'with new configuration' do
+      it 'sent request to current user endpoint' do
+        expect(access_token).to receive(:get).with('api/v4/user').and_return(response)
+        expect(subject.raw_info).to eq(parsed_response)
+      end
+    end
+
+    context 'with old style configuration' do
+      let(:enterprise_site) { 'https://some.other.site.com/api/v4' }
+
+      subject { enterprise }
+
+      it 'sent request to current user endpoint' do
+        expect(access_token).to receive(:get).with('user').and_return(response)
+        expect(subject.raw_info).to eq(parsed_response)
+      end
+
+      context 'with a trailing slash' do
+        let(:enterprise_site) { 'https://some.other.site.com/api/v4/' }
+
+        it 'sent request to current user endpoint' do
+          expect(access_token).to receive(:get).with('user').and_return(response)
+          expect(subject.raw_info).to eq(parsed_response)
+        end
+      end
     end
   end
 end

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Peter Leitzen

Merge request reports