Use MM as oauth2 provider for GitLab


#1

I am trying to use MM as an oauth2 provider for gitlab to authenticate against.

Here is my setup so far:

gitlab_rails['omniauth_providers'] = [
   {
     "name" => "oauth2_generic",
     "app_id" => "xxx",
     "app_secret" => "xxx",
     "args" => {
       client_options: {
          'site' => 'https://meeting.swsz.org',
          'user_info_url' => '/api/v4/users/me'
       },
       user_response_structure: {
        root_path: [],
        attributes: { nickname: 'username' }
       },
       name: 'Mattermost',
       strategy_class: "OmniAuth::Strategies::OAuth2Generic"
}   }

When I try to login through Mattermost I see the following message on GitLab:
Could not authenticate you from Mattermost because “”.

The docker logs of the MM web container say the following;
172.18.0.9 - - [10/Mar/2018:13:48:00 +0100] “GET /oauth/authorize?client_id=xxx&redirect_uri=https%3A%2F%2Fgit.swsz.org%2Fusers%2Fauth%2FMattermost%2Fcallback&response_type=code&state=466e6474e18304b3be133be2a3b1a26289c07e0f8890df30 HTTP/1.1” 302 191 “https://git.swsz.org/” “Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36” “46.95.76.208”
172.18.0.9 - - [10/Mar/2018:13:48:00 +0100] “POST /oauth/token HTTP/1.1” 405 0 “-” “Faraday v0.12.2” “172.18.0.1”

Any help with this would be highly appreciated.

I only found topics on here who tried to do it the other way arround (having gitlab as the oauth2 provider)


#2

It looks like you’re off to a great start! I had hoped to replicate your setup and assist with testing, but it looks like I have to custom compile Gitlab to even get the https://gitlab.com/satorix/omniauth-oauth2-generic gem installed. If you have any suggestions on ways to bootstrap that process I’d be happy to help further!

At this point, I’d be curious to see if the call to /api/v4/users/me gets invoked without error. It might also be useful to intercept the network requests using your browser’s developer console and examine the payload for further clues.


#3

I’ve set it up in a docker environment. Using: https://hub.docker.com/r/gitlab/gitlab-ce/

I’ll try the browser tools this evening (GMT). From what I see in the logs it failed when trying to retrieve the oauth token (405 error) … so it doesn’t even get thus far as to get the user info via API.


#4

What exactly are we looking for? I really would love to get this off the ground and add other applications to this setup. :slight_smile:


#5

In that console tab, can you consecutively click on the top four network requests and post the Form Data from the bottom of the Headers tab, and the entire contents of the Response tab? (Shouldn’t be anything to redact from that text, but may want to just peruse before posting publicly.)


#6

Here are the requested screens: (can only post one image per post)

I’ve now deauthorized the app, just that the oauth tokens posted here can’t be reused.
Kind of strange that the response tab is always empty.


#7


#8


#9


#10


#11


#12


#13


#14

Good news is that I’ve been able to reproduce the problem you’re observing above. Bad news is that it’s still unclear why this doesn’t work. To document, here’s my changes to /etc/gitlab/gitlab.rb in the GitLab Ominbus image based on your changes above:

gitlab_rails['omniauth_enabled'] = true
gitlab_rails['omniauth_allow_single_sign_on'] = ['oauth2_generic']
gitlab_rails['omniauth_block_auto_created_users'] = false
gitlab_rails['omniauth_auto_link_saml_user'] = true

gitlab_rails['omniauth_providers'] = [
  {
    'name' => 'oauth2_generic',
    'app_id' => '<app_id>',
    'app_secret' => '<app_secret>',
    'args' => {
      client_options: {
        'site' => 'http://<mattermost_host>:8065/', # including port if necessary
        'user_info_url' => '/api/v4/users/me'
      },
      user_response_structure: {
        root_path: [], # i.e. if attributes are returned in JsonAPI format (in a 'user' node nested under a 'data' node)
        attributes: { nickname: 'username' } # if the nickname attribute of a user is called 'username'
      },
      # optionally, you can add the following two lines to "white label" the display name
      # of this strategy (appears in urls and Gitlab login buttons)
      # If you do this, you must also replace oauth2_generic, everywhere it appears above, with the new name.
      name: 'Mattermost', # display name for this strategy
      strategy_class: "OmniAuth::Strategies::OAuth2Generic" # Devise-specific config option Gitlab uses to find renamed strategy
    }
  }
]

and the configuration of the OAuth2 application in Mattermost:

Is Trusted: No
Client ID: <client_id>
Client Secret: ***************
Callback URLs: http://<gitlab_host>/users/auth/Mattermost/callback
Created by test on Wednesday, March 21, 2018

Here are the Gitlab logs associated with an attempt to authorize:

==> /var/log/gitlab/gitlab-rails/production.log <==
Started POST "/users/auth/Mattermost" for 172.17.0.1 at 2018-03-21 12:44:57 +0000
Processing by Gitlab::RequestForgeryProtection::Controller#index as HTML
  Parameters: {"authenticity_token"=>"[FILTERED]"}
Completed 200 OK in 1ms (ActiveRecord: 0.0ms)

==> /var/log/gitlab/gitlab-rails/production_json.log <==
{"method":"POST","path":"/users/auth/Mattermost","format":"html","controller":"Gitlab::RequestForgeryProtection::Controller","action":"index","status":200,"duration":2.31,"view":0.0,"db":0.0,"time":"2018-03-21T12:44:57.739Z","params":{"_method":"post","authenticity_token":"[FILTERED]"},"remote_ip":null,"user_id":null,"username":null}

==> /var/log/gitlab/gitlab-rails/production.log <==
Started GET "/users/auth/Mattermost/callback?code=[FILTERED]&state=3e78b546e6874487c18207845bc68158e6fbcff86085b49f" for 172.17.0.1 at 2018-03-21 12:44:57 +0000
Processing by OmniauthCallbacksController#failure as HTML
  Parameters: {"code"=>"[FILTERED]", "state"=>"3e78b546e6874487c18207845bc68158e6fbcff86085b49f"}
Redirected to http://localhost:9090/users/sign_in
Completed 302 Found in 5ms (ActiveRecord: 0.0ms)

==> /var/log/gitlab/unicorn/unicorn_stdout.log <==
I, [2018-03-21T12:47:29.527107 #841]  INFO -- omniauth: (Mattermost) Callback phase initiated.
E, [2018-03-21T12:47:29.532019 #841] ERROR -- omniauth: (Mattermost) Authentication failure! invalid_credentials: OAuth2::Error,

==> /var/log/gitlab/gitlab-rails/production_json.log <==
{"method":"GET","path":"/users/auth/Mattermost/callback","format":"html","controller":"OmniauthCallbacksController","action":"failure","status":302,"duration":6.67,"view":0.0,"db":0.0,"location":"http://localhost:9090/users/sign_in","time":"2018-03-21T12:44:57.769Z","params":{"code":"[FILTERED]","state":"3e78b546e6874487c18207845bc68158e6fbcff86085b49f"},"remote_ip":"172.17.0.1","user_id":null,"username":null}

I do note that Gitlab never reaches out to Mattermost on the user_info_url but decides that the authentication failed from the sole interaction against /oauth/authorize. Nothing in the response from Mattermost suggests the authentication failed, so I’m guessing GitLab is expecting something that Mattermost isn’t sending.

I might suggest reaching out to GitLab at this point for assistance, though there’s a few more things I’d like to try myself as well.


#15

Have you been able to solve the problem or gather more information? I’m experiencing the same problem.


#16

Nothing new from my side. Problem is still the same. I am cosidering GitLab as main auth provider as it is better for connecting aditional apps like Jenkins with it. (Plugins for group lookup and stuff).

The non-profit that I am working for is probably going to switch to google apps for non-profits and I’ll use these accounts on the gitlab oauth backend. So for my Mattermost users the flow will be:

MM -> GitLab -> Google G-Suite

Hoping that it will work as I plan it. :slight_smile:


#17

Finally got it to work. Here is my solution:

### OmniAuth Settings
###! Docs: https://docs.gitlab.com/ce/integration/omniauth.html
gitlab_rails['omniauth_enabled'] = true
gitlab_rails['omniauth_allow_single_sign_on'] = ['oauth2_generic']
# gitlab_rails['omniauth_sync_email_from_provider'] = 'saml'
# gitlab_rails['omniauth_sync_profile_from_provider'] = ['saml']
# gitlab_rails['omniauth_sync_profile_attributes'] = ['email']
# gitlab_rails['omniauth_auto_sign_in_with_provider'] = 'saml'
gitlab_rails['omniauth_block_auto_created_users'] = false
gitlab_rails['omniauth_auto_link_ldap_user'] = false
# gitlab_rails['omniauth_auto_link_saml_user'] = false
# gitlab_rails['omniauth_external_providers'] = ['twitter', 'google_oauth2']
gitlab_rails['omniauth_providers'] = [
   {
     "name" => "oauth2_generic",
     "app_id" => "XXX",
     "app_secret" => "XXX",
     "args" => {
       client_options: {
          'site' => 'https://meeting.swsz.org',
          'authorize_url' => '/oauth/authorize',
          'token_url' => '/oauth/access_token',
          'user_info_url' => '/api/v4/users/me'
       },
       user_response_structure: {
        root_path: [],
        attributes: { name: 'first_name'+'last_name',
                      first_name: 'first_name',
                      last_name: 'last_name',
                      nickname: 'username',
                      email: 'email'
                       }
       },
       name: 'oauth2_generic',
       strategy_class: "OmniAuth::Strategies::OAuth2Generic"
}   }
 ]

I didn’t get it to work with name: ‘Mattermost’ as the URL mapping doesn’t seem to work, I always get a 404 at the callback url.

Also note that it doesn’t work if the mattermost username exists as a local user already. It doesn’t seem to sync.

Another problem that needs to be addressed is the profile editing in GitLab… the name and email should be readonly and synced from the oauth provider.

But all in all not to bad for a first start. :slight_smile: