@@ -36,10 +36,50 @@ def __init__(self):
36
36
self ._lock = threading .RLock ()
37
37
self ._cache = {}
38
38
self .key_makers = {
39
- self .CredentialType .REFRESH_TOKEN : self ._build_rt_key ,
40
- self .CredentialType .ACCESS_TOKEN : self ._build_at_key ,
41
- self .CredentialType .ID_TOKEN : self ._build_idt_key ,
42
- self .CredentialType .ACCOUNT : self ._build_account_key ,
39
+ self .CredentialType .REFRESH_TOKEN :
40
+ lambda home_account_id = None , environment = None , client_id = None ,
41
+ target = None , ** ignored_payload_from_a_real_token :
42
+ "-" .join ([
43
+ home_account_id or "" ,
44
+ environment or "" ,
45
+ self .CredentialType .REFRESH_TOKEN ,
46
+ client_id or "" ,
47
+ "" , # RT is cross-tenant in AAD
48
+ target or "" , # raw value could be None if deserialized from other SDK
49
+ ]).lower (),
50
+ self .CredentialType .ACCESS_TOKEN :
51
+ lambda home_account_id = None , environment = None , client_id = None ,
52
+ realm = None , target = None , ** ignored_payload_from_a_real_token :
53
+ "-" .join ([
54
+ home_account_id or "" ,
55
+ environment or "" ,
56
+ self .CredentialType .ACCESS_TOKEN ,
57
+ client_id ,
58
+ realm or "" ,
59
+ target or "" ,
60
+ ]).lower (),
61
+ self .CredentialType .ID_TOKEN :
62
+ lambda home_account_id = None , environment = None , client_id = None ,
63
+ realm = None , ** ignored_payload_from_a_real_token :
64
+ "-" .join ([
65
+ home_account_id or "" ,
66
+ environment or "" ,
67
+ self .CredentialType .ID_TOKEN ,
68
+ client_id or "" ,
69
+ realm or "" ,
70
+ "" # Albeit irrelevant, schema requires an empty scope here
71
+ ]).lower (),
72
+ self .CredentialType .ACCOUNT :
73
+ lambda home_account_id = None , environment = None , realm = None ,
74
+ ** ignored_payload_from_a_real_entry :
75
+ "-" .join ([
76
+ home_account_id or "" ,
77
+ environment or "" ,
78
+ realm or "" ,
79
+ ]).lower (),
80
+ self .CredentialType .APP_METADATA :
81
+ lambda environment = None , client_id = None , ** kwargs :
82
+ "appmetadata-{}-{}" .format (environment or "" , client_id or "" ),
43
83
}
44
84
45
85
def find (self , credential_type , target = None , query = None ):
@@ -88,12 +128,9 @@ def add(self, event, now=None):
88
128
with self ._lock :
89
129
90
130
if access_token :
91
- key = self ._build_at_key (
92
- home_account_id , environment , event .get ("client_id" , "" ),
93
- realm , target )
94
131
now = time .time () if now is None else now
95
132
expires_in = response .get ("expires_in" , 3599 )
96
- self . _cache . setdefault ( self . CredentialType . ACCESS_TOKEN , {})[ key ] = {
133
+ at = {
97
134
"credential_type" : self .CredentialType .ACCESS_TOKEN ,
98
135
"secret" : access_token ,
99
136
"home_account_id" : home_account_id ,
@@ -106,12 +143,12 @@ def add(self, event, now=None):
106
143
"extended_expires_on" : str (int ( # Same here
107
144
now + response .get ("ext_expires_in" , expires_in ))),
108
145
}
146
+ self .modify (self .CredentialType .ACCESS_TOKEN , at , at )
109
147
110
148
if client_info :
111
149
decoded_id_token = decode_id_token (
112
150
id_token , client_id = event ["client_id" ]) if id_token else {}
113
- key = self ._build_account_key (home_account_id , environment , realm )
114
- self ._cache .setdefault (self .CredentialType .ACCOUNT , {})[key ] = {
151
+ account = {
115
152
"home_account_id" : home_account_id ,
116
153
"environment" : environment ,
117
154
"realm" : realm ,
@@ -123,11 +160,10 @@ def add(self, event, now=None):
123
160
else self .AuthorityType .MSSTS ,
124
161
# "client_info": response.get("client_info"), # Optional
125
162
}
163
+ self .modify (self .CredentialType .ACCOUNT , account , account )
126
164
127
165
if id_token :
128
- key = self ._build_idt_key (
129
- home_account_id , environment , event .get ("client_id" , "" ), realm )
130
- self ._cache .setdefault (self .CredentialType .ID_TOKEN , {})[key ] = {
166
+ idt = {
131
167
"credential_type" : self .CredentialType .ID_TOKEN ,
132
168
"secret" : id_token ,
133
169
"home_account_id" : home_account_id ,
@@ -136,11 +172,9 @@ def add(self, event, now=None):
136
172
"client_id" : event .get ("client_id" ),
137
173
# "authority": "it is optional",
138
174
}
175
+ self .modify (self .CredentialType .ID_TOKEN , idt , idt )
139
176
140
177
if refresh_token :
141
- key = self ._build_rt_key (
142
- home_account_id , environment ,
143
- event .get ("client_id" , "" ), target )
144
178
rt = {
145
179
"credential_type" : self .CredentialType .REFRESH_TOKEN ,
146
180
"secret" : refresh_token ,
@@ -151,53 +185,33 @@ def add(self, event, now=None):
151
185
}
152
186
if "foci" in response :
153
187
rt ["family_id" ] = response ["foci" ]
154
- self ._cache . setdefault (self .CredentialType .REFRESH_TOKEN , {})[ key ] = rt
188
+ self .modify (self .CredentialType .REFRESH_TOKEN , rt , rt )
155
189
156
- key = self ._build_appmetadata_key (environment , event .get ("client_id" ))
157
190
app_metadata = {
158
191
"client_id" : event .get ("client_id" ),
159
192
"environment" : environment ,
160
193
}
161
194
if "foci" in response :
162
195
app_metadata ["family_id" ] = response .get ("foci" )
163
- self ._cache . setdefault (self .CredentialType .APP_METADATA , {})[ key ] = app_metadata
196
+ self .modify (self .CredentialType .APP_METADATA , app_metadata , app_metadata )
164
197
165
198
def modify (self , credential_type , old_entry , new_key_value_pairs = None ):
166
199
# Modify the specified old_entry with new_key_value_pairs,
167
200
# or remove the old_entry if the new_key_value_pairs is None.
168
201
169
- # This helper exists to consolidate all token modify/remove behaviors,
202
+ # This helper exists to consolidate all token add/ modify/remove behaviors,
170
203
# so that the sub-classes will have only one method to work on,
171
204
# instead of patching a pair of update_xx() and remove_xx() per type.
172
205
# You can monkeypatch self.key_makers to support more types on-the-fly.
173
206
key = self .key_makers [credential_type ](** old_entry )
174
207
with self ._lock :
175
208
if new_key_value_pairs : # Update with them
176
209
entries = self ._cache .setdefault (credential_type , {})
177
- entry = entries .get (key , {}) # key usually exists, but we'll survive its absence
210
+ entry = entries .setdefault (key , {}) # Create it if not yet exist
178
211
entry .update (new_key_value_pairs )
179
212
else : # Remove old_entry
180
213
self ._cache .setdefault (credential_type , {}).pop (key , None )
181
214
182
-
183
- @staticmethod
184
- def _build_appmetadata_key (environment , client_id ):
185
- return "appmetadata-{}-{}" .format (environment or "" , client_id or "" )
186
-
187
- @classmethod
188
- def _build_rt_key (
189
- cls ,
190
- home_account_id = None , environment = None , client_id = None , target = None ,
191
- ** ignored_payload_from_a_real_token ):
192
- return "-" .join ([
193
- home_account_id or "" ,
194
- environment or "" ,
195
- cls .CredentialType .REFRESH_TOKEN ,
196
- client_id or "" ,
197
- "" , # RT is cross-tenant in AAD
198
- target or "" , # raw value could be None if deserialized from other SDK
199
- ]).lower ()
200
-
201
215
def remove_rt (self , rt_item ):
202
216
assert rt_item .get ("credential_type" ) == self .CredentialType .REFRESH_TOKEN
203
217
return self .modify (self .CredentialType .REFRESH_TOKEN , rt_item )
@@ -207,50 +221,14 @@ def update_rt(self, rt_item, new_rt):
207
221
return self .modify (
208
222
self .CredentialType .REFRESH_TOKEN , rt_item , {"secret" : new_rt })
209
223
210
- @classmethod
211
- def _build_at_key (cls ,
212
- home_account_id = None , environment = None , client_id = None ,
213
- realm = None , target = None , ** ignored_payload_from_a_real_token ):
214
- return "-" .join ([
215
- home_account_id or "" ,
216
- environment or "" ,
217
- cls .CredentialType .ACCESS_TOKEN ,
218
- client_id ,
219
- realm or "" ,
220
- target or "" ,
221
- ]).lower ()
222
-
223
224
def remove_at (self , at_item ):
224
225
assert at_item .get ("credential_type" ) == self .CredentialType .ACCESS_TOKEN
225
226
return self .modify (self .CredentialType .ACCESS_TOKEN , at_item )
226
227
227
- @classmethod
228
- def _build_idt_key (cls ,
229
- home_account_id = None , environment = None , client_id = None , realm = None ,
230
- ** ignored_payload_from_a_real_token ):
231
- return "-" .join ([
232
- home_account_id or "" ,
233
- environment or "" ,
234
- cls .CredentialType .ID_TOKEN ,
235
- client_id or "" ,
236
- realm or "" ,
237
- "" # Albeit irrelevant, schema requires an empty scope here
238
- ]).lower ()
239
-
240
228
def remove_idt (self , idt_item ):
241
229
assert idt_item .get ("credential_type" ) == self .CredentialType .ID_TOKEN
242
230
return self .modify (self .CredentialType .ID_TOKEN , idt_item )
243
231
244
- @classmethod
245
- def _build_account_key (cls ,
246
- home_account_id = None , environment = None , realm = None ,
247
- ** ignored_payload_from_a_real_entry ):
248
- return "-" .join ([
249
- home_account_id or "" ,
250
- environment or "" ,
251
- realm or "" ,
252
- ]).lower ()
253
-
254
232
def remove_account (self , account_item ):
255
233
assert "authority_type" in account_item
256
234
return self .modify (self .CredentialType .ACCOUNT , account_item )
0 commit comments