Zammad: Oauth2 Question

Created on 7 Mar 2017  ·  22Comments  ·  Source: zammad/zammad

Hi!

I'm implementing an Oauth2 service and want to login to Zammad using it.

Everything works fine but at the step where Zammad gets the Access Token and should login the user i get the following error in the logs:

ERROR -- : Attribute 'login' required!
E, [2017-03-07T10:02:19.751951 #4144] ERROR -- : ["/opt/zammad/app/models/user.rb:833:in `check_login'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/callbacks.rb:432:in `block in make_lambda'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/callbacks.rb:164:in `block in halting'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/callbacks.rb:504:in `block in call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/callbacks.rb:504:in `each'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/callbacks.rb:504:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/callbacks.rb:92:in `__run_callbacks__'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/callbacks.rb:778:in `_run_validation_callbacks'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activemodel-4.2.7.1/lib/active_model/validations/callbacks.rb:113:in `run_validations!'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activemodel-4.2.7.1/lib/active_model/validations.rb:338:in `valid?'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/validations.rb:58:in `valid?'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/validations.rb:83:in `perform_validations'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/validations.rb:37:in `save'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/attribute_methods/dirty.rb:21:in `save'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/transactions.rb:286:in `block (2 levels) in save'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/transactions.rb:351:in `block in with_transaction_returning_status'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `block in transaction'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/connection_adapters/abstract/transaction.rb:184:in `within_new_transaction'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `transaction'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/transactions.rb:220:in `transaction'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/transactions.rb:348:in `with_transaction_returning_status'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/transactions.rb:286:in `block in save'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/transactions.rb:301:in `rollback_active_record_state!'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/transactions.rb:285:in `save'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/persistence.rb:34:in `create'", "/opt/zammad/app/models/user.rb:291:in `create_from_hash!'", "/opt/zammad/app/models/authorization.rb:57:in `create_from_hash'", "/opt/zammad/app/controllers/sessions_controller.rb:145:in `create_omniauth'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_controller/metal/implicit_render.rb:4:in `send_action'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/abstract_controller/base.rb:198:in `process_action'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_controller/metal/rendering.rb:10:in `process_action'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/abstract_controller/callbacks.rb:20:in `block in process_action'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/callbacks.rb:117:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/callbacks.rb:555:in `block (2 levels) in compile'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/callbacks.rb:505:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/callbacks.rb:92:in `__run_callbacks__'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/callbacks.rb:778:in `_run_process_action_callbacks'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/callbacks.rb:81:in `run_callbacks'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/abstract_controller/callbacks.rb:19:in `process_action'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_controller/metal/rescue.rb:29:in `process_action'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_controller/metal/instrumentation.rb:32:in `block in process_action'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/notifications.rb:164:in `block in instrument'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/notifications/instrumenter.rb:20:in `instrument'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/notifications.rb:164:in `instrument'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_controller/metal/instrumentation.rb:30:in `process_action'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_controller/metal/params_wrapper.rb:250:in `process_action'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/railties/controller_runtime.rb:18:in `process_action'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/abstract_controller/base.rb:137:in `process'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionview-4.2.7.1/lib/action_view/rendering.rb:30:in `process'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_controller/metal.rb:196:in `dispatch'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_controller/metal/rack_delegation.rb:13:in `dispatch'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_controller/metal.rb:237:in `block in action'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_dispatch/routing/route_set.rb:74:in `dispatch'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_dispatch/routing/route_set.rb:43:in `serve'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_dispatch/journey/router.rb:43:in `block in serve'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_dispatch/journey/router.rb:30:in `each'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_dispatch/journey/router.rb:30:in `serve'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_dispatch/routing/route_set.rb:817:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/omniauth-1.3.1/lib/omniauth/strategy.rb:408:in `call_app!'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/omniauth-1.3.1/lib/omniauth/strategy.rb:362:in `callback_phase'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/omniauth-oauth2-1.4.0/lib/omniauth/strategies/oauth2.rb:75:in `callback_phase'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/omniauth-1.3.1/lib/omniauth/strategy.rb:227:in `callback_call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/omniauth-1.3.1/lib/omniauth/strategy.rb:184:in `call!'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/omniauth-1.3.1/lib/omniauth/strategy.rb:164:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/omniauth-1.3.1/lib/omniauth/strategy.rb:186:in `call!'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/omniauth-1.3.1/lib/omniauth/strategy.rb:164:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/omniauth-1.3.1/lib/omniauth/strategy.rb:186:in `call!'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/omniauth-1.3.1/lib/omniauth/strategy.rb:164:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/omniauth-1.3.1/lib/omniauth/strategy.rb:186:in `call!'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/omniauth-1.3.1/lib/omniauth/strategy.rb:164:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/omniauth-1.3.1/lib/omniauth/strategy.rb:186:in `call!'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/omniauth-1.3.1/lib/omniauth/strategy.rb:164:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/omniauth-1.3.1/lib/omniauth/strategy.rb:186:in `call!'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/omniauth-1.3.1/lib/omniauth/strategy.rb:164:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/omniauth-1.3.1/lib/omniauth/strategy.rb:186:in `call!'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/omniauth-1.3.1/lib/omniauth/strategy.rb:164:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/omniauth-1.3.1/lib/omniauth/builder.rb:63:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/rack-1.6.4/lib/rack/etag.rb:24:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/rack-1.6.4/lib/rack/conditionalget.rb:25:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/rack-1.6.4/lib/rack/head.rb:13:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_dispatch/middleware/params_parser.rb:27:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_dispatch/middleware/flash.rb:260:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/rack-1.6.4/lib/rack/session/abstract/id.rb:225:in `context'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/rack-1.6.4/lib/rack/session/abstract/id.rb:220:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_dispatch/middleware/cookies.rb:560:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/query_cache.rb:36:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:653:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_dispatch/middleware/callbacks.rb:29:in `block in call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/callbacks.rb:88:in `__run_callbacks__'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/callbacks.rb:778:in `_run_call_callbacks'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/callbacks.rb:81:in `run_callbacks'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_dispatch/middleware/callbacks.rb:27:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_dispatch/middleware/remote_ip.rb:78:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_dispatch/middleware/debug_exceptions.rb:17:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/railties-4.2.7.1/lib/rails/rack/logger.rb:38:in `call_app'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/railties-4.2.7.1/lib/rails/rack/logger.rb:20:in `block in call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/tagged_logging.rb:68:in `block in tagged'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/tagged_logging.rb:26:in `tagged'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/tagged_logging.rb:68:in `tagged'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/railties-4.2.7.1/lib/rails/rack/logger.rb:20:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_dispatch/middleware/request_id.rb:21:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/rack-1.6.4/lib/rack/methodoverride.rb:22:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/rack-1.6.4/lib/rack/runtime.rb:18:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/cache/strategy/local_cache_middleware.rb:28:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.7.1/lib/action_dispatch/middleware/static.rb:120:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/rack-1.6.4/lib/rack/sendfile.rb:113:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/railties-4.2.7.1/lib/rails/engine.rb:518:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/railties-4.2.7.1/lib/rails/application.rb:165:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/rack-1.6.4/lib/rack/content_length.rb:15:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/puma-3.6.0/lib/puma/configuration.rb:225:in `call'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/puma-3.6.0/lib/puma/server.rb:578:in `handle_request'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/puma-3.6.0/lib/puma/server.rb:415:in `process_client'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/puma-3.6.0/lib/puma/server.rb:275:in `block in run'", "/opt/zammad/vendor/bundle/ruby/2.3.0/gems/puma-3.6.0/lib/puma/thread_pool.rb:116:in `block in spawn_thread'"]

I do not find any documentation on how zammad would fetch user credentials via Oauth2?

In any Oauth2 Documentation the response to the token-request should only contain the access_token and an expires values.

Could you please give me a hint?

Best regards from austria!

  • David
question

Most helpful comment

Hi guys!

I solve my problem with wso2is changing the def raw_info as follow:

def raw_info
  @raw_info ||= begin
    uri = URI.parse('https://mywso2is/oauth2/userinfo?schema=openid')
    request = Net::HTTP::Get.new(uri)
    request['Authorization'] = 'Bearer ' + access_token.token

    response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
      http.request(request)
    end
    JSON.parse(response.body)
  end
end

All 22 comments

Zammad doesn't support the Access Token login method. We need the credentials of the user in the response payload.

Taken from a ticket (#102057):
Other providers work as followed:

Zammad is configured for an auth provider (e.g. Github). After that the icon is shown in the login screen. After the klick on the icon/link the user gets redirected to an omniauth URL. After that everything till receiving the credentials is out of the Zammad scope and handled by omniauth.
Omniauth builds an URL and redirects the user with the required OAuth2 parameters to the matching login page of the provider. There the authentication takes place.
One of the omniauth parameters is the callback URL. After the the authentication is done the user gets redirected to this URL by the provider. The callback URL is configured in our route list:

https://github.com/zammad/zammad/blob/c71b0d36d4fcefdaae4e39f1859094727a3ca74c/config/routes/auth.rb#L5

The route tunnels the request to the sessions controller, which tries to determine the user or create it if it couldn't be found:

https://github.com/zammad/zammad/blob/c71b0d36d4fcefdaae4e39f1859094727a3ca74c/app/controllers/sessions_controller.rb#L144

Thats done here:

https://github.com/zammad/zammad/blob/c71b0d36d4fcefdaae4e39f1859094727a3ca74c/app/models/authorization.rb#L54

These parameters are needed by Zammad and have to be submitted by the provider. The token based authentication is not supported.

Hi!

I don't understand your response.

I just tried:
! Settings / Security -> Generic Oauth2 set up. !

  1. On the Login Page i click on OAuth2
  2. My Browser redirects me to the authorize url as set in the config with the params client_id, client_secret, redirect_uri, response_type and state.
  3. Then i accept the Login using Oauth and my service-provider redirects me to the given redirect_uri with the params state and code. (This is the authorization code, right?)
  4. Zammad makes a request in background to the token url from config with params client_id, client_secret, code, grant_type, redirect_uri. In this case grant_type = authorization_code so i return the access_token.

This workflow is exactly how it should be depending on documentation.

I do not understand, where we should set the userdata.

  • David

with the params state and code. (This is the authorization code, right?)

That's the point: Zammad expects a Hash structure containing the user data not an auth code. The Hash needs the following structure:
https://github.com/zammad/zammad/blob/c71b0d36d4fcefdaae4e39f1859094727a3ca74c/app/models/authorization.rb#L79

Your point 4. didn't take place. Zammad does not perform any requests after an OAuth login was successful.

Your point 4. didn't take place. Zammad does not perform any requests after an OAuth login was successful.

But point 4 is the request to the TOKEN_URL which happens in my logs?

  • 192.168.4.142 - - [07/Mar/2017:14:33:23 +0100] "GET /oauth/authorize?client_id=0815&redirect_uri=http%3A%2F%2Fdomain.tld%2Fauth%2Foauth2%2Fcallback&response_type=code&state=97e53de9acb6f6a1b1af41a75dd65e8893e853c53bb64d1b HTTP/1.1" 302 840 "http://domain.tld/" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"
  • 192.168.4.64 - - [07/Mar/2017:14:33:23 +0100] "POST /oauth/token HTTP/1.1" 200 216 "-" "Faraday v0.9.2"

I speak about the user login using oauth2.

response_type=code is not supported by Zammad

But this response_type=code is set by Zammad when i press the "Oauth2" button on the login page?
That's not set by my Oauth provider??

🤔 I'll have a look

Hi @ThePatzen - sorry for the delay. I spend some time with the OAuth2 provider part and found some folks having a very similar issue like you: #775

Do you also use the Django OAuth2 toolkit? Does the workaround provided by @firlevapz here work for your too?

Looking forward to hear from you.

Hi @thorsteneckel - no problem! No i don't use this toolkit. I implemented OAuth2 native.

Do i understand right. This workaround changes the zammad code to do a seperate request to /api/users/me to get the credentials of the user?

Oh I see. Yes, that's exactly what it does. I think that could be a general way for you to go if I get your scenario right. As stated in the other issue we will try to get this into Zammad. Would it cover your case if you could configure the /api/users/me URL for your provider?

PS: Nice - implementing it native 🤓

From my point of view OAuth2 Module needs a additional config param which is the "User lookup Url".

Also /vendor/lib/oauth2_database.rb should be change like this:

class Oauth2Database < OmniAuth::Strategies::OAuth2
  option :name, 'oauth2'

  def initialize(app, *args, &block)
    # database lookup
    config  = Setting.get('auth_oauth2_credentials') || {}
    args[0] = config['app_id']
    args[1] = config['app_secret']
    args[2][:client_options] = args[2][:client_options].merge(config.symbolize_keys)
    super
  end

  def callback_url
    full_host + script_name + callback_path
  end

  uid { raw_info['id'] }

  info do
    {
      email: raw_info['email'],
      username: raw_info['username'],
      login: raw_info['email'],
      first_name: raw_info['first_name'],
      last_name: raw_info['last_name'],
    }
  end

  extra do
    {
      'raw_info' => raw_info
    }
  end

  def raw_info
    @raw_info ||= access_token.get(config['user_info_url']).parsed
  end

end

Does the code above work in your case? Have you tested it? Would be great to solve your issue and #775 with one auth strategy.

Hi!

I'm currently out of office. I'll test this tomorrow and give you response as soon as i've done it!

Greeds from austria!

No worries - we are here 🤓 Greetings to Austria from Berlin 🚀

Hi! This way the login works!

!BUT!: A new user account is created each time! It's not possible to login to an allready existing!

  • edit *: I just forgot the user id field. now all works!

Recommendation:
I would also recommend to enhance the configuration with several fields:

  • URL for the User Lookup
  • Fieldname in the lookup-response of the email
  • Fieldname in the lookup-response of the login
  • Fieldname in the lookup-response of the firstname
  • Fieldname in the lookup-response of the lastname
  • Fieldname in the lookup-response of the user id added

I would recommend the following code:
`class Oauth2Database < OmniAuth::Strategies::OAuth2
option :name, 'oauth2'

def initialize(app, *args, &block)
# database lookup
config = Setting.get('auth_oauth2_credentials') || {}
args[0] = config['app_id']
args[1] = config['app_secret']
args[2][:client_options] = args[2][:client_options].merge(config.symbolize_keys)
super
end

def callback_url
full_host + script_name + callback_path
end

uid { raw_info[config['user_info_id']] }

info do
{
email: raw_info[config['user_info_email']],
username: raw_info[config['user_info_username']],
login: raw_info[config['user_info_login']],
first_name: raw_info[config['user_info_firstname']],
last_name: raw_info[config['user_info_lastname']],
}
end

extra do
{
'raw_info' => raw_info
}
end

def raw_info
@raw_info ||= access_token.get(config['user_info_url']).parsed
end

end`

You would, need the following configuration fields:

  • user_info_id
  • user_info_email
  • user_info_login
  • user_info_firstname
  • user_info_lastname
  • Regards from AT!
    David

Nice! Thanks for the feedback. I had another look at the Omniauth code and ours. Can you please check if you have entries in your authorizations database table? You can check this either via direct access or the Rails console Authorization.all.

If not then your uid parameter is probably missing.

We discussed the topic and decided to extend and refactor the whole OAuth2 thing. This will include the implement of the configurations you recommended. However this might take some time since our list has some more urgent tasks. I'll create a separat issue for this and refer to this issue here then.

Hi!

Yes now there is an entry in the authorizations table!
For me now alle works! (Using my changed code)

:-) Greeds from Innsbruck,Austria :-)

