def validate_params(self): params = self.event['request']['userAttributes'] if UserUtil.check_try_to_register_as_line_user(self.event['userName']) or \ UserUtil.check_try_to_register_as_twitter_user(self.event['userName']) or \ UserUtil.check_try_to_register_as_yahoo_user(self.event['userName']) or \ UserUtil.check_try_to_register_as_facebook_user(self.event['userName']): raise ValidationError("external provider's user can not execute") if params.get('phone_number', '') != '' and \ params.get('phone_number_verified', '') != 'true' and \ self.event['triggerSource'] != 'CustomMessage_ForgotPassword': validate(params, self.get_schema()) client = boto3.client('cognito-idp') response = client.list_users( UserPoolId=self.event['userPoolId'], Filter='phone_number = "%s"' % params['phone_number'], ) for user in response['Users']: for attribute in user['Attributes']: if attribute[ 'Name'] == 'phone_number_verified' and attribute[ 'Value'] == 'true': raise ValidationError( 'This phone_number is already exists') # セキュリティ観点より、電話番号変更を実行させない。 # これにより XSS が発生したとしても、電話番号認証が必要な処理は回避が可能 if self.event['triggerSource'] == 'CustomMessage_VerifyUserAttribute': # phone_number_verified が true の場合は電話番号変更を行っていないため当チェックは不要 if params.get('phone_number_verified', '') != 'true': self.__validate_has_not_token(params) # サードパーティを利用したユーザの場合、パスワード変更を実行させない if self.event['triggerSource'] == 'CustomMessage_ForgotPassword': # サードパーティを利用したユーザかを確認 if UserUtil.is_external_provider_user(self.dynamodb, self.event['userName']): raise ValidationError( "external provider's user can not execute")
def validate_params(self): params = self.event if params['userName'] in settings.ng_user_name: raise ValidationError('This username is not allowed') validate(params, self.get_schema()) if params['triggerSource'] == 'PreSignUp_SignUp': # 通常サインアップユーザーにTwitter・LINE・Yahoo・Facebookから始まる名前を許可しないバリデーション if params['request']['validationData'] is None or \ params['request']['validationData'].get('EXTERNAL_PROVIDER_LOGIN_MARK') != \ os.environ['EXTERNAL_PROVIDER_LOGIN_MARK']: if UserUtil.check_try_to_register_as_twitter_user( params['userName']): raise ValidationError('This username is not allowed') if UserUtil.check_try_to_register_as_line_user( params['userName']): raise ValidationError('This username is not allowed') if UserUtil.check_try_to_register_as_yahoo_user( params['userName']): raise ValidationError('This username is not allowed') if UserUtil.check_try_to_register_as_facebook_user( params['userName']): raise ValidationError('This username is not allowed') response = self.__filter_users(self.cognito, params) self.__email_exist_check(response) elif params['triggerSource'] == 'PreSignUp_AdminCreateUser': if (params['request'].get('validationData') is not None) and \ params['request']['validationData'].get('EXTERNAL_PROVIDER_LOGIN_MARK') == \ os.environ['EXTERNAL_PROVIDER_LOGIN_MARK']: response = self.__filter_users(self.cognito, params) self.__email_exist_check(response) else: raise NotAuthorizedError('Forbidden') # 現状CognitoTriggerは'PreSignUp_SignUp','PreSignUp_AdminCreateUser'の2種類のみなので異なるTriggerがリクエストされた場合は例外にする else: raise Exception
def get_schema(self): params = self.event # TwitterのIDは30文字以下なので条件分岐を作成していない if params.get('triggerSource') == 'PreSignUp_AdminCreateUser' and \ UserUtil.check_try_to_register_as_line_user(params['userName']): return { 'type': 'object', 'properties': { 'userName': settings.parameters['line_id'] } } elif params.get('triggerSource') == 'PreSignUp_AdminCreateUser' and \ UserUtil.check_try_to_register_as_yahoo_user( params['userName']): return { 'type': 'object', 'properties': { 'userName': settings.parameters['yahoo_id'] } } elif params.get('triggerSource') == 'PreSignUp_AdminCreateUser' and \ UserUtil.check_try_to_register_as_facebook_user( params['userName']): return { 'type': 'object', 'properties': { 'userName': settings.parameters['facebook_id'] } } else: return { 'type': 'object', 'properties': { 'userName': settings.parameters['user_id'] } }
def test_check_try_to_register_as_yahoo_user_ok(self): self.assertFalse( UserUtil.check_try_to_register_as_yahoo_user('myuser')) self.assertFalse( UserUtil.check_try_to_register_as_yahoo_user( 'myuser-Yahoo-xxxxxxx'))
def test_check_try_to_register_as_yahoo_user_ng(self): self.assertTrue( UserUtil.check_try_to_register_as_yahoo_user('Yahoo-xxxxxxx'))
def exec_main_proc(self): params = self.event body = json.loads(params.get('body')) if UserUtil.check_try_to_register_as_line_user(body['user_id']) or \ UserUtil.check_try_to_register_as_twitter_user(body['user_id']) or \ UserUtil.check_try_to_register_as_yahoo_user(body['user_id']) or \ UserUtil.check_try_to_register_as_facebook_user(body['user_id']): raise ValidationError('This username is not allowed') users_table = self.dynamodb.Table(os.environ['USERS_TABLE_NAME']) external_provider_users_table = self.dynamodb.Table( os.environ['EXTERNAL_PROVIDER_USERS_TABLE_NAME']) external_provider_user_id = params['requestContext']['authorizer'][ 'claims']['cognito:username'] exist_check_user = users_table.get_item(Key={ 'user_id': body['user_id'] }).get('Item') external_provider_user = external_provider_users_table.get_item( Key={ 'external_provider_user_id': external_provider_user_id }).get('Item') if (external_provider_user is not None) and ('user_id' in external_provider_user): raise ValidationError('The user id of this user has been added.') elif exist_check_user is None: # EXTERNAL_PROVIDERのidで作成したcognitoのユーザーを除去 if UserUtil.delete_external_provider_id_cognito_user( self.cognito, external_provider_user_id): # user_idでのCognitoユーザーの作成し直し try: email = external_provider_user['email'] hash_data = external_provider_user['password'] byte_hash_data = hash_data.encode() decoded_iv = external_provider_user['iv'] iv = decoded_iv.encode() backed_password = CryptoUtil.decrypt_password( byte_hash_data, iv) backed_temp_password = os.environ[ 'EXTERNAL_PROVIDER_LOGIN_COMMON_TEMP_PASSWORD'] provider = os.environ['EXTERNAL_PROVIDER_LOGIN_MARK'] response = UserUtil.create_external_provider_user( cognito=self.cognito, user_id=body['user_id'], user_pool_id=os.environ['COGNITO_USER_POOL_ID'], user_pool_app_id=os. environ['COGNITO_USER_POOL_APP_ID'], email=email, backed_temp_password=backed_temp_password, backed_password=backed_password, provider=provider) UserUtil.force_non_verified_phone(cognito=self.cognito, user_id=body['user_id']) UserUtil.wallet_initialization( self.cognito, os.environ['COGNITO_USER_POOL_ID'], body['user_id']) # ExternalProviderUsersテーブルにuser_idを追加 UserUtil.add_user_id_to_external_provider_user( body['user_id'], external_provider_users_table, external_provider_user_id) # Usersテーブルにユーザーを作成 UserUtil.add_user_profile( dynamodb=self.dynamodb, user_id=body['user_id'], user_display_name=body['user_id']) has_user_id = UserUtil.has_user_id( self.dynamodb, external_provider_user_id) return { 'statusCode': 200, 'body': json.dumps({ 'access_token': response['AuthenticationResult']['AccessToken'], 'last_auth_user': body['user_id'], 'id_token': response['AuthenticationResult']['IdToken'], 'refresh_token': response['AuthenticationResult']['RefreshToken'], 'status': 'login', 'has_user_id': has_user_id }) } except ClientError as e: logging.fatal(e) return { 'statusCode': 500, 'body': json.dumps({'message': 'Internal server error'}) } return { 'statusCode': 500, 'body': json.dumps({'message': 'Internal server error'}) } else: raise ValidationError('This id is already in use.')