aiokwikset 0.2.1__tar.gz → 0.2.2a1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of aiokwikset might be problematic. Click here for more details.
- {aiokwikset-0.2.1 → aiokwikset-0.2.2a1}/PKG-INFO +1 -1
- {aiokwikset-0.2.1 → aiokwikset-0.2.2a1}/aiokwikset/api.py +35 -8
- {aiokwikset-0.2.1 → aiokwikset-0.2.2a1}/aiokwikset/aws_kwikset.py +41 -29
- aiokwikset-0.2.2a1/aiokwikset/errors.py +19 -0
- {aiokwikset-0.2.1 → aiokwikset-0.2.2a1}/aiokwikset/exceptions.py +2 -0
- {aiokwikset-0.2.1 → aiokwikset-0.2.2a1}/aiokwikset.egg-info/PKG-INFO +1 -1
- {aiokwikset-0.2.1 → aiokwikset-0.2.2a1}/setup.py +1 -1
- aiokwikset-0.2.1/aiokwikset/errors.py +0 -13
- {aiokwikset-0.2.1 → aiokwikset-0.2.2a1}/LICENSE +0 -0
- {aiokwikset-0.2.1 → aiokwikset-0.2.2a1}/README.md +0 -0
- {aiokwikset-0.2.1 → aiokwikset-0.2.2a1}/aiokwikset/__init__.py +0 -0
- {aiokwikset-0.2.1 → aiokwikset-0.2.2a1}/aiokwikset/client.py +0 -0
- {aiokwikset-0.2.1 → aiokwikset-0.2.2a1}/aiokwikset/const.py +0 -0
- {aiokwikset-0.2.1 → aiokwikset-0.2.2a1}/aiokwikset/device.py +0 -0
- {aiokwikset-0.2.1 → aiokwikset-0.2.2a1}/aiokwikset/user.py +0 -0
- {aiokwikset-0.2.1 → aiokwikset-0.2.2a1}/aiokwikset.egg-info/SOURCES.txt +0 -0
- {aiokwikset-0.2.1 → aiokwikset-0.2.2a1}/aiokwikset.egg-info/dependency_links.txt +0 -0
- {aiokwikset-0.2.1 → aiokwikset-0.2.2a1}/aiokwikset.egg-info/requires.txt +0 -0
- {aiokwikset-0.2.1 → aiokwikset-0.2.2a1}/aiokwikset.egg-info/top_level.txt +0 -0
- {aiokwikset-0.2.1 → aiokwikset-0.2.2a1}/aiokwikset.egg-info/zip-safe +0 -0
- {aiokwikset-0.2.1 → aiokwikset-0.2.2a1}/setup.cfg +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import aioboto3
|
|
3
|
+
import botocore.exceptions
|
|
3
4
|
import attr
|
|
4
5
|
import datetime
|
|
5
6
|
|
|
@@ -17,7 +18,7 @@ from aiohttp.client_exceptions import (
|
|
|
17
18
|
ClientPayloadError
|
|
18
19
|
)
|
|
19
20
|
|
|
20
|
-
from .errors import RequestError
|
|
21
|
+
from .errors import RequestError, NotAuthorized
|
|
21
22
|
from .device import Device
|
|
22
23
|
from .user import User
|
|
23
24
|
from .exceptions import TokenVerificationException
|
|
@@ -169,7 +170,7 @@ class API(object):
|
|
|
169
170
|
if not self.access_token:
|
|
170
171
|
raise AttributeError('Access Token Required to Check Token')
|
|
171
172
|
now = datetime.datetime.now()
|
|
172
|
-
dec_access_token = jwt.get_unverified_claims(self.
|
|
173
|
+
dec_access_token = jwt.get_unverified_claims(self.id_token)
|
|
173
174
|
|
|
174
175
|
if now > datetime.datetime.fromtimestamp(dec_access_token['exp']):
|
|
175
176
|
expired = True
|
|
@@ -185,12 +186,13 @@ class API(object):
|
|
|
185
186
|
"""
|
|
186
187
|
auth_params = {'SECRET_HASH': '', 'REFRESH_TOKEN': self.refresh_token}
|
|
187
188
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
189
|
+
try:
|
|
190
|
+
async with self.get_client() as client:
|
|
191
|
+
refresh_response = await client.initiate_auth(
|
|
192
|
+
ClientId=self.client_id,
|
|
193
|
+
AuthFlow='REFRESH_TOKEN_AUTH',
|
|
194
|
+
AuthParameters=auth_params,
|
|
195
|
+
)
|
|
194
196
|
|
|
195
197
|
self._set_attributes(
|
|
196
198
|
refresh_response,
|
|
@@ -209,6 +211,11 @@ class API(object):
|
|
|
209
211
|
|
|
210
212
|
if not self.user:
|
|
211
213
|
self.user = User(self._request)
|
|
214
|
+
|
|
215
|
+
#attempt to catch the NotAuthorizedException
|
|
216
|
+
except botocore.exceptions.ClientError as err:
|
|
217
|
+
if err.response['Error']['Code'] == 'NotAuthorizedException':
|
|
218
|
+
raise NotAuthorized("Refresh Token has been revoked.")
|
|
212
219
|
|
|
213
220
|
def _set_attributes(self, response, attribute_dict):
|
|
214
221
|
"""
|
|
@@ -239,6 +246,26 @@ class API(object):
|
|
|
239
246
|
self.code_type = code_type
|
|
240
247
|
|
|
241
248
|
pre_verification = await self.aws.authenticate_user()
|
|
249
|
+
|
|
250
|
+
if pre_verification.get('AuthenticationResult'):
|
|
251
|
+
print("2-step verification disabled")
|
|
252
|
+
await self.verify_token(pre_verification['AuthenticationResult']['IdToken'],
|
|
253
|
+
'id_token', 'id')
|
|
254
|
+
self.refresh_token = pre_verification['AuthenticationResult']['RefreshToken']
|
|
255
|
+
await self.verify_token(pre_verification['AuthenticationResult']['AccessToken'],
|
|
256
|
+
'access_token', 'access')
|
|
257
|
+
self.token_type = pre_verification['AuthenticationResult']['TokenType']
|
|
258
|
+
|
|
259
|
+
if not self.device:
|
|
260
|
+
self.device = Device(self._request)
|
|
261
|
+
|
|
262
|
+
if not self.user:
|
|
263
|
+
self.user = User(self._request)
|
|
264
|
+
|
|
265
|
+
return
|
|
266
|
+
|
|
267
|
+
print("2-step verification enabled")
|
|
268
|
+
|
|
242
269
|
return pre_verification
|
|
243
270
|
|
|
244
271
|
async def verify_user(self, pre_verification, code):
|
|
@@ -6,9 +6,12 @@ import hmac
|
|
|
6
6
|
import re
|
|
7
7
|
|
|
8
8
|
import aioboto3
|
|
9
|
+
import botocore.exceptions
|
|
9
10
|
import os
|
|
10
11
|
import six
|
|
11
12
|
|
|
13
|
+
from .errors import NotAuthorized
|
|
14
|
+
|
|
12
15
|
# https://github.com/aws/amazon-cognito-identity-js/blob/master/src/AuthenticationHelper.js#L22
|
|
13
16
|
n_hex = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1' + \
|
|
14
17
|
'29024E088A67CC74020BBEA63B139B22514A08798E3404DD' + \
|
|
@@ -240,35 +243,44 @@ class AWSKWIKSET(object):
|
|
|
240
243
|
boto_client = self.client or client
|
|
241
244
|
auth_params = self.get_auth_params()
|
|
242
245
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
ChallengeName=self.PASSWORD_VERIFIER_CHALLENGE,
|
|
256
|
-
Session=response['Session'],
|
|
257
|
-
ChallengeResponses=challenge_response)
|
|
258
|
-
|
|
259
|
-
if custom_challenge['ChallengeName'] == self.CUSTOM_VERIFIER_CHALLENGE:
|
|
260
|
-
custom_challenge_response = self.process_custom_challenge()
|
|
261
|
-
|
|
262
|
-
custom_challenge_code = await client.respond_to_auth_challenge(
|
|
246
|
+
try:
|
|
247
|
+
async with boto_client as client:
|
|
248
|
+
response = await client.initiate_auth(
|
|
249
|
+
AuthFlow='CUSTOM_AUTH',
|
|
250
|
+
AuthParameters=auth_params,
|
|
251
|
+
ClientId=self.client_id
|
|
252
|
+
)
|
|
253
|
+
if response['ChallengeName'] == self.PASSWORD_VERIFIER_CHALLENGE:
|
|
254
|
+
challenge_response = self.process_challenge(
|
|
255
|
+
response['ChallengeParameters'])
|
|
256
|
+
|
|
257
|
+
custom_challenge = await client.respond_to_auth_challenge(
|
|
263
258
|
ClientId=self.client_id,
|
|
264
|
-
ChallengeName=self.
|
|
265
|
-
Session=
|
|
266
|
-
ChallengeResponses=
|
|
267
|
-
|
|
268
|
-
|
|
259
|
+
ChallengeName=self.PASSWORD_VERIFIER_CHALLENGE,
|
|
260
|
+
Session=response['Session'],
|
|
261
|
+
ChallengeResponses=challenge_response)
|
|
262
|
+
|
|
263
|
+
#2-step verification is disabled
|
|
264
|
+
if custom_challenge.get('AuthenticationResult'):
|
|
265
|
+
return custom_challenge
|
|
266
|
+
|
|
267
|
+
#2-step verification is enabled
|
|
268
|
+
if custom_challenge['ChallengeName'] == self.CUSTOM_VERIFIER_CHALLENGE:
|
|
269
|
+
custom_challenge_response = self.process_custom_challenge()
|
|
270
|
+
|
|
271
|
+
custom_challenge_code = await client.respond_to_auth_challenge(
|
|
272
|
+
ClientId=self.client_id,
|
|
273
|
+
ChallengeName=self.CUSTOM_VERIFIER_CHALLENGE,
|
|
274
|
+
Session=custom_challenge['Session'],
|
|
275
|
+
ChallengeResponses=custom_challenge_response)
|
|
276
|
+
|
|
277
|
+
return custom_challenge_code
|
|
278
|
+
else:
|
|
279
|
+
raise NotImplementedError('The %s challenge is not supported'
|
|
280
|
+
% response['ChallengeName'])
|
|
269
281
|
else:
|
|
270
282
|
raise NotImplementedError('The %s challenge is not supported'
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
283
|
+
% response['ChallengeName'])
|
|
284
|
+
except botocore.exceptions.ClientError as err:
|
|
285
|
+
if err.response['Error']['Code'] == 'NotAuthorizedException':
|
|
286
|
+
raise NotAuthorized("Refresh Token has been revoked")
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Define package errors."""
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
class KwiksetError(Exception):
|
|
5
|
+
"""Define a base error."""
|
|
6
|
+
|
|
7
|
+
pass
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class RequestError(KwiksetError):
|
|
11
|
+
"""Define an error related to invalid requests."""
|
|
12
|
+
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
class NotAuthorized(Exception):
|
|
16
|
+
"""Raised when the refresh token has been revoked"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, *args: Any) -> None:
|
|
19
|
+
Exception.__init__(self, *args)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|