0

I am trying to connect my react frontend to my flask api backend. Note that flask-cors is already installed.

I initiated CORS as CORS(app) . the login passes but I keep getting this error when I go to project route:

Access to fetch at 'http://192.168.101.4:5000/project' from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.

My init.py file:

from flask import Flask, request, make_response

from .extensions import db, migrate, jwt, mail, CORS

from .models import TokenBlocklist

from .routes.base import base
from .routes.auth import auth
from .routes.core import core
from .routes.admin import admin
from .routes.user import user
from .routes.project import project


def create_app(config_file='config.py'):
    app = Flask(__name__)

    app.config.from_pyfile(config_file)
    
    @jwt.token_in_blocklist_loader
    def check_if_token_revoked(jtw_header, jwt_payload: dict)->bool:
        jti = jwt_payload['jti']
        token = db.session.query(TokenBlocklist.id).filter_by(jti=jti).scalar()

        return token is not None

    # initiate
    db.init_app(app)
    migrate.init_app(app, db)
    jwt.init_app(app)
    mail.init_app(app)
    CORS(app)

    app.register_blueprint(base)
    app.register_blueprint(auth, url_prefix='/auth')
    app.register_blueprint(core, url_prefix='/core')
    app.register_blueprint(admin, url_prefix='/admin')
    app.register_blueprint(user, url_prefix='/user')
    app.register_blueprint(project, url_prefix='/project')

    return app

my auth.py:

"""
Route: endpoints for authentication
"""

from flask import Blueprint, jsonify, request, current_app, url_for, make_response
import datetime
import uuid
import validators
from itsdangerous import URLSafeTimedSerializer

from flask_jwt_extended import create_access_token, create_refresh_token, get_jwt_identity, jwt_required, unset_jwt_cookies, get_jwt, set_access_cookies, set_refresh_cookies
from werkzeug.security import generate_password_hash

from flask_cors import CORS

from ..utils import send_mail
from ..extensions import db, status, jwt
from ..models import User, TokenBlocklist

auth = Blueprint('auth', __name__)

CORS(auth)

@auth.route('/confirm-email/<token>')
def confirm_email(token):
    s = URLSafeTimedSerializer(current_app.config['SECRET_KEY'])
    try:
        email = s.loads(token, salt='email-confirm', max_age=200)
        
        # mark user mail as confirmed
        user = User.query.filter_by(email=email).first()
        
        if not user.is_confirmed:
            user.is_confirmed = True
            db.session.commit()
        return jsonify(msg='email confirmed'), status.ok
    except:
        return jsonify(msg = False), status.bad
    

@auth.route('/register', methods=['POST'])
def register():
    """
    recieve request->username, email, password
    check username & email exists or not, if not hash password and store.
    send email with confirmation link
    """
    data = request.get_json()
    username = data['username']
    email = data['email']
    password = data['password']

    # check existance of requirements in request json
    if not username or not email or not password:
        return jsonify(msg='missing json data'), status.bad
    
    # email validations
    if not validators.email(email):
        return jsonify(msg='invalid email address'), 
    
    # check if username and email is taken
    user = User.query.filter_by(username=username).first()
    if user:
        return jsonify(msg='username already taken')
    
    user = User.query.filter_by(email=email).first()
    if user:
        return jsonify(msg='email already taken')

    # save new user in db
    new_user = User(
        username = username,
        email = email,
        password = generate_password_hash(password, 'sha256'), # probably not a good practice to use User
        public_id = uuid.uuid4()
    )
    try:
        db.session.add(new_user)
        db.session.commit()
    except:
        return jsonify(msg='could not save')
    
    # create email confirmation link
    token = URLSafeTimedSerializer(current_app.config['SECRET_KEY'])
    token = token.dumps(email, salt='email-confirm')
    link = url_for('auth.confirm_email', token=token, _external=True)

    # send mail
    body = f'confirmation link: {link}'
    
    mail_sent = send_mail(recipient=email, body=body, subject='Linkage Email Confirmation')

    if not mail_sent:
        return jsonify(msg= 'email could not be sent')

    return jsonify(msg= 'mail sent' ,email=email, token=token), 201


@auth.route('/login', methods=['POST'])
def login():
    """
    recieve json data->email, password
    check if email exists,
        check user's hashed password and if email is confirmed.
        generate refresh and access token and return
    """
    data = request.get_json()
    email = data['email']
    password = data['password']

    user = User.query.filter_by(email=email).first()

    # email not found
    if not user:
        return make_response(
            'User not found',
            401,
            {'WWW-Authenticate' : 'Basic realm ="could not verify"'}
        )
    
    # email found
    verified = user.verify_password(password)
    if verified is False:
        return make_response(
            'password mismatch',
            401,
            {'WWW-Authenticate' : 'Basic realm ="could not verify"'}
        )
    
    # authenticated, now generate tokens
    user_public_id = user.public_id
    refresh_token = create_refresh_token(identity=user_public_id)
    access_token = create_access_token(identity=user_public_id)

    # i am totally not sure about the following, but the fe dev *insists*
    response = jsonify({"x-access-token": access_token})
    response.set_cookie("refresh_token_cookie", refresh_token)

    
    return response, 200

And Finally my project.py:

from datetime import datetime

from flask import Blueprint, jsonify, request, make_response
from flask_jwt_extended import get_jwt_identity, jwt_required

from ..extensions import db
from ..models import Project

project = Blueprint('project', __name__)



# this route must be deleted before production
@project.route('/', methods=['GET'])
@jwt_required()
def all_projects():
    user_public_id = get_jwt_identity()
    projects = Project.query.filter_by(user_public_id=user_public_id).all()
    projects_data = []

    for project in projects:
        project_data = {}
        project_data['id'] = project.id
        project_data['domain'] = project.domain
        project_data['name'] = project.name
        project_data['user_public_id'] = project.user_public_id
        project_data['wp_password'] = project.wp_password
        project_data['wp_username'] = project.wp_username
        project_data['date_added'] = project.date_added
        projects_data.append(project_data)

    return jsonify(projects = projects_data), 20
    

CORS related configs in my config.py file:

#CORS
CORS_ALLOW_HEADERS = ['Content-Type', 'Authorization']
CORS_SUPPORTS_CREDENTIALS = True
CORS_HEADERS = ['Content-Type', 'Authorization']

I am totally lost here. I don't know where is the redirect is happening. Thank you for your time.

  • See if suggestions in [this](https://stackoverflow.com/questions/42168773/how-to-resolve-preflight-is-invalid-redirect-or-redirect-is-not-allowed-for) resolves your issue? – user11666461 Jan 11 '23 at 10:02

0 Answers0