Skip to content

Commit

Permalink
use nonces during authentication
Browse files Browse the repository at this point in the history
Closes #30
  • Loading branch information
lilioid committed Dec 26, 2024
1 parent d7b76db commit c382877
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 4 deletions.
23 changes: 21 additions & 2 deletions src/simple_openid_connect/integrations/django/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
View functions which handle openid authentication and their related callbacks
"""
import logging
import secrets
from http import HTTPStatus
from typing import Mapping

Expand Down Expand Up @@ -43,6 +44,17 @@ def __init__(self) -> None:
)


class InvalidNonceError(Exception):
"""
Exception that is thrown when an authentication response contains an invalid or no nonce value
"""

def __init__(self) -> None:
super().__init__(
self, "Authentication response contained an invalid or no nonce value"
)


class InitLoginView(View):
"""
The view which handles initiating a login.
Expand All @@ -59,8 +71,13 @@ def get(self, request: HttpRequest) -> HttpResponse:
# See https://www.rfc-editor.org/rfc/rfc6749#section-10.12
request.session["openid_auth_in_progress"] = True

# prevent replay attacks by generating and specifying a nonce
nonce = secrets.token_urlsafe(48)
request.session["openid_auth_nonce"] = nonce

# redirect the user-agent to the oidc provider
client = OpenidAppConfig.get_instance().get_client(request)
redirect = client.authorization_code_flow.start_authentication()
redirect = client.authorization_code_flow.start_authentication(nonce=nonce)
return HttpResponseRedirect(redirect)


Expand Down Expand Up @@ -101,7 +118,9 @@ def get(self, request: HttpRequest) -> HttpResponse:
# validate the received tokens
id_token = IdToken.parse_jwt(token_response.id_token, client.provider_keys)
id_token.validate_extern(
client.provider_config.issuer, client.client_auth.client_id
client.provider_config.issuer,
client.client_auth.client_id,
nonce=request.session["openid_auth_nonce"],
)

# handle federated user information (create a new user if necessary or update local info) and log the user in
Expand Down
23 changes: 21 additions & 2 deletions tests/django_test_project/django_test_project/tests/test_login.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
import secrets
import sys
from base64 import b64encode

Expand All @@ -13,10 +14,17 @@

@pytest.mark.django_db
def test_directly_calling_login_endpoint(
dyn_client, dummy_provider_config, dummy_provider_settings, response_mock, jwks
dyn_client,
dummy_provider_config,
dummy_provider_settings,
response_mock,
jwks,
monkeypatch,
):
# arrange
settings = OpenidAppConfig.get_instance().safe_settings
NONCE = "42"
monkeypatch.setattr(secrets, "token_urlsafe", lambda len: NONCE)
client_auth = b64encode(
f"{settings.OPENID_CLIENT_ID}:{settings.OPENID_CLIENT_SECRET}".encode()
).decode()
Expand All @@ -30,6 +38,7 @@ def test_directly_calling_login_endpoint(
+ resolve_url(settings.OPENID_REDIRECT_URI),
"response_type": "code",
"scope": settings.OPENID_SCOPE,
"nonce": NONCE,
}
)
],
Expand Down Expand Up @@ -69,6 +78,7 @@ def test_directly_calling_login_endpoint(
"aud": settings.OPENID_CLIENT_ID,
"iat": 0,
"exp": sys.maxsize,
"nonce": NONCE,
}
)
).sign_compact(jwks),
Expand All @@ -89,10 +99,17 @@ def test_directly_calling_login_endpoint(

@pytest.mark.django_db
def test_directly_accessing_protected_resource(
dyn_client, dummy_provider_config, dummy_provider_settings, response_mock, jwks
dyn_client,
dummy_provider_config,
dummy_provider_settings,
response_mock,
jwks,
monkeypatch,
):
# arrange
settings = OpenidAppConfig.get_instance().safe_settings
NONCE = "42"
monkeypatch.setattr(secrets, "token_urlsafe", lambda len: NONCE)
client_auth = b64encode(
f"{settings.OPENID_CLIENT_ID}:{settings.OPENID_CLIENT_SECRET}".encode()
).decode()
Expand All @@ -106,6 +123,7 @@ def test_directly_accessing_protected_resource(
+ resolve_url(settings.OPENID_REDIRECT_URI),
"response_type": "code",
"scope": settings.OPENID_SCOPE,
"nonce": NONCE,
}
)
],
Expand Down Expand Up @@ -145,6 +163,7 @@ def test_directly_accessing_protected_resource(
"aud": settings.OPENID_CLIENT_ID,
"iat": 0,
"exp": sys.maxsize,
"nonce": NONCE,
}
)
).sign_compact(jwks),
Expand Down

0 comments on commit c382877

Please sign in to comment.