Commit 1b61a419 authored by James Edwards-Jones's avatar James Edwards-Jones

Group SAML Omniauth Callback flow

parent 47083508
......@@ -68,7 +68,9 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
resources :ldap_group_links, only: [:index, :create, :destroy]
## EE-specific
resource :saml_providers, path: 'saml', only: [:show, :create, :update] do
post :callback, to: 'omniauth_callbacks#group_saml'
get :sso, to: 'sso#saml'
end
......
class Groups::OmniauthCallbacksController < OmniauthCallbacksController
extend ::Gitlab::Utils::Override
def group_saml
@unauthenticated_group = Group.find_by_full_path(params[:group_id])
saml_provider = @unauthenticated_group.saml_provider
identity_linker = Gitlab::Auth::GroupSaml::IdentityLinker.new(current_user, oauth, saml_provider)
omniauth_flow(Gitlab::Auth::GroupSaml, identity_linker: identity_linker)
end
private
override :redirect_identity_linked
def redirect_identity_linked
flash[:notice] = "SAML for #{@unauthenticated_group.name} was added to your connected accounts"
redirect_to after_sign_in_path_for(current_user)
end
override :redirect_identity_exists
def redirect_identity_exists
flash[:notice] = "Signed in with SAML for #{@unauthenticated_group.name}"
redirect_to after_sign_in_path_for(current_user)
end
override :after_sign_in_path_for
def after_sign_in_path_for(resource)
saml_redirect_path || super
end
override :sign_in_user_flow
def sign_in_user_flow(auth_user_class)
# User has successfully authenticated with the SAML provider for the group
# but is not signed in to the GitLab instance.
flash[:notice] = "You must be signed in to use SAML with this group"
redirect_to new_user_session_path
end
def saml_redirect_path
params['RelayState'].presence if current_user
end
end
---
title: Adds authentication flow for GitLab.com per group SAML beta
merge_request: 5575
author:
type: changed
module Gitlab
module Auth
module GroupSaml
class User
def initialize(auth_hash)
raise NotImplementedError
end
end
end
end
end
require 'spec_helper'
describe Groups::OmniauthCallbacksController do
include LoginHelpers
let(:uid) { 'my-uid' }
let(:user) { create(:user) }
let(:provider) { :group_saml }
let(:group) { create(:group, :private) }
let!(:saml_provider) { create(:saml_provider, group: group) }
before do
stub_licensed_features(group_saml: true)
end
def linked_accounts
Identity.where(user: user, extern_uid: uid, provider: provider)
end
context "when request hasn't been validated by omniauth middleware" do
it "prevents authentication" do
sign_in(user)
expect do
post provider, group_id: group
end.to raise_error(AbstractController::ActionNotFound)
end
end
context "valid credentials" do
before do
mock_auth_hash(provider, uid, user.email)
stub_omniauth_provider(provider, context: request)
end
context "when signed in" do
before do
sign_in(user)
end
context "and identity already linked" do
let(:user) { create(:omniauth_user, extern_uid: uid, provider: provider, saml_provider: saml_provider) }
it "redirects to RelayState" do
post provider, group_id: group, RelayState: '/explore'
expect(response).to redirect_to('/explore')
end
it "displays a flash message verifying group sign in" do
post provider, group_id: group
expect(flash[:notice]).to start_with "Signed in with SAML"
end
it 'uses existing linked identity' do
expect { post provider, group_id: group }.not_to change(linked_accounts, :count)
end
end
context 'oauth already linked to another account' do
before do
create(:omniauth_user, extern_uid: uid, provider: provider, saml_provider: saml_provider)
end
it 'displays warning to user' do
post provider, group_id: group
expect(flash[:notice]).to match(/has already been taken*/)
end
end
context "and identity hasn't been linked" do
it "links the identity" do
post provider, group_id: group
expect(group).to be_member(user)
end
it "redirects to RelayState" do
post provider, group_id: group, RelayState: '/explore'
expect(response).to redirect_to('/explore')
end
it "displays a flash indicating the account has been linked" do
post provider, group_id: group
expect(flash[:notice]).to match(/SAML for .* was added/)
end
end
end
context "when not signed in" do
it "redirects to sign in page" do
post provider, group_id: group
expect(response).to redirect_to(new_user_session_path)
end
it "informs users that they need to sign in to the GitLab instance first" do
post provider, group_id: group
expect(flash[:notice]).to start_with("You must be signed in")
end
end
end
end
......@@ -70,13 +70,15 @@ FactoryBot.define do
transient do
extern_uid '123456'
provider 'ldapmain'
saml_provider nil
end
after(:create) do |user, evaluator|
user.identities << create(
:identity,
provider: evaluator.provider,
extern_uid: evaluator.extern_uid
extern_uid: evaluator.extern_uid,
saml_provider: evaluator.saml_provider
)
end
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment