ASKBOT / askbot-devel

Askbot is a Django/Python Q&A forum. **Contributors README**: https://github.com/ASKBOT/askbot-devel#how-to-contribute. Commercial hosting of Askbot and support are available at https://askbot.com
Other
1.57k stars 627 forks source link

OpenID Connect login #926

Closed brunobastosg closed 1 year ago

brunobastosg commented 1 year ago

Is it possible to use some third-party library (like mozilla-django-oidc)?

Or it would require changes in askbot's code anyway?

brunobastosg commented 1 year ago

Just saw that there is code for OIDC: https://github.com/ASKBOT/askbot-devel/tree/master/askbot/deps/django_authopenid/protocols/oidc

Is it working? I don't see any login provider for OIDC here https://github.com/ASKBOT/askbot-devel/blob/3ac68d76c8b94ac7f51fc2d7dac5ff43e5229781/askbot/conf/login_providers.py

evgenyfadeev commented 1 year ago

So far I have it tested via configuring a ASKBOT_CUSTOM_AUTH_MODULE, which is a Python path to a .py file containing settings:

BIG_BUTTON = True
ORDER_NUMBER = 1
NAME = 'AskbotOkta'
ICON_MEDIA_PATH = 'images/jquery-openid/okta.png'
DISPLAY_NAME = 'Okta'
TYPE = 'oidc'
TRUST_EMAIL = True
TOOLTIP_TEXT = 'Sign in via Okta'
EXTRA_TOKEN_NAME = 'Okta login name and password'
OIDC_AUDIENCE = 'api://default'
OIDC_PROVIDER_URL = 'https://<your okta provider domain>/oauth2/default'
OIDC_CLIENT_ID = '<your client id>'
OIDC_CLIENT_SECRET = '<your client secret>'

It is working for me with OKTA, not tested with any other providers yet.

You can examine how this module is interpreted and try to define it accordingly.

It is possible that some modifications to the oidc flow might be needed to accomodate other OIDC providers, but those changes should be acceptable for all providers.

brunobastosg commented 1 year ago

Great! Thanks for the info! I'll try it.

brunobastosg commented 1 year ago

Hey, evgeny. It worked with Keycloak!

Just a question though... After I login for the first time, it takes me to a "Complete registration" screen, with my info already filled in, and a Signup button.

Is there a way to skip this screen and auto create the user? Using LDAP, there is a setting called LDAP_AUTOCREATE_USERS that does this, but I didn't find a similar setting for OIDC.

brunobastosg commented 1 year ago

I have one more question. I previously used LDAP authentication and now I'm migrating to OIDC.

However, if the LDAP user already exists, the OIDC login says user already exists. Is there any way to "reuse" the same user if it was created by LDAP login?

evgenyfadeev commented 1 year ago

If you set TRUST_EMAIL = True in the oidc provider module the oidc user will authenticate existing user with matching email, is that doing what you expect?

Here is where this check is done:

https://github.com/ASKBOT/askbot-devel/blob/master/askbot/deps/django_authopenid/protocols/oidc/views.py#L64

brunobastosg commented 1 year ago

If you set TRUST_EMAIL = True in the oidc provider module the oidc user will authenticate existing user with matching email, is that doing what you expect?

Thanks. The email field of the LDAP user was empty, that's why it hadn't work before.

Is there a way to skip this screen and auto create the user? Using LDAP, there is a setting called LDAP_AUTOCREATE_USERS that does this, but I didn't find a similar setting for OIDC.

How about this? Is it possible? If not and you could give me directions on how to implement it, I'd be happy to.

evgenyfadeev commented 1 year ago

I wrote here an answer, but decided to consider a bit more. I'll try to answer tomorrow.

brunobastosg commented 1 year ago

No problem. I'll close the issue since I got it working with Keycloak.

For reference if anyone is wondering:

BIG_BUTTON = True
ORDER_NUMBER = 1
NAME = 'Keycloak'
ICON_MEDIA_PATH = 'https://www.keycloak.org/resources/images/keycloak_icon_512px.svg'
DISPLAY_NAME = 'Keycloak'
TYPE = 'oidc'
TRUST_EMAIL = True
TOOLTIP_TEXT = 'Sign in via Keycloak'
EXTRA_TOKEN_NAME = 'Keycloak login name and password'
OIDC_AUDIENCE = 'api://default'
OIDC_PROVIDER_URL = 'https://<your keycloak provider domain>/auth/realms/<realm name>'
OIDC_CLIENT_ID = '<your client id>'
OIDC_CLIENT_SECRET = '<your client secret>'