moin icon indicating copy to clipboard operation
moin copied to clipboard

Add OIDC authentication using Flask-pyoidc.

Open openbrian opened this issue 2 years ago • 3 comments

Here's a PR to add OIDC authentication. It works just fine with Keycloak.

It does not fit into your design pattern because your Moin assumes all authentication methods have a password. OIDC does not. It will NOT login the user in middleware.

Initially there's support for 1 identity provider, but with small changes you can add multiple IDPs.

This change was very hard to make given the architecture of the current system. I left comments where Moin can become a more idiomatic Flask website. Notably:

  • getting the user from the session should not depend on the authentication mode
  • authentication should happen in a view/controller, not middleware
  • the session needs only 2 items: user id, session_token
  • model classes should not be touching the session
  • the indexer is a pain in the ass to use / it should return objects not dictionaries

These are noted in the codebase with my initials: BCD. Feel free to ignore and delete them.

A web app should not be inventing it's own authentication and session management. Consider using Flask-Login to handle this. (Also consider using Flask-Security-Too.)

openbrian avatar Aug 29 '23 19:08 openbrian

setup.py:111:17: E999 SyntaxError: invalid syntax

Also had to uncomment these lines in wikiconfig.py:

OIDC_REDIRECT_URI = 'http://localhost:5000/oidc_redirect_uri'
OIDC_ISSUER="https://localhost:8080/auth/realms/myfolks"
OIDC_CLIENT_ID='example.com/wiki'  # best practice is to use domain name and path here
OIDC_CLIENT_SECRET='get this from the idp administrator'
OIDC_LOGOUT_URI='todo'

After setting sso = True in wikiconfig.py:

(moin-venv-python) C:\AA-GIT\BrianD\moin>m run --port 8080
2023-08-31 09:55:24,714 ERROR oic.oauth2.base:138 http_request failed: HTTPSConnectionPool(host='localhost', port=8080):
 Max retries exceeded with url: /auth/realms/myfolks/.well-known/openid-configuration (Caused by NewConnectionError('<ur
llib3.connection.HTTPSConnection object at 0x00000213C9EA69E0>: Failed to establish a new connection: [WinError 10061] N
o connection could be made because the target machine actively refused it')), url: https://localhost:8080/auth/realms/my
folks/.well-known/openid-configuration, htargs: {'allow_redirects': True, 'cert': None, 'verify': True, 'timeout': 5.0},
 method: GET
Traceback (most recent call last):
  File "\\?\C:\AA-GIT\BrianD\moin-venv-python\Scripts\moin-script.py", line 33, in <module>
    sys.exit(load_entry_point('moin', 'console_scripts', 'moin')())
  File "C:\AA-GIT\BrianD\moin-venv-python\lib\site-packages\click\core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
  File "C:\AA-GIT\BrianD\moin-venv-python\lib\site-packages\click\core.py", line 1078, in main
    rv = self.invoke(ctx)
  File "C:\AA-GIT\BrianD\moin-venv-python\lib\site-packages\click\core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "C:\AA-GIT\BrianD\moin-venv-python\lib\site-packages\click\core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "C:\AA-GIT\BrianD\moin-venv-python\lib\site-packages\click\core.py", line 783, in invoke
    return __callback(*args, **kwargs)
  File "C:\AA-GIT\BrianD\moin-venv-python\lib\site-packages\click\decorators.py", line 92, in new_func
    return ctx.invoke(f, obj, *args, **kwargs)
  File "C:\AA-GIT\BrianD\moin-venv-python\lib\site-packages\click\core.py", line 783, in invoke
    return __callback(*args, **kwargs)
  File "C:\AA-GIT\BrianD\moin-venv-python\lib\site-packages\flask\cli.py", line 911, in run_command
    raise e from None
  File "C:\AA-GIT\BrianD\moin-venv-python\lib\site-packages\flask\cli.py", line 897, in run_command
    app = info.load_app()
  File "C:\AA-GIT\BrianD\moin-venv-python\lib\site-packages\flask\cli.py", line 301, in load_app
    app = self.create_app()
  File "c:\aa-git\briand\moin\src\moin\app.py", line 52, in create_app
    return create_app_ext(flask_config_file=config)
  File "c:\aa-git\briand\moin\src\moin\app.py", line 158, in create_app_ext
    oidc.init_app(app)
  File "C:\AA-GIT\BrianD\moin-venv-python\lib\site-packages\flask_pyoidc\flask_pyoidc.py", line 86, in init_app
    self.clients = {
  File "C:\AA-GIT\BrianD\moin-venv-python\lib\site-packages\flask_pyoidc\flask_pyoidc.py", line 87, in <dictcomp>
    name: PyoidcFacade(configuration, self._redirect_uri_config.full_uri)
  File "C:\AA-GIT\BrianD\moin-venv-python\lib\site-packages\flask_pyoidc\pyoidc_facade.py", line 41, in __init__
    provider_metadata = provider_configuration.ensure_provider_metadata(self._client)
  File "C:\AA-GIT\BrianD\moin-venv-python\lib\site-packages\flask_pyoidc\provider_configuration.py", line 179, in ensure
_provider_metadata
    resp = client.provider_config(self._issuer)
  File "C:\AA-GIT\BrianD\moin-venv-python\lib\site-packages\oic\oauth2\__init__.py", line 1150, in provider_config
    r = self.http_request(url, allow_redirects=True)
  File "C:\AA-GIT\BrianD\moin-venv-python\lib\site-packages\oic\oauth2\base.py", line 135, in http_request
    req.request(method, url, **_kwargs),
  File "C:\AA-GIT\BrianD\moin-venv-python\lib\site-packages\requests\sessions.py", line 589, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\AA-GIT\BrianD\moin-venv-python\lib\site-packages\requests\sessions.py", line 703, in send
    r = adapter.send(request, **kwargs)
  File "C:\AA-GIT\BrianD\moin-venv-python\lib\site-packages\requests\adapters.py", line 519, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPSConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /a
uth/realms/myfolks/.well-known/openid-configuration (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection o
bject at 0x00000213C9EA69E0>: Failed to establish a new connection: [WinError 10061] No connection could be made because
 the target machine actively refused it'))

RogerHaase avatar Aug 30 '23 21:08 RogerHaase

Start up an open ID connect server on port 8080. I suggest keycloak. Create a realm. Add a user, set a password. Create a client, set a client id. Set the redirect uri that matches your env.

openbrian avatar Sep 04 '23 19:09 openbrian

Or use a commercial one like Okta or Auth0.

openbrian avatar Sep 04 '23 19:09 openbrian