def decorated_function(*args, **kwargs): # get refresh_token from request body request_data = request.get_json() # enforce refresh_token was sent from client if request_data and request_data.get("refresh_token"): try: refresh_token = request_data.get("refresh_token") user_id = get_id_from_jwt(refresh_token, environ.get("REFRESH_TOKEN_SECRET")) if revoked_tokens_cache.get(refresh_token[112:]) == b'revoked': msg = "ERROR 401: Invalid refresh token." return make_json_response(status=401, msg=msg) current_user = User.query.filter_by(id=user_id).first() if current_user.refresh_token: kwargs["current_user"] = current_user return f(*args, **kwargs) raise Exception("No refresh token assoctated with this user") # enforce refresh_token was valid, expired or malfourmend tokens # will cause exceptions to be trhown from get_id_from_jwt except Exception as e: print(e) msg = "ERROR 401: Invalid refresh token." return make_json_response(status=401, msg=msg) else: msg = ("ERROR 400: Must include 'refresh_token' field in request ", "body.") return make_json_response(status=400, msg=msg)
def decorated_function(*args, **kwargs): # get access_token from request body access_token = request.headers.get("Authorization") # enforce access_token was sent from client if access_token and access_token.startswith("Bearer"): access_token = access_token.split(" ")[1] try: user_id = get_id_from_jwt(access_token, environ.get("ACCESS_TOKEN_SECRET")) if revoked_tokens_cache.get(access_token[112:]) == b'revoked': msg = "ERROR 401: Invalid refresh token." return make_json_response(status=401, msg=msg) kwargs["user_id"] = user_id return f(*args, **kwargs) # enforce access_token was valid, expired or malformend tokens # will cause exceptions to be trhown from get_id_from_jwt except Exception: msg = ("ERROR 401: Invalid access token. Ensure token is in the" " request's 'Authorization' header in the form:" " 'Bearer token_here'") return make_json_response(status=401, msg=msg) else: msg = ("ERROR 401: Invalid access token. Ensure token is in the" " request's 'Authorization' header in the form:" " 'Bearer token_here'") return make_json_response(status=401, msg=msg)
def setup_otp(user_id): ''' Responds with the user's otp_secret in a otp uri. ''' user = User.query.filter_by(id=user_id).first() user.set_otp_secret() db.session.commit() response = {"otp_uri": user.get_totp_uri()} msg = "OK 200: OTP URI Provided." return make_json_response(status=200, msg=msg, response_dict=response)
def refresh(current_user): ''' Returns a fresh access token given a valid refresh token. ''' exp = int(environ.get("ACCESS_TOKEN_EXP_SEC")) access_token = create_jwt_for_user(current_user.id, environ.get("ACCESS_TOKEN_SECRET"), sec=exp) tokens = {"access_token": access_token} msg = "OK 200: Access token refreshed succesfully." return make_json_response(status=200, msg=msg, response_dict=tokens)
def decorated_function(*args, **kwargs): request_data = request.get_json() valid_request = request_data and request_data.get("email") valid_request = valid_request and request_data.get("password") if valid_request: return f(*args, **kwargs) else: msg = ("ERROR 400: Must include 'email' and 'password' ", "fields in request body.") return make_json_response(status=400, msg=msg)
def login(): ''' Authenticates a client and responds with access and refresh tokens. ''' # pull user from db request_data = request.get_json() user = User.query.filter_by(email=request_data["email"]).first() # authenticate user and return access token if user and user.check_pw_hash(request_data["password"]): request_data = request.get_json() valid_request = request_data and request_data.get("totp") if user.otp_secret and valid_request: if not user.verify_totp(request_data.get("totp")): msg = "ERROR 401: Authentication failed." return make_json_response(status=401, msg=msg) exp = int(environ.get("ACCESS_TOKEN_EXP_SEC")) access_token = create_jwt_for_user(user.id, environ.get("ACCESS_TOKEN_SECRET"), sec=exp) exp = int(environ.get("REFRESH_TOKEN_EXP_DAYS")) refresh_token = create_jwt_for_user( user.id, environ.get("REFRESH_TOKEN_SECRET"), days=exp) # save user's refresh token user.refresh_token = refresh_token db.session.commit() tokens = {"access_token": access_token, "refresh_token": refresh_token} msg = "OK 200: Authentication successful" return make_json_response(status=200, msg=msg, response_dict=tokens) # user does not exist or entered bad credentials msg = "ERROR 401: Authentication failed." return make_json_response(status=401, msg=msg)
def register(): ''' Creates a new user in the db. ''' request_data = request.get_json() email = request_data["email"] user = User(email=email) user.set_pw_hash(request_data["password"]) db.session.add(user) db.session.commit() msg = "OK 201: Registration successful" return make_json_response(status=201, msg=msg)
def logout(current_user): ''' Deletes a user's refresh token from the db and adds it to the revoked cache. ''' # get access_token from request body to revoke it access_token = request.headers.get("Authorization") if access_token and access_token.startswith("Bearer"): access_token = access_token.split(" ")[1] try: # Will verify the token is valid. If it isnt, for example it's expired, then # an exception will be thrown and we'll skip revoking it. get_id_from_jwt(access_token, environ.get("ACCESS_TOKEN_SECRET")) revoke_token(access_token, environ.get("ACCESS_TOKEN_SECRET")) except Exception as e: print(e) revoke_token(current_user.refresh_token, environ.get("REFRESH_TOKEN_SECRET")) current_user.refresh_token = None db.session.commit() msg = "OK 200: Tokens revoked succesfully." return make_json_response(status=200, msg=msg)
def error_404(error): ''' Handels 404 error Page Not Found. ''' msg = ("ERROR 404: Page not found.") return make_json_response(status=404, msg=msg)
def error_500(error): ''' Handels 500 error Internal Error. ''' msg = ("ERROR 500: An error occured on the server.") return make_json_response(status=500, msg=msg)
def error_405(error): ''' Handels 405 error Method not allowed. ''' msg = ("ERROR 405: Method not allowed.") return make_json_response(status=405, msg=msg)