robrotheram / taiga-contrib-openid-auth

Taiga plugin for openid authentication
45 stars 25 forks source link

How to setup using KeyCloak #5

Closed LecrisUT closed 3 years ago

LecrisUT commented 3 years ago

I have tried using the default settings in KeyCloak and Taiga to setup this method, however I keep getting errors when it redirects back to taiga:

ConnectionError at /api/v1/auth
HTTPSConnectionPool(host='keycloak', port=443): Max retries exceeded with url: /auth/realms/[redacted]/protocol/openid-connect/token (Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x7f3b673f1a58>: Failed to establish a new connection: [Errno -2] Name or service not known',))

Please advise on how you've set it up on your end.

robrotheram commented 3 years ago

Looking at that error I looks like the plugin needs to be configured use the keycloak server. I have all the settings in the readme.

First create a new OpenID client

For the backend server you will need to add the following to the local.py

INSTALLED_APPS += ["taiga_contrib_openid_auth"]
OPENID_USER_URL = "https://{url-to-keycloak}/auth/realms/{realm}/protocol/openid-connect/userinfo"
OPENID_TOKEN_URL = "https://{url-to-keycloak}/auth/realms/{realm}/protocol/openid-connect/token"
OPENID_CLIENT_ID = "{client id}"
OPENID_CLIENT_SECRET = "{client secret}"

Replace the url-to-keycloak with your own keycloak server and client and secret from keycloak The frontend

{
  "openidAuth" : "https://{url-to-keycloak}/auth/realms/{realm}/protocol/openid-connect/auth",
  "openidName" : "{name-for-login-button}",
  "openidClientId": "{client_id}",
  "contribPlugins": [
      "/plugins/openid-auth/openid-auth.json"
  ]
}

I hope that helps.

LecrisUT commented 3 years ago

Unfortunately I have followed all of those steps originally, giving me the current issue. Are there any particular settings for the mapper tab? Something that might be relevant, when compiling the front part, when I call gulp, I get the following error:

[10:27:28] Error: watching partials/*.jade,coffee/*.coffee,images/**/*: watch task has to be a function (optionally generated by using gulp.parallel or gulp.series)
    at Gulp.watch (/opt/taiga-plugins/openid-auth/front/node_modules/gulp/index.js:28:11)
    at /opt/taiga-plugins/openid-auth/front/gulpfile.js:47:10
    at taskWrapper (/opt/taiga-plugins/openid-auth/front/node_modules/undertaker/lib/set-task.js:13:15)
    at bound (domain.js:402:14)
    at runBound (domain.js:415:12)
    at asyncRunner (/opt/taiga-plugins/openid-auth/front/node_modules/async-done/index.js:55:18)
    at process._tickCallback (internal/process/next_tick.js:61:11)
LecrisUT commented 3 years ago

I figured out how to extract the traceback if it helps:

Environment:

Request Method: POST
Request URL: https://taiga/api/v1/auth

Django Version: 2.2.16
Python Version: 3.6.8
Installed Applications:
['django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.admin',
 'django.contrib.staticfiles',
 'django.contrib.sitemaps',
 'django.contrib.postgres',
 'taiga.base',
 'taiga.base.api',
 'taiga.locale',
 'taiga.events',
 'taiga.front',
 'taiga.users',
 'taiga.userstorage',
 'taiga.external_apps',
 'taiga.projects',
 'taiga.projects.references',
 'taiga.projects.custom_attributes',
 'taiga.projects.history',
 'taiga.projects.notifications',
 'taiga.projects.attachments',
 'taiga.projects.likes',
 'taiga.projects.votes',
 'taiga.projects.milestones',
 'taiga.projects.epics',
 'taiga.projects.userstories',
 'taiga.projects.tasks',
 'taiga.projects.issues',
 'taiga.projects.wiki',
 'taiga.projects.contact',
 'taiga.projects.settings',
 'taiga.searches',
 'taiga.timeline',
 'taiga.mdrender',
 'taiga.export_import',
 'taiga.feedback',
 'taiga.stats',
 'taiga.hooks.github',
 'taiga.hooks.gitlab',
 'taiga.hooks.bitbucket',
 'taiga.hooks.gogs',
 'taiga.webhooks',
 'taiga.importers',
 'djmail',
 'django_jinja',
 'django_jinja.contrib._humanize',
 'sr',
 'easy_thumbnails',
 'raven.contrib.django.raven_compat',
 'taiga_contrib_openid_auth']
Installed Middleware:
['raven.contrib.django.middleware.DjangoRestFrameworkCompatMiddleware',
 'raven.contrib.django.middleware.SentryMiddleware',
 'taiga.base.middleware.cors.CorsMiddleware',
 'taiga.events.middleware.SessionIDMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.locale.LocaleMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware']

Traceback:

File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py" in urlopen
  600.                                                   chunked=chunked)

File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py" in _make_request
  343.             self._validate_conn(conn)

File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py" in _validate_conn
  839.             conn.connect()

File "/usr/local/lib/python3.6/site-packages/urllib3/connection.py" in connect
  344.             ssl_context=context)

