From c652c2375b68efe12a6a384f78b4afd936d8f169 Mon Sep 17 00:00:00 2001
From: Jessie Young <jessieyoung@gitlab.com>
Date: Mon, 15 Aug 2022 13:59:42 -0700
Subject: [PATCH] Vendor omniauth-azure-oauth2 gem

* Our ultimate goal is to upgrade `omniauth` to v2.0. See the related
  [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/30073)
* In order to upgrade `omniauth` to v2.0, we need to upgrade
  `omniauth-azure-oauth2` because the latter has a dependency on the
former.
* There is an open issue asking the maintainer to make
  `omniauth-azure-oauth2` compatible with `omniauth` v2.0 but the author
  advised forking the gem:
  https://github.com/marknadig/omniauth-azure-oauth2/pull/29#issuecomment-663113582
* There is a fork called `omniauth-azure-activedirectory-v2` that
  supports [*only* the 2.0
  endpoints](https://github.com/RIPAGlobal/omniauth-azure-activedirectory-v2/pull/1)
  for Active Directory but we need to keep using `omniauth-azure-oauth2`
  for our customers who use the 1.0 ActiveDirectory endpoints
* This MR vendors the gem and updates its `.gemspec` file so that it is
  compatible with `omniauth` v2.0
* We may deprecate our usage of this gem in the future
  [(issue)](https://gitlab.com/gitlab-org/gitlab/-/issues/366212)
* MR where we vendored a different omniauth gem for same reasons:
  https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92485
---
 .gitlab/ci/rules.gitlab-ci.yml                |   6 +
 .gitlab/ci/vendored-gems.gitlab-ci.yml        |   8 +
 Gemfile                                       |   2 +-
 .../gems/omniauth-azure-oauth2/.gitlab-ci.yml |  28 ++
 .../gems/omniauth-azure-oauth2/CHANGELOG.md   |  31 ++
 vendor/gems/omniauth-azure-oauth2/Gemfile     |   8 +
 .../gems/omniauth-azure-oauth2/Gemfile.lock   |  73 ++++
 vendor/gems/omniauth-azure-oauth2/LICENSE     |  22 ++
 vendor/gems/omniauth-azure-oauth2/README.md   | 161 +++++++++
 vendor/gems/omniauth-azure-oauth2/Rakefile    |   6 +
 .../omniauth-azure-oauth2/examples/sinatra.rb |  31 ++
 .../lib/omniauth-azure-oauth2.rb              |   1 +
 .../lib/omniauth/azure_oauth2.rb              |   1 +
 .../lib/omniauth/azure_oauth2/version.rb      |   5 +
 .../lib/omniauth/strategies/azure_oauth2.rb   |  73 ++++
 .../omniauth-azure-oauth2.gemspec             |  25 ++
 .../omniauth/strategies/azure_oauth2_spec.rb  | 332 ++++++++++++++++++
 .../omniauth-azure-oauth2/spec/spec_helper.rb |   2 +
 vendor/gems/omniauth_crowd/.gitlab-ci.yml     |   2 +-
 19 files changed, 815 insertions(+), 2 deletions(-)
 create mode 100644 vendor/gems/omniauth-azure-oauth2/.gitlab-ci.yml
 create mode 100644 vendor/gems/omniauth-azure-oauth2/CHANGELOG.md
 create mode 100644 vendor/gems/omniauth-azure-oauth2/Gemfile
 create mode 100644 vendor/gems/omniauth-azure-oauth2/Gemfile.lock
 create mode 100644 vendor/gems/omniauth-azure-oauth2/LICENSE
 create mode 100644 vendor/gems/omniauth-azure-oauth2/README.md
 create mode 100644 vendor/gems/omniauth-azure-oauth2/Rakefile
 create mode 100644 vendor/gems/omniauth-azure-oauth2/examples/sinatra.rb
 create mode 100644 vendor/gems/omniauth-azure-oauth2/lib/omniauth-azure-oauth2.rb
 create mode 100644 vendor/gems/omniauth-azure-oauth2/lib/omniauth/azure_oauth2.rb
 create mode 100644 vendor/gems/omniauth-azure-oauth2/lib/omniauth/azure_oauth2/version.rb
 create mode 100644 vendor/gems/omniauth-azure-oauth2/lib/omniauth/strategies/azure_oauth2.rb
 create mode 100644 vendor/gems/omniauth-azure-oauth2/omniauth-azure-oauth2.gemspec
 create mode 100644 vendor/gems/omniauth-azure-oauth2/spec/omniauth/strategies/azure_oauth2_spec.rb
 create mode 100644 vendor/gems/omniauth-azure-oauth2/spec/spec_helper.rb

diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index dd47acd0b7def..fcb853a7bd2fc 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -1467,6 +1467,12 @@
       changes: ["vendor/gems/ipynbdiff/**/*"]
     - <<: *if-merge-request-labels-run-all-rspec
 
+.vendor:rules:omniauth-azure-oauth2:
+  rules:
+    - <<: *if-merge-request
+      changes: ["vendor/gems/omniauth-azure-oauth2/**/*"]
+    - <<: *if-merge-request-labels-run-all-rspec
+
 .vendor:rules:omniauth-cas3:
   rules:
     - <<: *if-merge-request
diff --git a/.gitlab/ci/vendored-gems.gitlab-ci.yml b/.gitlab/ci/vendored-gems.gitlab-ci.yml
index 275faa389e2c4..4408a6e4624a5 100644
--- a/.gitlab/ci/vendored-gems.gitlab-ci.yml
+++ b/.gitlab/ci/vendored-gems.gitlab-ci.yml
@@ -14,6 +14,14 @@ vendor ipynbdiff:
     include: vendor/gems/ipynbdiff/.gitlab-ci.yml
     strategy: depend
 
+vendor omniauth-azure-oauth2:
+  extends:
+    - .vendor:rules:omniauth-azure-oauth2
+  needs: []
+  trigger:
+    include: vendor/gems/omniauth-azure-oauth2/.gitlab-ci.yml
+    strategy: depend
+
 vendor omniauth-cas3:
   extends:
     - .vendor:rules:omniauth-cas3
diff --git a/Gemfile b/Gemfile
index 9b4340ab4553c..63a10ac6918bb 100644
--- a/Gemfile
+++ b/Gemfile
@@ -39,7 +39,7 @@ gem 'ruby-saml', '~> 1.13.0'
 gem 'omniauth', '~> 1.8'
 gem 'omniauth-auth0', '~> 2.0.0'
 gem 'omniauth-azure-activedirectory-v2', '~> 1.0'
-gem 'omniauth-azure-oauth2', '~> 0.0.9' # Deprecated v1 version
+gem 'omniauth-azure-oauth2', '~> 0.0.9' # See vendor/gems/omniauth-azure-oauth2/README.md
 gem 'omniauth-cas3', '~> 1.1.4', path: 'vendor/gems/omniauth-cas3' # See vendor/gems/omniauth-cas3/README.md
 gem 'omniauth-dingtalk-oauth2', '~> 1.0'
 gem 'omniauth-alicloud', '~> 1.0.1'
diff --git a/vendor/gems/omniauth-azure-oauth2/.gitlab-ci.yml b/vendor/gems/omniauth-azure-oauth2/.gitlab-ci.yml
new file mode 100644
index 0000000000000..575fec397674b
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/.gitlab-ci.yml
@@ -0,0 +1,28 @@
+workflow:
+  rules:
+    - if: $CI_MERGE_REQUEST_ID
+
+.rspec:
+  cache:
+    key: omniauth-azure-oauth2
+    paths:
+      - vendor/gems/omniauth-azure-oauth2/vendor/ruby
+  before_script:
+    - cd vendor/gems/omniauth-azure-oauth2
+    - ruby -v                                   # Print out ruby version for debugging
+    - gem install bundler --no-document         # Bundler is not installed with the image
+    - bundle config set --local path 'vendor'   # Install dependencies into ./vendor/ruby
+    - bundle config set with 'development'
+    - bundle config set --local frozen 'true'   # Disallow Gemfile.lock changes on CI
+    - bundle config                             # Show bundler configuration
+    - bundle install -j $(nproc)
+  script:
+    - bundle exec rspec
+
+rspec-2.7:
+  image: "ruby:2.7"
+  extends: .rspec
+
+rspec-3.0:
+  image: "ruby:3.0"
+  extends: .rspec
diff --git a/vendor/gems/omniauth-azure-oauth2/CHANGELOG.md b/vendor/gems/omniauth-azure-oauth2/CHANGELOG.md
new file mode 100644
index 0000000000000..ca274303b18ec
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/CHANGELOG.md
@@ -0,0 +1,31 @@
+# Version 0.0.9
+* Expand JWT dep. Thanks @ronaldsalas
+
+# Version 0.0.9
+* Added support for dynamic tenant urls. Thanks @marcus-fellinger-esc
+
+# Version 0.0.8
+* Upgrade to omniauth-oauth2 1.4.0 and fix callback url issue
+* Allow prompt parameter, thanks @hilu
+* Add tenant id to info
+* Updated base url
+
+# Version 0.0.6 
+* Use 'name' from Azure for name, and 'unique_name' for nickname per Auth Hash spec. Thanks @jayme-github   
+
+# Version 0.0.5 
+* loosen jwt requirement
+
+# Version 0.0.5 
+* loosen jwt requirement
+
+# VERSION 0.0.4
+* fix for JWT scoping, thanks @tobsher
+
+# VERSION 0.0.3
+* added common endpoint and removed mandatory requirement for tenant-id
+* upgraded jwt
+
+# VERSION 0.0.1
+
+* Initial build
\ No newline at end of file
diff --git a/vendor/gems/omniauth-azure-oauth2/Gemfile b/vendor/gems/omniauth-azure-oauth2/Gemfile
new file mode 100644
index 0000000000000..ef2f8b4147f49
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/Gemfile
@@ -0,0 +1,8 @@
+source 'https://rubygems.org'
+
+# Specify your gem's dependencies in omniauth-azure-oauth2.gemspec
+gemspec
+
+group :example do
+  gem 'sinatra'
+end
\ No newline at end of file
diff --git a/vendor/gems/omniauth-azure-oauth2/Gemfile.lock b/vendor/gems/omniauth-azure-oauth2/Gemfile.lock
new file mode 100644
index 0000000000000..0bd5d40117592
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/Gemfile.lock
@@ -0,0 +1,73 @@
+PATH
+  remote: .
+  specs:
+    omniauth-azure-oauth2 (0.0.10)
+      jwt (>= 1.0, < 3.0)
+      omniauth (~> 1.0, < 3)
+      omniauth-oauth2 (~> 1.4)
+
+GEM
+  remote: https://rubygems.org/
+  specs:
+    diff-lcs (1.5.0)
+    faraday (2.5.2)
+      faraday-net_http (>= 2.0, < 3.1)
+      ruby2_keywords (>= 0.0.4)
+    faraday-net_http (3.0.0)
+    hashie (5.0.0)
+    jwt (2.4.1)
+    multi_xml (0.6.0)
+    mustermann (2.0.2)
+      ruby2_keywords (~> 0.0.1)
+    oauth2 (2.0.6)
+      faraday (>= 0.17.3, < 3.0)
+      jwt (>= 1.0, < 3.0)
+      multi_xml (~> 0.5)
+      rack (>= 1.2, < 3)
+      rash_alt (>= 0.4, < 1)
+      version_gem (~> 1.1)
+    omniauth (1.9.1)
+      hashie (>= 3.4.6)
+      rack (>= 1.6.2, < 3)
+    omniauth-oauth2 (1.7.3)
+      oauth2 (>= 1.4, < 3)
+      omniauth (>= 1.9, < 3)
+    rack (2.2.4)
+    rack-protection (2.2.2)
+      rack
+    rake (13.0.6)
+    rash_alt (0.4.12)
+      hashie (>= 3.4)
+    rspec (3.11.0)
+      rspec-core (~> 3.11.0)
+      rspec-expectations (~> 3.11.0)
+      rspec-mocks (~> 3.11.0)
+    rspec-core (3.11.0)
+      rspec-support (~> 3.11.0)
+    rspec-expectations (3.11.0)
+      diff-lcs (>= 1.2.0, < 2.0)
+      rspec-support (~> 3.11.0)
+    rspec-mocks (3.11.1)
+      diff-lcs (>= 1.2.0, < 2.0)
+      rspec-support (~> 3.11.0)
+    rspec-support (3.11.0)
+    ruby2_keywords (0.0.5)
+    sinatra (2.2.2)
+      mustermann (~> 2.0)
+      rack (~> 2.2)
+      rack-protection (= 2.2.2)
+      tilt (~> 2.0)
+    tilt (2.0.11)
+    version_gem (1.1.0)
+
+PLATFORMS
+  ruby
+
+DEPENDENCIES
+  omniauth-azure-oauth2!
+  rake
+  rspec (>= 2.14.0)
+  sinatra
+
+BUNDLED WITH
+   2.3.20
diff --git a/vendor/gems/omniauth-azure-oauth2/LICENSE b/vendor/gems/omniauth-azure-oauth2/LICENSE
new file mode 100644
index 0000000000000..57ecd3eabb99a
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2014 Deltek
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/vendor/gems/omniauth-azure-oauth2/README.md b/vendor/gems/omniauth-azure-oauth2/README.md
new file mode 100644
index 0000000000000..a28e9ffdfd27f
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/README.md
@@ -0,0 +1,161 @@
+# OmniAuth Windows Azure Active Directory Strategy
+
+This is fork of [omniauth-azure-oauth2](https://github.com/marknadig/omniauth-azure-oauth2) 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. We may deprecate this library entirely in the future:
+   https://gitlab.com/gitlab-org/gitlab/-/issues/366212
+
+[![Build Status](https://travis-ci.org/KonaTeam/omniauth-azure-oauth2.svg?branch=master)](https://travis-ci.org/KonaTeam/omniauth-azure-oauth2)
+
+This gem provides a simple way to authenticate to Windows Azure Active Directory (WAAD) over OAuth2 using OmniAuth.
+
+One of the unique challenges of WAAD OAuth is that WAAD is multi tenant. Any given tenant can have multiple active
+directories. The CLIENT-ID, REPLY-URL and keys will be unique to the tenant/AD/application combination. This gem simply
+provides hooks for determining those unique values for each call.
+
+## Installation
+
+Add this line to your application's Gemfile:
+
+```ruby
+gem 'omniauth-azure-oauth2'
+```
+
+## Usage
+
+First, you will need to add your site as an application in WAAD.:
+[Adding, Updating, and Removing an Application](http://msdn.microsoft.com/en-us/library/azure/dn132599.aspx)
+
+Summary:
+Select your Active Directory in https://manage.windowsazure.com/<tenantid> of type 'Web Application'. Name, sign-on url,
+logo are not important.  You will need the CLIENT-ID from the application configuration and you will need to generate
+an expiring key (aka 'client secret').  REPLY URL is the oauth redirect uri which will be the omniauth callback path
+https://example.com/users/auth/azure_oauth2/callback. The APP ID UI just needs to be unique to that tenant and identify
+your site and isn't needed to configure the gem.
+Permissions need Delegated Permissions to at least have "Enable sign-on and read user's profiles".
+
+Note: Seems like the terminology is still fluid, so follow the MS guidance (buwahaha) to set this up.
+
+The TenantInfo information can be a hash or class. It must provide client_id and client_secret.
+Optionally a domain_hint and tenant_id. For a simple single-tenant app, this could be:
+
+```ruby
+use OmniAuth::Builder do
+  provider :azure_oauth2,
+    {
+      client_id: ENV['AZURE_CLIENT_ID'],
+      client_secret: ENV['AZURE_CLIENT_SECRET'],
+      tenant_id: ENV['AZURE_TENANT_ID']
+    }
+end
+```
+
+Or the alternative format for use with [devise](https://github.com/plataformatec/devise):
+
+```ruby
+config.omniauth :azure_oauth2, client_id: ENV['AZURE_CLIENT_ID'],
+      client_secret: ENV['AZURE_CLIENT_SECRET'], tenant_id: ENV['AZURE_TENANT_ID']
+```
+
+For multi-tenant apps where you don't know the tenant_id in advance, simply leave out the tenant_id to use the 
+[common endpoint](http://msdn.microsoft.com/en-us/library/azure/dn645542.aspx).
+
+```ruby
+use OmniAuth::Builder do
+  provider :azure_oauth2,
+    {
+      client_id: ENV['AZURE_CLIENT_ID'],
+      client_secret: ENV['AZURE_CLIENT_SECRET']
+    }
+end
+```
+
+For dynamic tenant assignment, pass a class that supports those same attributes and accepts the strategy as a parameter
+
+```ruby
+class YouTenantProvider
+  def initialize(strategy)
+    @strategy = strategy
+  end
+
+  def client_id
+    tenant.azure_client_id
+  end
+
+  def client_secret
+    tenant.azure_client_secret
+  end
+
+  def tenant_id
+    tenant.azure_tanant_id
+  end
+
+  def domain_hint
+    tenant.azure_domain_hint
+  end
+
+  private
+
+  def tenant
+    # whatever strategy you want to figure out the right tenant from params/session
+    @tenant ||= Customer.find(@strategy.session[:customer_id])
+  end
+end
+
+use OmniAuth::Builder do
+  provider :azure_oauth2, YourTenantProvider
+end
+```
+
+The base_azure_url can be overridden in the provider configuration for different locales; e.g. `base_azure_url: "https://login.microsoftonline.de"`
+
+
+## Auth Hash Schema
+
+The following information is provided back to you for this provider:
+
+```ruby
+{
+  uid: '12345',
+  info: {
+    name: 'some one',
+    first_name: 'some',
+    last_name: 'one',
+    email: 'someone@example.com'
+  },
+  credentials: {
+    token: 'thetoken',
+    refresh_token: 'refresh'
+  },
+  extra: { raw_info: raw_api_response }
+}
+```
+## notes
+
+When you make a request to WAAD you must specify a resource. The gem currently assumes this is the AD identified as '00000002-0000-0000-c000-000000000000'.
+This can be passed in as part of the config. It currently isn't designed to be dynamic.
+
+```ruby
+use OmniAuth::Builder do
+  provider :azure_oauth2, TenantInfo, resource: 'myresource'
+end
+```
+
+## Contributing
+
+1. Fork it
+2. Create your feature branch (`git checkout -b my-new-feature`)
+3. Make your changes, add tests, run tests (`rake`)
+4. Commit your changes and tests  (`git commit -am 'Added some feature'`)
+5. Push to the branch (`git push origin my-new-feature`)
+6. Create new Pull Request
+
+
+## Misc
+Run tests `bundle exec rake`  
+Push to rubygems `bundle exec rake release`.
+ 
diff --git a/vendor/gems/omniauth-azure-oauth2/Rakefile b/vendor/gems/omniauth-azure-oauth2/Rakefile
new file mode 100644
index 0000000000000..965431eb7c937
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/Rakefile
@@ -0,0 +1,6 @@
+require File.join('bundler', 'gem_tasks')
+require File.join('rspec', 'core', 'rake_task')
+
+RSpec::Core::RakeTask.new(:spec)
+
+task :default => :spec
\ No newline at end of file
diff --git a/vendor/gems/omniauth-azure-oauth2/examples/sinatra.rb b/vendor/gems/omniauth-azure-oauth2/examples/sinatra.rb
new file mode 100644
index 0000000000000..3db9e5fe435e1
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/examples/sinatra.rb
@@ -0,0 +1,31 @@
+$:.push File.dirname(__FILE__) + '/../lib'
+
+require 'omniauth-azure-oauth2'
+require 'sinatra'
+
+class MyAzureProvider
+  def self.client_id
+    ENV['AZURE_CLIENT_ID']
+  end
+
+  def self.client_secret
+    ENV['AZURE_CLIENT_SECRET']
+  end
+
+  def self.tenant_id
+    ENV['AZURE_TENANT_ID']
+  end
+
+end
+
+use Rack::Session::Cookie
+use OmniAuth::Strategies::Azure, MyAzureProvider
+
+get '/' do
+  "<a href='/auth/azure_oauth2'>Log in with Azure</a>"
+end
+
+get '/auth/azure_oauth2/callback' do
+  content_type 'text/plain'
+  request.env['omniauth.auth'].inspect
+end
\ No newline at end of file
diff --git a/vendor/gems/omniauth-azure-oauth2/lib/omniauth-azure-oauth2.rb b/vendor/gems/omniauth-azure-oauth2/lib/omniauth-azure-oauth2.rb
new file mode 100644
index 0000000000000..121c26842aa7f
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/lib/omniauth-azure-oauth2.rb
@@ -0,0 +1 @@
+require File.join('omniauth', 'azure_oauth2')
\ No newline at end of file
diff --git a/vendor/gems/omniauth-azure-oauth2/lib/omniauth/azure_oauth2.rb b/vendor/gems/omniauth-azure-oauth2/lib/omniauth/azure_oauth2.rb
new file mode 100644
index 0000000000000..69651ede9e7fd
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/lib/omniauth/azure_oauth2.rb
@@ -0,0 +1 @@
+require File.join('omniauth', 'strategies', 'azure_oauth2')
\ No newline at end of file
diff --git a/vendor/gems/omniauth-azure-oauth2/lib/omniauth/azure_oauth2/version.rb b/vendor/gems/omniauth-azure-oauth2/lib/omniauth/azure_oauth2/version.rb
new file mode 100644
index 0000000000000..cfaa9ddd458d8
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/lib/omniauth/azure_oauth2/version.rb
@@ -0,0 +1,5 @@
+module OmniAuth
+  module AzureOauth2
+    VERSION = "0.0.10"
+  end
+end
diff --git a/vendor/gems/omniauth-azure-oauth2/lib/omniauth/strategies/azure_oauth2.rb b/vendor/gems/omniauth-azure-oauth2/lib/omniauth/strategies/azure_oauth2.rb
new file mode 100644
index 0000000000000..f18babc0619cd
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/lib/omniauth/strategies/azure_oauth2.rb
@@ -0,0 +1,73 @@
+require 'omniauth/strategies/oauth2'
+require 'jwt'
+
+module OmniAuth
+  module Strategies
+    class AzureOauth2 < OmniAuth::Strategies::OAuth2
+      BASE_AZURE_URL = 'https://login.microsoftonline.com'
+
+      option :name, 'azure_oauth2'
+
+      option :tenant_provider, nil
+
+      # AD resource identifier
+      option :resource, '00000002-0000-0000-c000-000000000000'
+
+      # tenant_provider must return client_id, client_secret and optionally tenant_id and base_azure_url
+      args [:tenant_provider]
+
+      def client
+        if options.tenant_provider
+          provider = options.tenant_provider.new(self)
+        else
+          provider = options  # if pass has to config, get mapped right on to options
+        end
+
+        options.client_id = provider.client_id
+        options.client_secret = provider.client_secret
+        options.tenant_id =
+          provider.respond_to?(:tenant_id) ? provider.tenant_id : 'common'
+        options.base_azure_url =
+          provider.respond_to?(:base_azure_url) ? provider.base_azure_url : BASE_AZURE_URL
+
+        options.authorize_params = provider.authorize_params if provider.respond_to?(:authorize_params)
+        options.authorize_params.domain_hint = provider.domain_hint if provider.respond_to?(:domain_hint) && provider.domain_hint
+        options.authorize_params.prompt = request.params['prompt'] if request.params['prompt']
+        options.client_options.authorize_url = "#{options.base_azure_url}/#{options.tenant_id}/oauth2/authorize"
+        options.client_options.token_url = "#{options.base_azure_url}/#{options.tenant_id}/oauth2/token"
+        super
+      end
+
+      uid {
+        raw_info['sub']
+      }
+
+      info do
+        {
+          name: raw_info['name'],
+          nickname: raw_info['unique_name'],
+          first_name: raw_info['given_name'],
+          last_name: raw_info['family_name'],
+          email: raw_info['email'] || raw_info['upn'],
+          oid: raw_info['oid'],
+          tid: raw_info['tid']
+        }
+      end
+
+      def token_params
+        azure_resource = request.env['omniauth.params'] && request.env['omniauth.params']['azure_resource']
+        super.merge(resource: azure_resource || options.resource)
+      end
+
+      def callback_url
+        full_host + script_name + callback_path
+      end
+
+      def raw_info
+        # it's all here in JWT http://msdn.microsoft.com/en-us/library/azure/dn195587.aspx
+        @raw_info ||= ::JWT.decode(access_token.token, nil, false).first
+      end
+
+    end
+  end
+end
diff --git a/vendor/gems/omniauth-azure-oauth2/omniauth-azure-oauth2.gemspec b/vendor/gems/omniauth-azure-oauth2/omniauth-azure-oauth2.gemspec
new file mode 100644
index 0000000000000..6e1bc583881b5
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/omniauth-azure-oauth2.gemspec
@@ -0,0 +1,25 @@
+# -*- encoding: utf-8 -*-
+require File.expand_path(File.join('..', 'lib', 'omniauth', 'azure_oauth2', 'version'), __FILE__)
+
+Gem::Specification.new do |gem|
+  gem.authors       = ["Mark Nadig"]
+  gem.email         = ["mark@nadigs.net"]
+  gem.description   = %q{An Windows Azure Active Directory OAuth2 strategy for OmniAuth}
+  gem.summary       = %q{An Windows Azure Active Directory OAuth2 strategy for OmniAuth}
+  gem.homepage      = "https://github.com/KonaTeam/omniauth-azure-oauth2"
+
+  gem.files         =  Dir.glob("lib/**/*.*")
+  gem.test_files    =  Dir.glob("spec/**/**/*.*")
+  gem.name          = "omniauth-azure-oauth2"
+  gem.require_paths = ["lib"]
+  gem.version       = OmniAuth::AzureOauth2::VERSION
+  gem.license       = "MIT"
+
+  gem.add_runtime_dependency 'omniauth', '~> 1.0', '< 3'
+  gem.add_dependency 'jwt', ['>= 1.0', '< 3.0']
+
+  gem.add_runtime_dependency 'omniauth-oauth2', '~> 1.4'
+
+  gem.add_development_dependency 'rspec', '>= 2.14.0'
+  gem.add_development_dependency 'rake'
+end
diff --git a/vendor/gems/omniauth-azure-oauth2/spec/omniauth/strategies/azure_oauth2_spec.rb b/vendor/gems/omniauth-azure-oauth2/spec/omniauth/strategies/azure_oauth2_spec.rb
new file mode 100644
index 0000000000000..d171d88ac6c48
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/spec/omniauth/strategies/azure_oauth2_spec.rb
@@ -0,0 +1,332 @@
+require 'spec_helper'
+require 'omniauth-azure-oauth2'
+
+module OmniAuth
+  module Strategies
+    module JWT; end
+  end
+end
+
+describe OmniAuth::Strategies::AzureOauth2 do
+  let(:request) { double('Request', :params => {}, :cookies => {}, :env => {}) }
+  let(:app) {
+    lambda do
+      [200, {}, ["Hello."]]
+    end
+  }
+
+  before do
+    OmniAuth.config.test_mode = true
+  end
+
+  after do
+    OmniAuth.config.test_mode = false
+  end
+
+  describe 'static configuration' do
+    let(:options) { @options || {} }
+    subject do
+      OmniAuth::Strategies::AzureOauth2.new(app, {client_id: 'id', client_secret: 'secret', tenant_id: 'tenant'}.merge(options))
+    end
+
+    describe '#client' do
+      it 'has correct authorize url' do
+        allow(subject).to receive(:request) { request }
+        expect(subject.client.options[:authorize_url]).to eql('https://login.microsoftonline.com/tenant/oauth2/authorize')
+      end
+
+      it 'has correct authorize params' do
+        allow(subject).to receive(:request) { request }
+        subject.client
+        expect(subject.authorize_params[:domain_hint]).to be_nil
+      end
+
+      it 'has correct token url' do
+        allow(subject).to receive(:request) { request }
+        expect(subject.client.options[:token_url]).to eql('https://login.microsoftonline.com/tenant/oauth2/token')
+      end
+
+      describe "overrides" do
+        it 'should override domain_hint' do
+          @options = {domain_hint: 'hint'}
+          allow(subject).to receive(:request) { request }
+          subject.client
+          expect(subject.authorize_params[:domain_hint]).to eql('hint')
+        end
+      end
+    end
+
+  end
+
+  describe 'static configuration - german' do
+    let(:options) { @options || {} }
+    subject do
+      OmniAuth::Strategies::AzureOauth2.new(app, {client_id: 'id', client_secret: 'secret', tenant_id: 'tenant', base_azure_url: 'https://login.microsoftonline.de'}.merge(options))
+    end
+
+    describe '#client' do
+      it 'has correct authorize url' do
+        allow(subject).to receive(:request) { request }
+        expect(subject.client.options[:authorize_url]).to eql('https://login.microsoftonline.de/tenant/oauth2/authorize')
+      end
+
+      it 'has correct authorize params' do
+        allow(subject).to receive(:request) { request }
+        subject.client
+        expect(subject.authorize_params[:domain_hint]).to be_nil
+      end
+
+      it 'has correct token url' do
+        allow(subject).to receive(:request) { request }
+        expect(subject.client.options[:token_url]).to eql('https://login.microsoftonline.de/tenant/oauth2/token')
+      end
+
+      it 'has correct token params' do
+        allow(subject).to receive(:request) { request }
+        subject.client
+        expect(subject.token_params[:resource]).to eql('00000002-0000-0000-c000-000000000000')
+      end
+
+      describe "overrides" do
+        it 'should override domain_hint' do
+          @options = {domain_hint: 'hint'}
+          allow(subject).to receive(:request) { request }
+          subject.client
+          expect(subject.authorize_params[:domain_hint]).to eql('hint')
+        end
+      end
+    end
+  end
+
+  describe 'static common configuration' do
+    let(:options) { @options || {} }
+    subject do
+      OmniAuth::Strategies::AzureOauth2.new(app, {client_id: 'id', client_secret: 'secret'}.merge(options))
+    end
+
+    before do
+      allow(subject).to receive(:request) { request }
+    end
+
+    describe '#client' do
+      it 'has correct authorize url' do
+        expect(subject.client.options[:authorize_url]).to eql('https://login.microsoftonline.com/common/oauth2/authorize')
+      end
+
+      it 'has correct token url' do
+        expect(subject.client.options[:token_url]).to eql('https://login.microsoftonline.com/common/oauth2/token')
+      end
+    end
+  end
+
+  describe 'dynamic configuration' do
+    let(:provider_klass) {
+      Class.new {
+        def initialize(strategy)
+        end
+
+        def client_id
+          'id'
+        end
+
+        def client_secret
+          'secret'
+        end
+
+        def tenant_id
+          'tenant'
+        end
+
+        def authorize_params
+          { custom_option: 'value' }
+        end
+      }
+    }
+
+    subject do
+      OmniAuth::Strategies::AzureOauth2.new(app, provider_klass)
+    end
+
+    before do
+      allow(subject).to receive(:request) { request }
+    end
+
+    describe '#client' do
+      it 'has correct authorize url' do
+        expect(subject.client.options[:authorize_url]).to eql('https://login.microsoftonline.com/tenant/oauth2/authorize')
+      end
+
+      it 'has correct authorize params' do
+        subject.client
+        expect(subject.authorize_params[:domain_hint]).to be_nil
+        expect(subject.authorize_params[:custom_option]).to eql('value')
+      end
+
+      it 'has correct token url' do
+        expect(subject.client.options[:token_url]).to eql('https://login.microsoftonline.com/tenant/oauth2/token')
+      end
+
+      it 'has correct token params' do
+        subject.client
+        expect(subject.token_params[:resource]).to eql('00000002-0000-0000-c000-000000000000')
+      end
+
+      # todo: how to get this working?
+      # describe "overrides" do
+      #   it 'should override domain_hint' do
+      #     provider_klass.domain_hint = 'hint'
+      #     subject.client
+      #     expect(subject.authorize_params[:domain_hint]).to eql('hint')
+      #   end
+      # end
+    end
+
+  end
+
+  describe 'dynamic configuration - german' do
+    let(:provider_klass) {
+      Class.new {
+        def initialize(strategy)
+        end
+
+        def client_id
+          'id'
+        end
+
+        def client_secret
+          'secret'
+        end
+
+        def tenant_id
+          'tenant'
+        end
+
+        def base_azure_url
+          'https://login.microsoftonline.de'
+        end
+      }
+    }
+
+    subject do
+      OmniAuth::Strategies::AzureOauth2.new(app, provider_klass)
+    end
+
+    before do
+      allow(subject).to receive(:request) { request }
+    end
+
+    describe '#client' do
+      it 'has correct authorize url' do
+        expect(subject.client.options[:authorize_url]).to eql('https://login.microsoftonline.de/tenant/oauth2/authorize')
+      end
+
+      it 'has correct authorize params' do
+        subject.client
+        expect(subject.authorize_params[:domain_hint]).to be_nil
+      end
+
+      it 'has correct token url' do
+        expect(subject.client.options[:token_url]).to eql('https://login.microsoftonline.de/tenant/oauth2/token')
+      end
+
+      it 'has correct token params' do
+        subject.client
+        expect(subject.token_params[:resource]).to eql('00000002-0000-0000-c000-000000000000')
+      end
+
+      # todo: how to get this working?
+      # describe "overrides" do
+      #   it 'should override domain_hint' do
+      #     provider_klass.domain_hint = 'hint'
+      #     subject.client
+      #     expect(subject.authorize_params[:domain_hint]).to eql('hint')
+      #   end
+      # end
+    end
+
+  end
+
+  describe 'dynamic common configuration' do
+    let(:provider_klass) {
+      Class.new {
+        def initialize(strategy)
+        end
+
+        def client_id
+          'id'
+        end
+
+        def client_secret
+          'secret'
+        end
+      }
+    }
+
+    subject do
+      OmniAuth::Strategies::AzureOauth2.new(app, provider_klass)
+    end
+
+    before do
+      allow(subject).to receive(:request) { request }
+    end
+
+    describe '#client' do
+      it 'has correct authorize url' do
+        expect(subject.client.options[:authorize_url]).to eql('https://login.microsoftonline.com/common/oauth2/authorize')
+      end
+
+      it 'has correct token url' do
+        expect(subject.client.options[:token_url]).to eql('https://login.microsoftonline.com/common/oauth2/token')
+      end
+    end
+  end
+
+  describe "raw_info" do
+    subject do
+      OmniAuth::Strategies::AzureOauth2.new(app, {client_id: 'id', client_secret: 'secret'})
+    end
+
+    let(:token) do
+      JWT.encode({"some" => "payload"}, "secret")
+    end
+
+    let(:access_token) do
+      double(:token => token)
+    end
+
+    before do
+      allow(subject).to receive(:access_token) { access_token }
+      allow(subject).to receive(:request) { request }
+    end
+
+    it "does not clash if JWT strategy is used" do
+      expect do
+        subject.info
+      end.to_not raise_error
+    end
+  end
+
+  describe 'token_params' do
+    let(:strategy) { OmniAuth::Strategies::AzureOauth2.new(app, client_id: 'id', client_secret: 'secret') }
+    let(:request)  { double('Request', env: env) }
+    let(:env)      { {} }
+
+    subject { strategy.token_params }
+
+    before { allow(strategy).to receive(:request).and_return request }
+
+    it { is_expected.to be_a OmniAuth::Strategy::Options }
+    it 'has default resource' do
+      expect(subject.resource).to eq '00000002-0000-0000-c000-000000000000'
+    end
+
+    context 'when custom crm url' do
+      let(:crm_url) { 'https://mydomain.crm.dynamics.com/' }
+      let(:env)     { { 'omniauth.params' => { 'azure_resource' => crm_url } } }
+
+      it 'has resource from url params' do
+        expect(subject.resource).to eq crm_url
+      end
+    end
+  end
+end
diff --git a/vendor/gems/omniauth-azure-oauth2/spec/spec_helper.rb b/vendor/gems/omniauth-azure-oauth2/spec/spec_helper.rb
new file mode 100644
index 0000000000000..9d0890421a21b
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/spec/spec_helper.rb
@@ -0,0 +1,2 @@
+require File.join('bundler', 'setup')
+require 'rspec'
\ No newline at end of file
diff --git a/vendor/gems/omniauth_crowd/.gitlab-ci.yml b/vendor/gems/omniauth_crowd/.gitlab-ci.yml
index 1ad5140980349..08a5da1a3d11b 100644
--- a/vendor/gems/omniauth_crowd/.gitlab-ci.yml
+++ b/vendor/gems/omniauth_crowd/.gitlab-ci.yml
@@ -4,7 +4,7 @@ workflow:
 
 .rspec:
   cache:
-    key: omniauth-gitlab-ruby
+    key: omniauth_crowd
     paths:
       - vendor/gems/omniauth_crowd/vendor/ruby
   before_script:
-- 
GitLab