Skip to content

Commit cb2e858

Browse files
authored
Merge pull request #48 from urbanplatform/fix-middleware-bug
Version 2.0.2 - Fixed middleware unbound variable `token` error when using a token prefix different from `Bearer`. - Added new option to customize the expected token prefix via `TOKEN_PREFIX` setting. - Added error handling when the `AUTH_USER_MODEL` is already registered in the admin.
2 parents 6a8af99 + b9a89c9 commit cb2e858

File tree

6 files changed

+28
-15
lines changed

6 files changed

+28
-15
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,9 @@ This package should only be used in projects starting from scratch, since it ove
6060
# Flag if the user info has been included in the token (default is True)
6161
'USER_INFO_IN_TOKEN': True,
6262
# Flag to show the traceback of debug logs (default is False)
63-
'TRACE_DEBUG_LOGS': False
63+
'TRACE_DEBUG_LOGS': False,
64+
# The token prefix that is expected in Authorization header (default is 'Bearer')
65+
'TOKEN_PREFIX': 'Bearer'
6466
}
6567
```
6668

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
44

55
[tool.poetry]
66
name = "django_uw_keycloak"
7-
version = "2.0.1"
7+
version = "2.0.2"
88
description = "Middleware to allow authorization using Keycloak and Django"
99
authors = [
1010
"Ubiwhere <urbanplatform@ubiwhere.com>",

src/django_keycloak/admin.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""
22
Module to register models into Django admin dashboard.
33
"""
4+
import logging
45
from django.contrib import admin
56
from django.contrib.auth import get_user_model
67
from django.utils.html import format_html
@@ -10,6 +11,8 @@
1011

1112
User = get_user_model()
1213

14+
logger = logging.getLogger(__name__)
15+
1316

1417
class UserAdmin(admin.ModelAdmin):
1518
list_display = (
@@ -60,4 +63,7 @@ def has_change_permission(self, request, obj=None):
6063
return False
6164

6265

63-
admin.site.register(User, UserAdmin)
66+
try:
67+
admin.site.register(User, UserAdmin)
68+
except admin.sites.AlreadyRegistered:
69+
logger.warning(f"Could not register Keycloak UserAdmin")

src/django_keycloak/authentication.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,22 @@
66
from rest_framework.authentication import TokenAuthentication
77
from rest_framework.exceptions import AuthenticationFailed
88
from django_keycloak import Token
9+
from django_keycloak.config import settings
910

1011

1112
class KeycloakAuthentication(TokenAuthentication):
1213
"""
1314
A custom token authentication class for Keycloak.
1415
"""
1516

16-
# `keyword` refeers to expected prefix in HTTP
17-
# Authentication header. We use `Bearer` because it
18-
# is commonly used in authorization protocols, such
19-
# as OAuth2
20-
keyword = "Bearer"
17+
# `keyword` refers to expected prefix in HTTP
18+
# Authentication header. Use the user-defined prefix
19+
keyword = settings.TOKEN_PREFIX
2120

2221
def authenticate_credentials(self, access_token: str):
2322
"""
2423
Overrides `authenticate_credentials` to provide custom
25-
Keycloak authentication for a given Bearer token in a request.
24+
Keycloak authentication for a given token in a request.
2625
"""
2726
# Try to build a Token instance from the provided access token in request
2827
token: Union[Token, None] = Token.from_access_token(access_token)

src/django_keycloak/config.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ class Settings:
3939
USER_INFO_IN_TOKEN: Optional[bool] = True
4040
# Flag to show the traceback of debug logs
4141
TRACE_DEBUG_LOGS: Optional[bool] = False
42-
42+
# The token prefix
43+
TOKEN_PREFIX: Optional[str] = "Bearer"
4344
# Derived setting of the SERVER/INTERNAL_URL and BASE_PATH
4445
KEYCLOAK_URL: str = field(init=False)
4546

src/django_keycloak/middleware.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from django_keycloak import Token
1313
from django_keycloak.config import settings
1414
from django_keycloak.models import KeycloakUser, KeycloakUserAutoId
15+
from django_keycloak.config import settings
1516

1617
AUTH_HEADER = "HTTP_AUTHORIZATION"
1718

@@ -41,14 +42,18 @@ def get_token_from_request(self, request) -> Optional[Token]:
4142
# Try to build a Token instance from decoded credentials
4243
token = Token.from_credentials(decoded_username, decoded_password)
4344
if token:
44-
# Convert the request "Basic" auth to "Bearer" with access token
45-
request.META[AUTH_HEADER] = f"Bearer {token.access_token}"
45+
# Convert the request "Basic" auth to token-based with access token
46+
request.META[
47+
AUTH_HEADER
48+
] = f"{settings.TOKEN_PREFIX} {token.access_token}"
4649
else:
47-
# Setup an invalid dummy bearer token
48-
request.META[AUTH_HEADER] = "Bearer not-valid-token"
50+
# Setup an invalid dummy token
51+
request.META[AUTH_HEADER] = f"{settings.TOKEN_PREFIX} not-valid-token"
4952

50-
elif auth_type == "Bearer":
53+
elif auth_type == settings.TOKEN_PREFIX:
5154
token = Token.from_access_token(value)
55+
else:
56+
token = None
5257

5358
return token
5459

0 commit comments

Comments
 (0)