Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Call /oidc/logout/ before logging in to ensure there is no session left on taiga-back #5

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

privat-eco
Copy link

Fixes an issue where user actions raises https://github.com/mozilla/mozilla-django-oidc/blob/63f56222e3c95fe67e73107f5f5374f5e662e8ca/mozilla_django_oidc/views.py#L81

To reproduce the issue fixed by this PR :

login via OIDC,
logout
try to log in again

the problem happens because cookie named "sessionid" is not cleaned on frontend logout and not replaced when user logs in again (and so we had a mismatch between the sessionid known by taiga-back and by the web browser.

A better solution would be to add in taiga-front the possibility to hook on logout from thirdparty plugins. if someone is more comfortable than me with Angular, feel free

@ChriFo
Copy link

ChriFo commented Mar 28, 2024

This is the relevante Angular code

angular.module('taigaContrib.logout', []).run ['$rootScope', '$http', ($rootScope, $http) ->
    $rootScope.$on('auth:logout', () ->
        $http.get('/api/v2/auth/logout')
    )
]

and the corresponding Python classes
api.py:

from django.contrib.auth import logout

from taiga.base import response
from taiga.base.api import viewsets
from taiga.base.decorators import list_route


class LogoutViewSet(viewsets.ViewSet):

    @list_route(methods=['GET'])
    def logout(self, request):
        logout(request)

        return response.NoContent()

apps.py:

from django.apps import AppConfig
from django.conf.urls import include, url


class TaigaContribLogoutAppConfig(AppConfig):
    name = "taiga_contrib_logout"
    verbose_name = "Taiga contrib logout App Config"

    def ready(self):
        from taiga.base import routers
        from taiga.urls import urlpatterns
        from .api import LogoutViewSet

        router = routers.DefaultRouter(trailing_slash=False)
        router.register(r"/auth", LogoutViewSet, base_name="logout")
        urlpatterns.append(url(r'^api/v2', include(router.urls)))

@mig5
Copy link

mig5 commented Jan 15, 2025

I didn't want to force a logout when clicking Login, because the user might've already been logged in at OIDC and so they should be seamlessly logged into this app too due to the existing session at the OP.

My solution was similar to the above (thank you very much for the Angular hints!), but different:

  1. added this to the end of the existing coffee file
# Register the run block to handle 'auth:logout' events
module.run(['$rootScope', '$window', ($rootScope, $window) ->
    $rootScope.$on('auth:logout', () ->
        # Perform a full browser redirect to the logout URL
        $window.location.href = '/api/oidc/logout/'
    )
])
  1. Ensured OIDC_STORE_ID_TOKEN = True in config.py (this makes mozilla django oidc library store the id_token in the session). See https://mozilla-django-oidc.readthedocs.io/en/stable/settings.html#OIDC_STORE_ID_TOKEN

  2. Created a provider_logout() method in oidc.py that looked like this (your logout URL might look different depending on your OP):

[...]
from django.contrib.auth import logout

[...]

# See https://mozilla-django-oidc.readthedocs.io/en/stable/installation.html#log-user-out-of-the-openid-connect-provider
def provider_logout(request):
    id_token = request.session.get("oidc_id_token")
    redirect_url = f"https://your-op-provider.com/oauth2/sessions/logout?id_token_hint={id_token}&post_logout_redirect_uri=https://your-taiga-domain.com"

    # End the session in Django.
    logout(request)

    return redirect_url
  1. Set this in config.py:
    # See https://mozilla-django-oidc.readthedocs.io/en/stable/settings.html#OIDC_OP_LOGOUT_URL_METHOD
    ALLOW_LOGOUT_GET_METHOD = True
    OIDC_OP_LOGOUT_URL_METHOD = 'taiga_contrib_oidc_auth.oidc.provider_logout'

Now requests to /api/oidc/logout/ (note the trailing slash) trigger both the end of the django session and also redirect to the OP to end the login session at the OP. The user is fully logged out (and doesn't just get auto-logged in next time they step through the OIDC login flow)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants