✨(oidc) store refresh token in session
This code is not very clean but it reduces the footprint to add refresh token storage in session. This could be cleaned up once the PR it merged: https://github.com/mozilla/mozilla-django-oidc/pull/377
This commit is contained in:
@@ -17,6 +17,12 @@ from core.models import DuplicateEmailError, User
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def store_oidc_refresh_token(session, refresh_token):
|
||||
"""Store the OIDC refresh token in the session if enabled in settings."""
|
||||
if import_from_settings("OIDC_STORE_REFRESH_TOKEN", False):
|
||||
session["oidc_refresh_token"] = refresh_token
|
||||
|
||||
|
||||
def store_tokens(session, access_token, id_token, refresh_token):
|
||||
"""Store tokens in the session if enabled in settings."""
|
||||
if import_from_settings("OIDC_STORE_ACCESS_TOKEN", False):
|
||||
@@ -25,8 +31,7 @@ def store_tokens(session, access_token, id_token, refresh_token):
|
||||
if import_from_settings("OIDC_STORE_ID_TOKEN", False):
|
||||
session["oidc_id_token"] = id_token
|
||||
|
||||
if import_from_settings("OIDC_STORE_REFRESH_TOKEN", False):
|
||||
session["oidc_refresh_token"] = refresh_token
|
||||
store_oidc_refresh_token(session, refresh_token)
|
||||
|
||||
|
||||
class OIDCAuthenticationBackend(MozillaOIDCAuthenticationBackend):
|
||||
@@ -36,6 +41,40 @@ class OIDCAuthenticationBackend(MozillaOIDCAuthenticationBackend):
|
||||
in the User and Identity models, and handles signed and/or encrypted UserInfo response.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""
|
||||
Initialize the OIDC Authentication Backend.
|
||||
|
||||
Adds an internal attribute to store the token_info dictionary.
|
||||
The purpose of `self._token_info` is to not duplicate code from
|
||||
the original `authenticate` method.
|
||||
This won't be needed after https://github.com/mozilla/mozilla-django-oidc/pull/377
|
||||
is merged.
|
||||
"""
|
||||
super().__init__(*args, **kwargs)
|
||||
self._token_info = None
|
||||
|
||||
def get_token(self, payload):
|
||||
"""
|
||||
Return token object as a dictionary.
|
||||
|
||||
Store the value to extract the refresh token in the `authenticate` method.
|
||||
"""
|
||||
self._token_info = super().get_token(payload)
|
||||
return self._token_info
|
||||
|
||||
def authenticate(self, request, **kwargs):
|
||||
"""Authenticates a user based on the OIDC code flow."""
|
||||
user = super().authenticate(request, **kwargs)
|
||||
|
||||
if user is not None:
|
||||
# Then the user successfully authenticated
|
||||
store_oidc_refresh_token(
|
||||
request.session, self._token_info.get("refresh_token")
|
||||
)
|
||||
|
||||
return user
|
||||
|
||||
def get_userinfo(self, access_token, id_token, payload):
|
||||
"""Return user details dictionary.
|
||||
|
||||
|
||||
@@ -547,3 +547,55 @@ def test_authentication_verify_claims_success(django_assert_num_queries, monkeyp
|
||||
assert user.full_name == "Doe"
|
||||
assert user.short_name is None
|
||||
assert user.email == "[email protected]"
|
||||
|
||||
|
||||
@responses.activate
|
||||
def test_authentication_session_tokens(
|
||||
django_assert_num_queries, monkeypatch, rf, settings
|
||||
):
|
||||
"""
|
||||
Test that the session contains oidc_refresh_token and oidc_access_token after authentication.
|
||||
"""
|
||||
settings.OIDC_OP_TOKEN_ENDPOINT = "http://oidc.endpoint.test/token"
|
||||
settings.OIDC_OP_USER_ENDPOINT = "http://oidc.endpoint.test/userinfo"
|
||||
settings.OIDC_OP_JWKS_ENDPOINT = "http://oidc.endpoint.test/jwks"
|
||||
settings.OIDC_STORE_ACCESS_TOKEN = True
|
||||
settings.OIDC_STORE_REFRESH_TOKEN = True
|
||||
|
||||
klass = OIDCAuthenticationBackend()
|
||||
request = rf.get("/some-url", {"state": "test-state", "code": "test-code"})
|
||||
request.session = {}
|
||||
|
||||
def verify_token_mocked(*args, **kwargs):
|
||||
return {"sub": "123", "email": "[email protected]"}
|
||||
|
||||
monkeypatch.setattr(OIDCAuthenticationBackend, "verify_token", verify_token_mocked)
|
||||
|
||||
responses.add(
|
||||
responses.POST,
|
||||
re.compile(settings.OIDC_OP_TOKEN_ENDPOINT),
|
||||
json={
|
||||
"access_token": "test-access-token",
|
||||
"refresh_token": "test-refresh-token",
|
||||
},
|
||||
status=200,
|
||||
)
|
||||
|
||||
responses.add(
|
||||
responses.GET,
|
||||
re.compile(settings.OIDC_OP_USER_ENDPOINT),
|
||||
json={"sub": "123", "email": "[email protected]"},
|
||||
status=200,
|
||||
)
|
||||
|
||||
with django_assert_num_queries(6):
|
||||
user = klass.authenticate(
|
||||
request,
|
||||
code="test-code",
|
||||
nonce="test-nonce",
|
||||
code_verifier="test-code-verifier",
|
||||
)
|
||||
|
||||
assert user is not None
|
||||
assert request.session["oidc_access_token"] == "test-access-token"
|
||||
assert request.session["oidc_refresh_token"] == "test-refresh-token"
|
||||
|
||||
Reference in New Issue
Block a user