Skip to content
This repository was archived by the owner on Jun 23, 2023. It is now read-only.

Commit eea8d5a

Browse files
authored
Merge pull request #175 from IdentityPython/extra_response_args
An add_on that allows adding extra arguments to a response.
2 parents 742f3c1 + ff7b3fc commit eea8d5a

File tree

3 files changed

+201
-0
lines changed

3 files changed

+201
-0
lines changed

src/oidcop/endpoint_context.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ def __init__(
148148

149149
# Default values, to be changed below depending on configuration
150150
# arguments for endpoints add-ons
151+
self.add_on = {}
151152
self.args = {}
152153
self.authn_broker = None
153154
self.authz = None
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
def pre_construct(response_args, request, endpoint_context, **kwargs):
2+
"""
3+
Add extra arguments to the request.
4+
5+
:param response_args:
6+
:param request:
7+
:param endpoint_context:
8+
:param kwargs:
9+
:return:
10+
"""
11+
12+
_extra = endpoint_context.add_on.get("extra_args")
13+
if _extra:
14+
for arg, _param in _extra.items():
15+
_val = endpoint_context.get(_param)
16+
if _val:
17+
request[arg] = _val
18+
19+
return request
20+
21+
22+
def add_support(endpoint, **kwargs):
23+
#
24+
_added = False
25+
for endpoint_name in list(kwargs.keys()):
26+
_endp = endpoint[endpoint_name]
27+
_endp.pre_construct.append(pre_construct)
28+
29+
if _added is False:
30+
_endp.server_get("endpoint_context").add_on["extra_args"] = kwargs
31+
_added = True

tests/test_61_add_on.py

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
import os
2+
3+
from cryptojwt.jwk.ec import ECKey
4+
from cryptojwt.jwk.ec import new_ec_key
5+
from cryptojwt.jws.jws import factory
6+
from cryptojwt.key_jar import init_key_jar
7+
from oidcmsg.oauth2 import AccessTokenRequest
8+
from oidcmsg.oauth2 import AuthorizationRequest
9+
from oidcmsg.time_util import utc_time_sans_frac
10+
11+
from oidcop.authn_event import create_authn_event
12+
import pytest
13+
14+
from oidcop import user_info
15+
from oidcop.client_authn import verify_client
16+
from oidcop.configure import OPConfiguration
17+
from oidcop.oauth2.authorization import Authorization
18+
from oidcop.oidc.token import Token
19+
from oidcop.server import Server
20+
from oidcop.user_authn.authn_context import INTERNETPROTOCOLPASSWORD
21+
22+
23+
KEYDEFS = [
24+
{"type": "RSA", "key": "", "use": ["sig"]},
25+
{"type": "EC", "crv": "P-256", "use": ["sig"]},
26+
]
27+
28+
ISSUER = "https://example.com/"
29+
30+
KEYJAR = init_key_jar(key_defs=KEYDEFS, issuer_id=ISSUER)
31+
KEYJAR.import_jwks(KEYJAR.export_jwks(True, ISSUER), "")
32+
33+
RESPONSE_TYPES_SUPPORTED = [
34+
["code"],
35+
["token"],
36+
["id_token"],
37+
["code", "token"],
38+
["code", "id_token"],
39+
["id_token", "token"],
40+
["code", "token", "id_token"],
41+
["none"],
42+
]
43+
44+
CAPABILITIES = {
45+
"response_types_supported": [" ".join(x) for x in RESPONSE_TYPES_SUPPORTED],
46+
"token_endpoint_auth_methods_supported": [
47+
"client_secret_post",
48+
"client_secret_basic",
49+
"client_secret_jwt",
50+
"private_key_jwt",
51+
],
52+
"response_modes_supported": ["query", "fragment", "form_post"],
53+
"subject_types_supported": ["public", "pairwise", "ephemeral"],
54+
"grant_types_supported": [
55+
"authorization_code",
56+
"implicit",
57+
"urn:ietf:params:oauth:grant-type:jwt-bearer",
58+
],
59+
"claim_types_supported": ["normal", "aggregated", "distributed"],
60+
"claims_parameter_supported": True,
61+
"request_parameter_supported": True,
62+
"request_uri_parameter_supported": True,
63+
}
64+
65+
AUTH_REQ = AuthorizationRequest(
66+
client_id="client_1",
67+
redirect_uri="https://example.com/cb",
68+
scope=["openid"],
69+
state="STATE",
70+
response_type="code",
71+
)
72+
73+
BASEDIR = os.path.abspath(os.path.dirname(__file__))
74+
75+
76+
class TestEndpoint(object):
77+
@pytest.fixture(autouse=True)
78+
def create_endpoint(self):
79+
conf = {
80+
"issuer": ISSUER,
81+
"httpc_params": {"verify": False, "timeout": 1},
82+
"capabilities": CAPABILITIES,
83+
"add_on": {
84+
"extra_args": {
85+
"function": "oidcop.oauth2.add_on.extra_args.add_support",
86+
"kwargs": {
87+
"authorization": {"iss": "issuer"}
88+
}
89+
},
90+
},
91+
"keys": {"uri_path": "jwks.json", "key_defs": KEYDEFS},
92+
"token_handler_args": {
93+
"jwks_file": "private/token_jwks.json",
94+
"code": {"lifetime": 600},
95+
"token": {
96+
"class": "oidcop.token.jwt_token.JWTToken",
97+
"kwargs": {
98+
"lifetime": 3600,
99+
"base_claims": {"eduperson_scoped_affiliation": None},
100+
"add_claims_by_scope": True,
101+
"aud": ["https://example.org/appl"],
102+
},
103+
},
104+
"refresh": {
105+
"class": "oidcop.token.jwt_token.JWTToken",
106+
"kwargs": {"lifetime": 3600, "aud": ["https://example.org/appl"], },
107+
},
108+
"id_token": {
109+
"class": "oidcop.token.id_token.IDToken",
110+
"kwargs": {
111+
"base_claims": {
112+
"email": {"essential": True},
113+
"email_verified": {"essential": True},
114+
}
115+
},
116+
},
117+
},
118+
"endpoint": {
119+
"authorization": {
120+
"path": "{}/authorization",
121+
"class": Authorization,
122+
"kwargs": {},
123+
},
124+
"token": {
125+
"path": "{}/token",
126+
"class": Token,
127+
"kwargs": {}},
128+
},
129+
"client_authn": verify_client,
130+
"authentication": {
131+
"anon": {
132+
"acr": INTERNETPROTOCOLPASSWORD,
133+
"class": "oidcop.user_authn.user.NoAuthn",
134+
"kwargs": {"user": "diana"},
135+
}
136+
},
137+
"template_dir": "template",
138+
"userinfo": {
139+
"class": user_info.UserInfo,
140+
"kwargs": {"db_file": "users.json"},
141+
},
142+
}
143+
server = Server(OPConfiguration(conf, base_path=BASEDIR), keyjar=KEYJAR)
144+
self.endpoint_context = server.endpoint_context
145+
self.endpoint_context.cdb["client_1"] = {
146+
"client_secret": "hemligt",
147+
"redirect_uris": [("https://example.com/cb", None)],
148+
"client_salt": "salted",
149+
"token_endpoint_auth_method": "client_secret_post",
150+
"response_types": ["code", "token", "code id_token", "id_token"],
151+
}
152+
self.endpoint = server.server_get("endpoint", "authorization")
153+
154+
def test_process_request(self):
155+
_context = self.endpoint.server_get("endpoint_context")
156+
assert _context.add_on["extra_args"] == {'authorization': {'iss': 'issuer'}}
157+
158+
_pr_resp = self.endpoint.parse_request(AUTH_REQ.to_dict())
159+
_resp = self.endpoint.process_request(_pr_resp)
160+
assert set(_resp.keys()) == {
161+
"response_args",
162+
"fragment_enc",
163+
"return_uri",
164+
"cookie",
165+
"session_id",
166+
}
167+
168+
assert 'iss' in _resp["response_args"]
169+
assert _resp["response_args"]["iss"] == _context.issuer

0 commit comments

Comments
 (0)