def login(event, context): event_log = deepcopy(event) try: event_log["body"].pop("password") except KeyError: pass logger.debug('event: {}'.format(event_log)) try: body = get_body(event) except json.JSONDecodeError: return { 'statusCode': 400, 'body': json.dumps({'error': 'Bad parameter(s) in request'}) } if not all([k in body for k in ['username', 'password']]) or \ not all([body[k] for k in ['username', 'password']]): return { 'statusCode': 400, 'body': json.dumps({'error': 'Both username and password are required.'}) } # Authenticate and get tokens req = requests.post(os.environ['AUTH0_DOMAIN'] + '/oauth/token', json={ 'grant_type': 'password', 'username': body['username'], 'password': body['password'], 'audience': os.environ['AUTH0_AUDIENCE'], 'client_id': os.environ['AUTH0_CLIENT_ID'], 'client_secret': os.environ['AUTH0_CLIENT_SECRET'], 'scope': 'openid' }) body = req.json() # extract payload for jwt token if 'id_token' in body: _id_token = body['id_token'] payload = jwt_decode(_id_token, AUTH0_CLIENT_PUBLIC_KEY) else: if 'error_description' in body: return { 'statusCode': 400, 'body': json.dumps({'error': body['error_description']}) } else: return { 'statusCode': 500, 'body': json.dumps({'error': 'Unknown Error happened'}) } # get Auth0 user profile object (in order to get app_metadata) resp = requests.post(os.environ['AUTH0_DOMAIN'] + '/oauth/token', json={ 'grant_type': 'client_credentials', 'client_id': os.environ['AUTH0_MANAGEMENT_API_CLIENT_ID'], 'client_secret': os.environ['AUTH0_MANAGEMENT_API_CLIENT_SECRET'], 'audience': os.environ['AUTH0_AUDIENCE'], 'scope': 'read:users' }, headers={'content-type': "application/json"}) users_token_body = resp.json() if 'access_token' in users_token_body: _access_token = users_token_body['access_token'] _auth0_user_id = payload['sub'] resp = requests.get( os.environ['AUTH0_DOMAIN'] + '/api/v2/users/{ID}'.format(ID=_auth0_user_id), headers={ 'content-type': "application/json", 'Authorization': 'Bearer {ACCESS_TOKEN}'.format(ACCESS_TOKEN=_access_token) }) users_body = resp.json() if "app_metadata" not in users_body: app_metadata = {} else: app_metadata = users_body["app_metadata"] # update app_metadata in users object # While developing, dynamodb local is used. So if `DYANMODB_LOCAL_ENDPOINT` is present in env vars # dynamodb boto client is patched to use local db email = payload['email'] user_id = payload['sub'][6:] try: repo = DynamoRepository( region_name=os.environ['REGION'], user_id=user_id, email=email, dynamodb_local_endpoint=os.environ['DYNAMO_ENDPOINT']) except KeyError: repo = DynamoRepository(region_name=os.environ['REGION'], user_id=user_id, email=email) try: repo.update_user_app_metadata(app_metadata) except NoSuchEntity: return { 'statusCode': 404, 'body': json.dumps({'error': 'User not found'}) } else: if 'error_description' in users_token_body: return { 'statusCode': 400, 'body': json.dumps({'error': body['error_description']}) } else: return { 'statusCode': 500, 'body': json.dumps({'error': 'Unknown Error happened'}) } if all(k in body for k in ['access_token', 'id_token', 'scope', 'expires_in', 'token_type']): return {'statusCode': 200, 'body': json.dumps(body)} elif 'error_description' in body: return { 'statusCode': 400, 'body': json.dumps({'error': body['error_description']}) } else: return { 'statusCode': 500, 'body': json.dumps({'error': 'Unknown Error happened'}) }
def login(event, context): event_log = deepcopy(event) try: event_log["body"].pop("password") except KeyError: pass logger.debug('event: {}'.format(event_log)) try: body = get_body(event) except json.JSONDecodeError: logger.error("bad JSON payload") return { 'statusCode': 400, 'body': json.dumps({'error': 'Bad parameter(s) in request'}) } except: logger.log_uncaught_exception() if not all([k in body for k in ['username', 'password']]) or \ not all([body[k] for k in ['username', 'password']]): logger.error("username, and/or password is missing in JSON") return { 'statusCode': 400, 'body': json.dumps({'error': 'Both username and password are required.'}) } # Authenticate and get tokens req = requests.post(os.environ['AUTH0_DOMAIN'] + '/oauth/token', json={ 'grant_type': 'password', 'username': body['username'], 'password': body['password'], 'audience': os.environ['AUTH0_AUDIENCE'], 'client_id': os.environ['AUTH0_CLIENT_ID'], 'client_secret': os.environ['AUTH0_CLIENT_SECRET'], 'scope': 'openid' }) body = req.json() # extract payload for jwt token if 'id_token' in body: _id_token = body['id_token'] payload = jwt_decode(_id_token, AUTH0_CLIENT_PUBLIC_KEY) else: logger.error( "oAuth token is not returned by Auth0 for POST {AUTH0_DOMAIN}/oauth/token. " "Please check if AUTH0_DOMAIN, AUTH0_AUDIENCE, AUTH0_CLIENT_ID, AUTH0_CLIENT_SECRET and " "AUTH0_CLIENT_PUBLIC_KEY are set correctly") if 'error_description' in body: logger.error(body['error_description']) return { 'statusCode': 400, 'body': json.dumps({'error': body['error_description']}) } else: logger.error("No error message returned from Auth0") return { 'statusCode': 500, 'body': json.dumps({'error': 'Unknown Error happened'}) } # get Auth0 user profile object (in order to get app_metadata) resp = requests.post(os.environ['AUTH0_DOMAIN'] + '/oauth/token', json={ 'grant_type': 'client_credentials', 'client_id': os.environ['AUTH0_MANAGEMENT_API_CLIENT_ID'], 'client_secret': os.environ['AUTH0_MANAGEMENT_API_CLIENT_SECRET'], 'audience': os.environ['AUTH0_AUDIENCE'], 'scope': 'read:users' }, headers={'content-type': "application/json"}) users_token_body = resp.json() if 'access_token' in users_token_body: _access_token = users_token_body['access_token'] _auth0_user_id = payload['sub'] resp = requests.get( os.environ['AUTH0_DOMAIN'] + '/api/v2/users/{ID}'.format(ID=_auth0_user_id), headers={ 'content-type': "application/json", 'Authorization': 'Bearer {ACCESS_TOKEN}'.format(ACCESS_TOKEN=_access_token) }) users_body = resp.json() if "app_metadata" not in users_body: app_metadata = {} else: app_metadata = users_body["app_metadata"] if 'error_description' in users_body: logger.error( "Failed: GET %AUTH0_DOMAIN%/api/v2/users/%ID% for AUTH0_DOMAIN={AUTH0_DOMAIN}, ID={ID}" .format(AUTH0_DOMAIN=os.environ['AUTH0_DOMAIN'], ID=_auth0_user_id)) logger.error(body['error_description']) # update app_metadata in users object # While developing, dynamodb local is used. So if `DYANMODB_LOCAL_ENDPOINT` is present in env vars # dynamodb boto client is patched to use local db email = payload['email'] user_id = payload['sub'][6:] try: repo = DynamoRepository( region_name=os.environ['REGION'], table='sp-{STAGE}'.format(STAGE=os.environ['STAGE']), user_id=user_id, email=email, dynamodb_local_endpoint=os.environ['DYNAMO_ENDPOINT']) except KeyError: repo = DynamoRepository( region_name=os.environ['REGION'], table='sp-{STAGE}'.format(STAGE=os.environ['STAGE']), user_id=user_id, email=email) except: logger.log_uncaught_exception() try: repo.update_user_app_metadata(app_metadata) except NoSuchEntity: return { 'statusCode': 404, 'body': json.dumps({'error': 'User not found'}) } except: logger.log_uncaught_exception() else: logger.error( "oAuth access_token is not returned by Auth0 for POST {AUTH0_DOMAIN}/oauth/token. " "Please check if AUTH0_DOMAIN, AUTH0_AUDIENCE, AUTH0_MANAGEMENT_API_CLIENT_ID, and " "AUTH0_MANAGEMENT_API_CLIENT_SECRET are set correctly. " "Please also check if scope 'read:users' is set in the management app" ) if 'error_description' in users_token_body: logger.error(users_token_body['error_description']) return { 'statusCode': 400, 'body': json.dumps({'error': users_token_body['error_description']}) } else: logger.error("No error message returned from Auth0") return { 'statusCode': 500, 'body': json.dumps({'error': 'Unknown Error happened'}) } if all(k in body for k in ['access_token', 'id_token', 'scope', 'expires_in', 'token_type']): return {'statusCode': 200, 'body': json.dumps(body)} elif 'error_description' in body: logger.error( "POST /oauth/token did not return all of 'access_token, id_token, scope, expires_in, token_type'" ) logger.error(body['error_description']) return { 'statusCode': 400, 'body': json.dumps({'error': body['error_description']}) } else: logger.error( "POST /oauth/token did not return all of 'access_token, id_token, scope, expires_in, token_type'" ) logger.error("No error message returned from Auth0") return { 'statusCode': 500, 'body': json.dumps({'error': 'Unknown Error happened'}) }