feat: pass session ID in redirect URL for native app OIDC login
When a native app (iOS, Android, Desktop) initiates OIDC login with a custom URL scheme as returnTo (e.g. visio://auth-callback), the session cookie set by Django is not accessible from the native app since it runs in a separate process from the browser. This overrides the OIDC callback view to detect custom-scheme redirect URLs and append the session ID as a query parameter, enabling native apps to complete authentication without needing browser cookie access. Standard HTTPS redirects (web browser) are not affected — they continue to use cookies as before.
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
"""Custom OIDC authentication views for native app support.
|
||||
|
||||
When a native app (iOS, Android, Desktop) initiates OIDC login, it sets
|
||||
`returnTo` to a custom URL scheme (e.g. `visio://auth-callback`). After
|
||||
the OIDC flow completes, Django sets the session cookie and redirects to
|
||||
that URL. However, native apps cannot read browser cookies — they need
|
||||
the session ID passed explicitly in the redirect URL.
|
||||
|
||||
This module overrides the OIDC callback view to append the session ID as
|
||||
a query parameter when the redirect target uses a non-HTTPS scheme.
|
||||
"""
|
||||
|
||||
from urllib.parse import urlencode, urlparse
|
||||
|
||||
from django.conf import settings
|
||||
from django.http import HttpResponseRedirect
|
||||
|
||||
from lasuite.oidc_login.views import (
|
||||
OIDCAuthenticationCallbackView as BaseCallbackView,
|
||||
)
|
||||
|
||||
|
||||
class OIDCAuthenticationCallbackView(BaseCallbackView):
|
||||
"""Callback view that passes session ID to native app deep links."""
|
||||
|
||||
def login_success(self):
|
||||
"""After successful login, append session ID for custom-scheme redirects."""
|
||||
response = super().login_success()
|
||||
|
||||
# Only modify redirects to custom URL schemes (native apps).
|
||||
# Standard HTTPS redirects (web browser) work fine with cookies.
|
||||
if isinstance(response, HttpResponseRedirect):
|
||||
redirect_url = response.url
|
||||
parsed = urlparse(redirect_url)
|
||||
if parsed.scheme and parsed.scheme not in ("http", "https", ""):
|
||||
session_key = self.request.session.session_key
|
||||
cookie_name = getattr(
|
||||
settings, "SESSION_COOKIE_NAME", "sessionid"
|
||||
)
|
||||
separator = "&" if parsed.query else "?"
|
||||
new_url = (
|
||||
f"{redirect_url}{separator}"
|
||||
f"{urlencode({cookie_name: session_key})}"
|
||||
)
|
||||
return HttpResponseRedirect(new_url)
|
||||
|
||||
return response
|
||||
@@ -460,7 +460,7 @@ class Base(Configuration):
|
||||
|
||||
# OIDC - Authorization Code Flow
|
||||
OIDC_AUTHENTICATE_CLASS = "lasuite.oidc_login.views.OIDCAuthenticationRequestView"
|
||||
OIDC_CALLBACK_CLASS = "lasuite.oidc_login.views.OIDCAuthenticationCallbackView"
|
||||
OIDC_CALLBACK_CLASS = "core.authentication.views.OIDCAuthenticationCallbackView"
|
||||
OIDC_CREATE_USER = values.BooleanValue(
|
||||
default=True, environ_name="OIDC_CREATE_USER", environ_prefix=None
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user