1+ import json
2+
13from oidcmsg .message import Message
24from oidcmsg .message import SINGLE_OPTIONAL_JSON
35from oidcmsg .message import SINGLE_REQUIRED_STRING
@@ -20,7 +22,9 @@ class State(Message):
2022
2123KEY_PATTERN = {
2224 'nonce' : '__{}__' ,
23- 'logout state' : '::{}::'
25+ 'logout state' : '::{}::' ,
26+ 'session id' : '..{}..' ,
27+ 'subject id' : '=={}=='
2428}
2529
2630
@@ -197,30 +201,38 @@ def multiple_extend_request_args(self, args, key, parameters, item_types,
197201
198202 return args
199203
200- def store_X2state (self , nonce , state , xtyp ):
204+ def store_X2state (self , x , state , xtyp ):
201205 """
202- Store the connection between a nonce value and a state value.
206+ Store the connection between some value and a state value.
203207 This allows us later in the game to find the state if we have the nonce.
204208
205- :param nonce : The nonce value
209+ :param x : The value of x
206210 :param state: The state value
211+ :param xtyp: The type of value x is (e.g. nonce, ...)
207212 """
208- self .state_db .set (KEY_PATTERN [xtyp ].format (nonce ), state )
213+ self .state_db .set (KEY_PATTERN [xtyp ].format (x ), state )
214+ _val = self .state_db .get ("ref{}ref" .format (state ))
215+ if _val is None :
216+ refs = {xtyp :x }
217+ else :
218+ refs = json .loads (_val )
219+ refs [xtyp ] = x
220+ self .state_db .set ("ref{}ref" .format (state ), json .dumps (refs ))
209221
210- def get_state_by_X (self , nonce , xtyp ):
222+ def get_state_by_X (self , x , xtyp ):
211223 """
212- Find the state value by providing the nonce value.
213- Will raise an exception if the nonce value is absent from the state
224+ Find the state value by providing the x value.
225+ Will raise an exception if the x value is absent from the state
214226 data base.
215227
216- :param nonce : The nonce value
228+ :param x : The x value
217229 :return: The state value
218230 """
219- _state = self .state_db .get (KEY_PATTERN [xtyp ].format (nonce ))
231+ _state = self .state_db .get (KEY_PATTERN [xtyp ].format (x ))
220232 if _state :
221233 return _state
222234 else :
223- raise KeyError ('Unknown {}: "{}"' .format (xtyp , nonce ))
235+ raise KeyError ('Unknown {}: "{}"' .format (xtyp , x ))
224236
225237 def store_nonce2state (self , nonce , state ):
226238 """
@@ -245,8 +257,9 @@ def get_state_by_nonce(self, nonce):
245257
246258 def store_logout_state2state (self , logout_state , state ):
247259 """
248- Store the connection between a nonce value and a state value.
249- This allows us later in the game to find the state if we have the nonce.
260+ Store the connection between a logout state value and a state value.
261+ This allows us later in the game to find the state if we have the
262+ logout state value.
250263
251264 :param logout_state: The logout state value
252265 :param state: The state value
@@ -255,15 +268,59 @@ def store_logout_state2state(self, logout_state, state):
255268
256269 def get_state_by_logout_state (self , logout_state ):
257270 """
258- Find the state value by providing the nonce value.
259- Will raise an exception if the nonce value is absent from the state
260- data base.
271+ Find the state value by providing the logout state value.
272+ Will raise an exception if the logout state value is absent from the
273+ state data base.
261274
262- :param nonce : The nonce value
275+ :param logout_state : The logout state value
263276 :return: The state value
264277 """
265278 return self .get_state_by_X (logout_state , 'logout state' )
266279
280+ def store_sid2state (self , sid , state ):
281+ """
282+ Store the connection between a session id (sid) value and a state value.
283+ This allows us later in the game to find the state if we have the
284+ sid value.
285+
286+ :param sid: The session ID value
287+ :param state: The state value
288+ """
289+ self .store_X2state (sid , state , 'session id' )
290+
291+ def get_state_by_sid (self , sid ):
292+ """
293+ Find the state value by providing the logout state value.
294+ Will raise an exception if the logout state value is absent from the
295+ state data base.
296+
297+ :param sid: The session ID value
298+ :return: The state value
299+ """
300+ return self .get_state_by_X (sid , 'session id' )
301+
302+ def store_sub2state (self , sub , state ):
303+ """
304+ Store the connection between a subject id (sub) value and a state value.
305+ This allows us later in the game to find the state if we have the
306+ sub value.
307+
308+ :param sub: The Subject ID value
309+ :param state: The state value
310+ """
311+ self .store_X2state (sub , state , 'subject id' )
312+
313+ def get_state_by_sub (self , sub ):
314+ """
315+ Find the state value by providing the subject id value.
316+ Will raise an exception if the subject id value is absent from the
317+ state data base.
318+
319+ :param sub: The Subject ID value
320+ :return: The state value
321+ """
322+ return self .get_state_by_X (sub , 'subject id' )
323+
267324 def create_state (self , iss , key = '' ):
268325 if not key :
269326 key = rndstr (32 )
@@ -277,4 +334,8 @@ def create_state(self, iss, key=''):
277334 return key
278335
279336 def remove_state (self , state ):
280- self .state_db .delete (state )
337+ self .state_db .delete (state )
338+ refs = json .loads (self .state_db .get ("ref{}ref" .format (state )))
339+ if refs :
340+ for xtyp , x in refs .items ():
341+ self .state_db .delete (KEY_PATTERN [xtyp ].format (x ))
0 commit comments