diff options
author | Sebastian Arcila Valenzuela <sarcila@gitlab.com> | 2019-08-19 16:19:19 +0300 |
---|---|---|
committer | Yorick Peterse <yorick@yorickpeterse.com> | 2019-09-30 15:22:06 +0300 |
commit | 3692e9f8a23386c627942ca2a9edd8c00af7e904 (patch) | |
tree | 0d092bdbdfc954e1a9e2b520291a7244c0cd679e /lib/gitlab/auth | |
parent | 010e3c5ed41db96f68549e01373a9aacadd995d7 (diff) |
Validate that SAML requests are originated from gitlab
If the request wasn't initiated by gitlab we shouldn't add the new
identity to the user, and instead show that we weren't able to link
the identity to the user.
This should fix: https://gitlab.com/gitlab-org/gitlab-ce/issues/56509
Diffstat (limited to 'lib/gitlab/auth')
-rw-r--r-- | lib/gitlab/auth/omniauth_identity_linker_base.rb | 5 | ||||
-rw-r--r-- | lib/gitlab/auth/saml/identity_linker.rb | 24 | ||||
-rw-r--r-- | lib/gitlab/auth/saml/origin_validator.rb | 41 |
3 files changed, 68 insertions, 2 deletions
diff --git a/lib/gitlab/auth/omniauth_identity_linker_base.rb b/lib/gitlab/auth/omniauth_identity_linker_base.rb index c620fc5d6bd..a6c247f31a7 100644 --- a/lib/gitlab/auth/omniauth_identity_linker_base.rb +++ b/lib/gitlab/auth/omniauth_identity_linker_base.rb @@ -3,12 +3,13 @@ module Gitlab module Auth class OmniauthIdentityLinkerBase - attr_reader :current_user, :oauth + attr_reader :current_user, :oauth, :session - def initialize(current_user, oauth) + def initialize(current_user, oauth, session = {}) @current_user = current_user @oauth = oauth @changed = false + @session = session end def link diff --git a/lib/gitlab/auth/saml/identity_linker.rb b/lib/gitlab/auth/saml/identity_linker.rb index ae0d6dded4e..93195c3189f 100644 --- a/lib/gitlab/auth/saml/identity_linker.rb +++ b/lib/gitlab/auth/saml/identity_linker.rb @@ -4,6 +4,30 @@ module Gitlab module Auth module Saml class IdentityLinker < OmniauthIdentityLinkerBase + extend ::Gitlab::Utils::Override + + UnverifiedRequest = Class.new(StandardError) + + override :link + def link + raise_unless_request_is_gitlab_initiated! if unlinked? + + super + end + + protected + + def raise_unless_request_is_gitlab_initiated! + raise UnverifiedRequest unless valid_gitlab_initiated_request? + end + + def valid_gitlab_initiated_request? + OriginValidator.new(session).gitlab_initiated?(saml_response) + end + + def saml_response + oauth.fetch(:extra, {}).fetch(:response_object, {}) + end end end end diff --git a/lib/gitlab/auth/saml/origin_validator.rb b/lib/gitlab/auth/saml/origin_validator.rb new file mode 100644 index 00000000000..4ecc688888f --- /dev/null +++ b/lib/gitlab/auth/saml/origin_validator.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +module Gitlab + module Auth + module Saml + class OriginValidator + AUTH_REQUEST_SESSION_KEY = "last_authn_request_id".freeze + + def initialize(session) + @session = session || {} + end + + def store_origin(authn_request) + session[AUTH_REQUEST_SESSION_KEY] = authn_request.uuid + end + + def gitlab_initiated?(saml_response) + return false if identity_provider_initiated?(saml_response) + + matches?(saml_response) + end + + private + + attr_reader :session + + def matches?(saml_response) + saml_response.in_response_to == expected_request_id + end + + def identity_provider_initiated?(saml_response) + saml_response.in_response_to.blank? + end + + def expected_request_id + session[AUTH_REQUEST_SESSION_KEY] + end + end + end + end +end |