Skip to content

Commit 95abc60

Browse files
authored
Add create_userinfo_header, fix issue with disabling middleware (#234)
* Add create_userinfo_header for use in creating authenticated clients for testing. * Update middleware to completely bypass middleware tasks if it's turned off in settings. This was continuing to pass the request back to RemoteUserMiddleware - which means it would try to do authentication on its own. Instead, if the flag is set, just return the response like we would if we were actually working.
1 parent 69f7a54 commit 95abc60

File tree

6 files changed

+82
-4
lines changed

6 files changed

+82
-4
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<!--
2+
A new scriv changelog fragment.
3+
4+
Uncomment the section that is right (remove the HTML comment wrapper).
5+
For top level release notes, leave all the headers commented out.
6+
-->
7+
8+
<!--
9+
### Removed
10+
11+
- A bullet item for the Removed category.
12+
13+
-->
14+
15+
### Added
16+
17+
- Added create_userinfo_header to assist with creating test clients.
18+
19+
<!--
20+
### Changed
21+
22+
- A bullet item for the Changed category.
23+
24+
-->
25+
<!--
26+
### Deprecated
27+
28+
- A bullet item for the Deprecated category.
29+
30+
-->
31+
<!--
32+
### Fixed
33+
34+
- A bullet item for the Fixed category.
35+
36+
-->
37+
<!--
38+
### Security
39+
40+
- A bullet item for the Security category.
41+
42+
-->

src/apigateway/mitol/apigateway/api.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,24 @@ def get_username_from_userinfo_header(request: HttpRequest | dict) -> str | None
8181
return None
8282

8383
return User.objects.get(global_id=user_id).username
84+
85+
86+
def create_userinfo_header(user):
87+
"""
88+
Create an X_USERINFO header, so we can fake out auth properly.
89+
APIClient has a force_authenticate method that adds the user account to the
90+
fake request, but the middleware in apigateway will kick it out because the
91+
header won't be there. So, use this to add the header when creating APIClients.
92+
Ex: new APIClient(headers=create_userinfo_header(myuser))
93+
This will use the model map in reverse. It will only care about the
94+
user_fields
95+
"""
96+
97+
model_map = settings.MITOL_APIGATEWAY_USERINFO_MODEL_MAP
98+
header_name = settings.MITOL_APIGATEWAY_USERINFO_HEADER_NAME.replace("HTTP_", "")
99+
header_data = {
100+
k: str(getattr(user, model_map["user_fields"][k], None))
101+
for k in model_map["user_fields"]
102+
}
103+
104+
return {header_name: base64.b64encode(json.dumps(header_data).encode())}

src/apigateway/mitol/apigateway/middleware.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def process_request(self, request):
2727
log.debug("ApisixUserMiddleware.process_request: started")
2828

2929
if settings.MITOL_APIGATEWAY_DISABLE_MIDDLEWARE:
30-
return super().process_request(request)
30+
return self.get_response(request)
3131

3232
if request.META.get(settings.MITOL_APIGATEWAY_USERINFO_HEADER_NAME):
3333
new_header = get_user_id_from_userinfo_header(request)

src/apigateway/mitol/apigateway/settings/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@
2222
# Mappings to the user model.
2323
"user_fields": {
2424
# Keys are data returned from the API gateway.
25-
# Values are tuple of model name (from above) and field name.
26-
# The base model is "user".
25+
# Values are the user object field name.
2726
"preferred_username": "username",
2827
"email": "email",
2928
"sub": "global_id",

tests/apigateway/test_api.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
"""Tests for the Apigateway API."""
22

3+
import base64
4+
import json
5+
36
import faker
47
import pytest
58
from django.conf import settings
@@ -47,3 +50,14 @@ def test_get_username(obj_type):
4750
decoded = api.get_username_from_userinfo_header(request)
4851
assert decoded != user_info[settings.MITOL_APIGATEWAY_USERINFO_ID_FIELD]
4952
assert decoded == user.username
53+
54+
55+
def test_create_userinfo_header():
56+
"""Test that the userinfo header gets created properly."""
57+
58+
user = SsoUserFactory.create()
59+
header_name = settings.MITOL_APIGATEWAY_USERINFO_HEADER_NAME.replace("HTTP_", "")
60+
header_data = api.create_userinfo_header(user)
61+
result = json.loads(base64.b64decode(header_data[header_name]).decode())
62+
63+
assert result["sub"] == user.global_id

uv.lock

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)