NICE! Would you mind posting your solution here so others might benefit from it / we can ensure that our refactoring is able to replace your customizations?

Greetings to Innsbruck from Berlin 🤙

Hi! Sorry for my late response! Here's my solution:

class Oauth2Database < OmniAuth::Strategies::OAuth2
  option :name, 'oauth2'

  def initialize(app, *args, &block)
    # database lookup
    config = Setting.get('auth_oauth2_credentials') || {}
    args[0] = config['app_id']
    args[1] = config['app_secret']
    args[2][:client_options] = args[2][:client_options].merge(config.symbolize_keys)
    super
  end

  def callback_url
    full_host + script_name + callback_path
  end

  uid { raw_info['id'] }

  info do
    {
      email:      raw_info['email'],
      username:   raw_info['username'],
      login:      raw_info['login'],
      first_name: raw_info['firstname'],
      last_name:  raw_info['lastname'],
    }
  end

  extra do
    {
    'raw_info' => raw_info
    }
  end

  def raw_info
    @raw_info ||= access_token.get('/api/me').parsed
  end

end

This has to be set as content of file /vendor/lib/oauth2_database.rb!

Your application has to give a Response as url /api/me with alle the fields used in "raw_info".

If there are any questions from anybody feel free to ask :-)

Niiiiice! Thanks @ThePatzen! I reformatted the code a bit. Closing for now. Have fun with your shiny new Zammad OAuth2 authentication 🤓

Hi guys, I have the same problem using wso2is as identity server. I don't understand "/api/me" path doesn't respond on zammad, the same for "/api/users/me" like write in issues 775. On zammad renspond only "/api/v1/users/me" but only if i logged in... but in this section i Think I'm not logged in again... Somebody can help me please?

Hi guys!

I solve my problem with wso2is changing the def raw_info as follow:

def raw_info
  @raw_info ||= begin
    uri = URI.parse('https://mywso2is/oauth2/userinfo?schema=openid')
    request = Net::HTTP::Get.new(uri)
    request['Authorization'] = 'Bearer ' + access_token.token

    response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
      http.request(request)
    end
    JSON.parse(response.body)
  end
end
Was this page helpful?
0 / 5 - 0 ratings