File "/usr/local/lib/python3.6/site-packages/urllib3/util/ssl_.py" in ssl_wrap_socket
  345.             return context.wrap_socket(sock, server_hostname=server_hostname)

File "/usr/lib64/python3.6/ssl.py" in wrap_socket
  365.                          _context=self, _session=session)

File "/usr/lib64/python3.6/ssl.py" in __init__
  776.                     self.do_handshake()

File "/usr/lib64/python3.6/ssl.py" in do_handshake
  1036.             self._sslobj.do_handshake()

File "/usr/lib64/python3.6/ssl.py" in do_handshake
  648.         self._sslobj.do_handshake()

During handling of the above exception ([SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:897)), another exception occurred:

File "/usr/local/lib/python3.6/site-packages/requests/adapters.py" in send
  449.                     timeout=timeout

File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py" in urlopen
  638.                                         _stacktrace=sys.exc_info()[2])

File "/usr/local/lib/python3.6/site-packages/urllib3/util/retry.py" in increment
  399.             raise MaxRetryError(_pool, url, error or ResponseError(cause))

During handling of the above exception (HTTPSConnectionPool(host='keycloak', port=443): Max retries exceeded with url: /auth/realms/[redacted]/protocol/openid-connect/token (Caused by SSLError(SSLError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:897)'),))), another exception occurred:

File "/usr/local/lib64/python3.6/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)

File "/usr/local/lib64/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  115.                 response = self.process_exception_by_middleware(e, request)

File "/usr/local/lib64/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/opt/taiga-back/taiga/base/api/viewsets.py" in view
  106.             return self.dispatch(request, *args, **kwargs)

File "/usr/local/lib64/python3.6/site-packages/django/views/decorators/csrf.py" in wrapped_view
  54.         return view_func(*args, **kwargs)

File "/opt/taiga-back/taiga/base/api/views.py" in dispatch
  460.             response = self.handle_exception(exc)

File "/opt/taiga-back/taiga/base/api/views.py" in dispatch
  458.             response = handler(request, *args, **kwargs)

File "/opt/taiga-back/taiga/auth/api.py" in create
  113.             data = auth_plugins[login_type]['login_func'](request)

File "/opt/taiga-plugins/openid-auth/back/taiga_contrib_openid_auth/services.py" in openid_login_func
  84.     user_info = connector.me(code, accessToken, redirect_uri)

File "/opt/taiga-plugins/openid-auth/back/taiga_contrib_openid_auth/connector.py" in me
  139.     auth_info = login(access_code, token, redirect_uri)

File "/opt/taiga-plugins/openid-auth/back/taiga_contrib_openid_auth/connector.py" in login
  110.         data = _post(url, params=params, headers=headers)

File "/opt/taiga-plugins/openid-auth/back/taiga_contrib_openid_auth/connector.py" in _post
  81.     response = requests.post(url, data=params, headers=headers)

File "/usr/local/lib/python3.6/site-packages/requests/api.py" in post
  116.     return request('post', url, data=data, json=json, **kwargs)

File "/usr/local/lib/python3.6/site-packages/requests/api.py" in request
  60.         return session.request(method=method, url=url, **kwargs)

File "/usr/local/lib/python3.6/site-packages/requests/sessions.py" in request
  533.         resp = self.send(prep, **send_kwargs)

File "/usr/local/lib/python3.6/site-packages/raven/breadcrumbs.py" in send
  341.             resp = real_send(self, request, *args, **kwargs)

File "/usr/local/lib/python3.6/site-packages/requests/sessions.py" in send
  646.         r = adapter.send(request, **kwargs)

File "/usr/local/lib/python3.6/site-packages/requests/adapters.py" in send
  514.                 raise SSLError(e, request=request)

Exception Type: SSLError at /api/v1/auth
Exception Value: HTTPSConnectionPool(host='keycloak', port=443): Max retries exceeded with url: /auth/realms/[redacted]/protocol/openid-connect/token (Caused by SSLError(SSLError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:897)'),))

Some other info: I am using locally trusted ssl with internal dns. I have managed to integrate keycloak into nextcloud similarly using openid.

robrotheram commented 3 years ago

Hi, I have no clue what the gulp error is, I am not that familiar with gulp (This project was forked of the github plug-in and I just changed the relevant parts to make it work with my key-cloak) That last line looks like tiaga is having issues with trusting your keycloak ssl cert.

I am unsure how you get python to trust your cert.

For a fall back you could modify lines (69, and 81) https://github.com/robrotheram/taiga-contrib-openid-auth/blob/master/back/taiga_contrib_openid_auth/connector.py#L69 https://github.com/robrotheram/taiga-contrib-openid-auth/blob/master/back/taiga_contrib_openid_auth/connector.py#L81 and add verify=False to get the plug-in to ignore certificate validation

LecrisUT commented 3 years ago

I've found out that it's an issue with how python resolves local signed certificates. I am yet to find a proper solution for the local certificates generated by caddy. But as it stands everything seems to work ok albeit having to revert to http.

PS: the verify=False did not work because there are other problems getting the certificate upstream, which can only be solved by properly trusting the caddy local certificates.