11"""Implements RFC7662"""
22import logging
33
4- from cryptojwt import JWT
5- from cryptojwt .jws .jws import factory
64from oidcmsg import oauth2
75from oidcmsg .time_util import utc_time_sans_frac
86
119LOGGER = logging .getLogger (__name__ )
1210
1311
14- def before (t1 , t2 , range ):
15- if t1 < (t2 - range ):
16- return True
17- return False
18-
19-
20- def after (t1 , t2 , range ):
21- if t1 > (t2 + range ):
22- return True
23- return False
24-
25-
2612class Introspection (Endpoint ):
2713 """Implements RFC 7662"""
2814
@@ -49,49 +35,30 @@ def get_client_id_from_token(self, endpoint_context, token, request=None):
4935 sinfo = endpoint_context .sdb [token ]
5036 return sinfo ["authn_req" ]["client_id" ]
5137
52- def do_jws (self , token ):
53- _jwt = JWT (key_jar = self .endpoint_context .keyjar )
54-
38+ def _introspect (self , token ):
5539 try :
56- _jwt_info = _jwt .unpack (token )
57- except Exception as err :
58- return None
59-
60- return _jwt_info
61-
62- def do_access_token (self , token ):
63- try :
64- _info = self .endpoint_context .sdb [token ]
40+ info = self .endpoint_context .sdb [token ]
6541 except KeyError :
6642 return None
6743
68- _revoked = _info .get ("revoked" , False )
69- if _revoked :
44+ # Make sure that the token is an access_token or a refresh_token
45+ if token not in info .get ("access_token" ) and token != info .get (
46+ "refresh_token"
47+ ):
7048 return None
7149
72- _eat = _info .get ("expires_at" )
73- if _eat < utc_time_sans_frac ():
50+ eat = info .get ("expires_at" )
51+ if eat and eat < utc_time_sans_frac ():
7452 return None
7553
76- if _info : # Now what can be returned ?
77- _ret = {
78- "sub" : _info ["sub" ],
79- "client_id" : _info ["client_id" ],
80- "token_type" : "bearer" ,
81- "iss" : self .endpoint_context .issuer
82- }
83- _authn = _info .get ("authn_event" )
84- if _authn :
85- _ret ["authn_info" ] = _authn ["authn_info" ]
86- _ret ["authn_time" ] = _authn ["authn_time" ]
87-
88- _scope = _info .get ("scope" )
89- if not _scope :
90- _ret ["scope" ] = " " .join (_info ["authn_req" ]["scope" ])
91-
92- return _ret
93- else :
94- return _info
54+ if info : # Now what can be returned ?
55+ ret = info .to_dict ()
56+ ret ["iss" ] = self .endpoint_context .issuer
57+
58+ if "scope" not in ret :
59+ ret ["scope" ] = " " .join (info ["authn_req" ]["scope" ])
60+
61+ return ret
9562
9663 def process_request (self , request = None , ** kwargs ):
9764 """
@@ -107,29 +74,8 @@ def process_request(self, request=None, **kwargs):
10774 _token = _introspect_request ["token" ]
10875 _resp = self .response_cls (active = False )
10976
110- if factory (_token ):
111- _info = self .do_jws (_token )
112- if _info is None :
113- return {"response_args" : _resp }
114- _now = utc_time_sans_frac ()
115-
116- # Time checks
117- if "exp" in _info :
118- if after (_now , _info ["exp" ], self .offset ):
119- return {"response_args" : _resp }
120- if 'iat' in _info :
121- if after (_info ["iat" ], _now , self .offset ):
122- return {"response_args" : _resp }
123- if 'nbf' in _info :
124- if before (_now , _info ["nbf" ], self .offset ):
125- return {"response_args" : _resp }
126- else :
127- # A non-jws access token
128- _info = self .do_access_token (_token )
129- if _info is None :
130- return {"response_args" : _resp }
131-
132- if not _info :
77+ _info = self ._introspect (_token )
78+ if _info is None :
13379 return {"response_args" : _resp }
13480
13581 if "release" in self .kwargs :
0 commit comments