def get_authorization_url(self, dynamodb): try: nonce = NonceUtil.generate( dynamodb=dynamodb, expiration_minites=settings.YAHOO_NONCE_EXPIRATION_MINUTES, provider='yahoo', type='nonce', length=settings.YAHOO_NONCE_LENGTH) state = NonceUtil.generate( dynamodb=dynamodb, expiration_minites=settings.YAHOO_NONCE_EXPIRATION_MINUTES, provider='yahoo', type='state', length=settings.YAHOO_NONCE_LENGTH) except (ClientError) as e: raise e authorization_endpoint = \ self.endpoints['authorization_endpoint'] + \ '?response_type=code' + \ '&client_id=' + self.client_id + \ '&scope=' + settings.YAHOO_LOGIN_REQUEST_SCOPE + \ '&redirect_uri=' + self.callback_url + \ '&nonce='+nonce+'&state='+state return authorization_endpoint
def test_generate_ng(self): with self.assertRaises(ClientError): self.dynamodb.Table = MagicMock() self.dynamodb.Table.return_value.put_item.side_effect = ClientError( {'Error': { 'Code': 'xxxx' }}, 'operation_name') NonceUtil.generate(dynamodb=self.dynamodb, expiration_minites=15, provider='yahoo', type='nonce', length=10)
def test_generate_ok(self): nonce = NonceUtil.generate(dynamodb=self.dynamodb, expiration_minites=15, provider='yahoo', type='nonce', length=10) table = self.dynamodb.Table(os.environ['NONCE_TABLE_NAME']) result = table.get_item(Key={'nonce': nonce}).get('Item') self.assertEqual(len(result), 4)
def verify_state_nonce(self, dynamodb, state): nonce_checked = NonceUtil.verify(dynamodb=dynamodb, nonce=state, provider='yahoo', type='state') if nonce_checked is False: raise YahooVerifyException(state + ' was invalid since it may be expired') return True
def verify_access_token(self, dynamodb, access_token, id_token): # 以下のコメントはhttps://developer.yahoo.co.jp/yconnect/v2/id_token.htmlの検証手順番号 try: start_time = time.time() header = jwt.get_unverified_header(id_token) response = requests.get(settings.YAHOO_API_PUBLIC_KEY_URL) if response.status_code is not 200: raise YahooOauthError( endpoint=settings.YAHOO_API_PUBLIC_KEY_URL, status_code=response.status_code, message=response.text) public_keys = json.loads(response.text) # 6,7,8の検証 decoded_data = jwt.decode(id_token, key=public_keys.get( header['kid']).encode('utf-8'), issuer=self.endpoints['issuer'], audience=self.client_id, algorithms='RS256') nonce_checked = NonceUtil.verify(dynamodb=dynamodb, nonce=decoded_data['nonce'], provider='yahoo', type='nonce') # 9の検証 if nonce_checked is False: raise YahooVerifyException( 'id token was invalid since nonce was invalid') # 10の検証 token_hash = hashlib.sha256(access_token.encode('utf-8')).digest() at_hash = base64.urlsafe_b64encode( token_hash[:int(len(token_hash) / 2)]) if decoded_data['at_hash'] != at_hash.decode().rstrip('='): print(at_hash.decode().rstrip('=')) raise YahooVerifyException( 'accesstoken was invalid since at_hash did not match') # 12の検証 if start_time >= decoded_data['exp']: raise YahooVerifyException( 'id token was invalid since start_time was less than exp') except (jwt.ExpiredSignatureError, jwt.InvalidTokenError, ClientError, YahooVerifyException) as e: raise e return True
def test_verify_ng_with_do_not_match_type(self): table = self.dynamodb.Table(os.environ['NONCE_TABLE_NAME']) param = { 'nonce': 'xxxx', 'provider': 'test', 'type': 'test', 'expiration_time': 1232432234322 } table.put_item(Item=param, ConditionExpression='attribute_not_exists(nonce)') result = NonceUtil.verify(dynamodb=self.dynamodb, nonce='xxxx', provider='test', type='test1') self.assertFalse(result)
def get_authorization_url(self, dynamodb): try: state = NonceUtil.generate( dynamodb=dynamodb, expiration_minites=settings.FACEBOOK_NONCE_EXPIRATION_MINUTES, provider='facebook', type='state', length=settings.FACEBOOK_NONCE_LENGTH) except (ClientError) as e: raise e authorization_endpoint = \ settings.FACEBOOK_API_AUTHENTICATE_URL + \ '?client_id=' + self.app_id + \ '&redirect_uri=' + self.callback_url + \ '&scope=' + settings.FACEBOOK_LOGIN_REQUEST_SCOPE + \ '&state='+state return authorization_endpoint