Esempio n. 1
0
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'})
        }
Esempio n. 2
0
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'})
        }