Skip to content

Commit 58b7f22

Browse files
authored
Merge pull request #58 from IdentityPython/ropc
Added support for the flows Resource Owner Password Credentials and Client Credentials
2 parents 7c8409d + a678cf0 commit 58b7f22

File tree

60 files changed

+1872
-1402
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+1872
-1402
lines changed

src/idpyoidc/claims.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,15 @@ def supported(self, claim):
217217
def prefers(self):
218218
return self.prefer
219219

220+
def get_claim(self, key, default=None):
221+
_val = self.get_usage(key)
222+
if _val is None:
223+
_val = self.get_preference(key)
224+
225+
if _val is None:
226+
return default
227+
else:
228+
return _val
220229

221230
SIGNING_ALGORITHM_SORT_ORDER = ['RS', 'ES', 'PS', 'HS']
222231

src/idpyoidc/client/claims/oidc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ class Claims(client_claims.Claims):
7575
"contacts": None,
7676
"default_max_age": 86400,
7777
"encrypt_id_token_supported": None,
78-
"grant_types_supported": ["authorization_code", "implicit", "refresh_token"],
78+
# "grant_types_supported": ["authorization_code", "refresh_token"],
7979
"logo_uri": None,
8080
"id_token_signing_alg_values_supported": claims.get_signing_algs,
8181
"id_token_encryption_alg_values_supported": claims.get_encryption_algs,

src/idpyoidc/client/oauth2/access_token.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class AccessToken(Service):
2727
request_body_type = "urlencoded"
2828
response_body_type = "json"
2929

30+
_include = {"grant_types_supported": ['authorization_code']}
31+
3032
_supports = {
3133
"token_endpoint_auth_methods_supported": get_client_authn_methods,
3234
"token_endpoint_auth_signing_alg": get_signing_algs,
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import logging
2+
from typing import Optional
3+
from typing import Union
4+
5+
from idpyoidc.client.service import Service
6+
from idpyoidc.message import Message
7+
from idpyoidc.message import oauth2
8+
from idpyoidc.time_util import time_sans_frac
9+
10+
11+
class CCAccessTokenRequest(Service):
12+
"""The service that talks to the OAuth2 client credentials endpoint."""
13+
14+
msg_type = oauth2.CCAccessTokenRequest
15+
response_cls = oauth2.AccessTokenResponse
16+
error_msg = oauth2.ResponseMessage
17+
endpoint_name = "token_endpoint"
18+
synchronous = True
19+
service_name = "client_credentials"
20+
default_authn_method = ""
21+
http_method = "POST"
22+
23+
def __init__(self, upstream_get, conf=None):
24+
Service.__init__(self, upstream_get, conf=conf)
25+
self.pre_construct.append(self.cc_pre_construct)
26+
27+
def cc_pre_construct(self,
28+
request: Union[Message, dict],
29+
service: Service,
30+
post_args: Optional[dict],
31+
**_args):
32+
_grant_type = request.get('grant_type')
33+
if not _grant_type:
34+
request['grant_type'] = 'client_credentials'
35+
elif _grant_type != 'client_credentials':
36+
logging.error('Wrong grant_type')
37+
38+
return request, post_args
39+
40+
def update_service_context(self, resp, key: Optional[str] = "", **kwargs):
41+
if "expires_in" in resp:
42+
resp["__expires_at"] = time_sans_frac() + int(resp["expires_in"])
43+
self.upstream_get("context").cstate.update(key, resp)

src/idpyoidc/client/oauth2/client_credentials/cc_access_token.py

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/idpyoidc/client/oauth2/client_credentials/cc_refresh_access_token.py

Lines changed: 0 additions & 48 deletions
This file was deleted.

src/idpyoidc/client/oauth2/refresh_access_token.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ class RefreshAccessToken(Service):
2323
default_authn_method = "bearer_header"
2424
http_method = "POST"
2525

26+
_include = {"grant_types_supported": ['refresh_token']}
27+
2628
def __init__(self, upstream_get, conf=None):
2729
Service.__init__(self, upstream_get, conf=conf)
2830
self.pre_construct.append(self.oauth_pre_construct)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import logging
2+
from typing import Optional
3+
from typing import Union
4+
5+
from idpyoidc.client.service import Service
6+
from idpyoidc.message import Message
7+
from idpyoidc.message import oauth2
8+
from idpyoidc.time_util import time_sans_frac
9+
10+
11+
class ROPCAccessTokenRequest(Service):
12+
"""The service uses the OAuth2 resource owner password credentials flow."""
13+
14+
msg_type = oauth2.ROPCAccessTokenRequest
15+
response_cls = oauth2.AccessTokenResponse
16+
error_msg = oauth2.ResponseMessage
17+
endpoint_name = "token_endpoint"
18+
synchronous = True
19+
service_name = "resource_owner_password_credentials"
20+
default_authn_method = ""
21+
http_method = "POST"
22+
23+
def __init__(self, upstream_get, conf=None):
24+
Service.__init__(self, upstream_get, conf=conf)
25+
self.pre_construct.append(self.ropc_pre_construct)
26+
27+
def ropc_pre_construct(self,
28+
request: Union[Message, dict],
29+
service: Service,
30+
post_args: Optional[dict],
31+
**_args):
32+
_grant_type = request.get('grant_type')
33+
if not _grant_type:
34+
request['grant_type'] = 'password'
35+
elif _grant_type != 'password':
36+
logging.error('Wrong grant_type')
37+
38+
return request, post_args
39+
40+
def update_service_context(self, resp, key: Optional[str] = "", **kwargs):
41+
if "expires_in" in resp:
42+
resp["__expires_at"] = time_sans_frac() + int(resp["expires_in"])
43+
self.upstream_get("context").cstate.update(key, resp)

src/idpyoidc/client/oauth2/token_exchange.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class TokenExchange(Service):
2727
request_body_type = "urlencoded"
2828
response_body_type = "json"
2929

30+
_include = {'grant_types_supported': ['urn:ietf:params:oauth:grant-type:token-exchange']}
31+
3032
def __init__(self, upstream_get, conf=None):
3133
Service.__init__(self, upstream_get, conf=conf)
3234
self.pre_construct.append(self.oauth_pre_construct)

src/idpyoidc/client/oidc/access_token.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ class AccessToken(access_token.AccessToken):
2323
error_msg = oidc.ResponseMessage
2424
default_authn_method = "client_secret_basic"
2525

26+
_include = {"grant_types_supported": ['authorization_code']}
27+
2628
_supports = {
2729
"token_endpoint_auth_methods_supported": get_client_authn_methods,
2830
"token_endpoint_auth_signing_alg_values_supported": get_signing_algs

0 commit comments

Comments
 (0)