When I did all of the listed items below AND had this code for my CORS configuration in my app.py:
CORS(app, supports_credentials=True, origins=[
"http://localhost:3000",
"http://thecasecomp.com"
])
Seems like I needed my online domain as well for both to work.
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at ‘https://453c-162-199-93-254.ngrok-free.app/@me’. (Reason: Credential is not supported if the CORS header ‘Access-Control-Allow-Origin’ is ‘*’)
All my requests to my backend work when I use the direct localhost 5000 backend address. However, I need to use ngrok to create a public address that accesses my localhost (because I want to host the backend on my computer). The ngrok address is accessible on a different network and returns user: Unauthorized
.
When I use the ngrok address (e.g., https://453c-162-199-93-254.ngrok-free.app) in the axios request, it sends the error above.
I've tried using axios.get directly on the front end instead of using an instance of it (axios.create from httpClient). I assume I need to use withCredentials because I have a registration and login (unless there's another way?). I also tried adding axios.defaults.withCredentials = true
before creating the instance.
I've tried adding origins when doing CORS(app, origins=[http://localhost:3000])
.
I've tried adding @cross_origins(origins=[...])
as well.
I've tried bypassing the ngrok browser warning, and that led to the error disappearing. However, my GET request from /@me was still not working, even after apparently logging in. After using axios directly with the withCredentials option, the error returned (see below).
const resp = await axios.get(`${backendLink}/@me`, withCredentials: true,});
I've tried defining a proxy ("proxy": "https://fe10-162-199-93-254.ngrok-free.app"
) and added more configuration (see below).
app.config["SESSION_COOKIE_SAMESITE"]="None"
app.config["SESSION_COOKIE_SECURE"]=True
from flask import Flask, request, abort, jsonify, session
from flask_bcrypt import Bcrypt
from flask_session import Session
from flask_cors import CORS, cross_origin
from config import ApplicationConfig
from models import db, User
app = Flask(__name__)
app.config.from_object(ApplicationConfig)
bcrypt = Bcrypt(app)
CORS(app, supports_credentials=True, origins=[
"http://localhost:3000",
"http://localhost:5000",
"https://453c-162-199-93-254.ngrok-free.app",
])
server_session = Session(app)
db.init_app(app)
with app.app_context():
db.create_all()
@app.route("/@me")
def get_current_user():
user_id = session.get("user_id")
if not user_id:
return jsonify({"error": "User unauthorized."}), 401
user = User.query.filter_by(id = user_id).first()
if user is None:
return jsonify({"error": "User not found."}), 404
return jsonify({
"id": user.id,
"email": user.email,
"first_name": user.first_name,
"last_name": user.last_name,
"phone_number": user.phone_number,
"grade": user.grade,
"school": user.school
})
@app.route("/registration", methods=["POST"])
def register_user():
email = request.json["email"]
password = request.json["password"]
first_name = request.json["firstName"]
last_name = request.json["lastName"]
phone_number = request.json["phone"]
grade = request.json["grade"]
school = request.json["school"]
user_exists = User.query.filter_by(email = email).first() is not None
if user_exists:
return jsonify({"error": "User already exists."}), 409
hashed_password = bcrypt.generate_password_hash(password)
new_user = User(email = email, password = hashed_password, first_name = first_name, last_name = last_name, phone_number = phone_number, grade = grade, school = school)
db.session.add(new_user)
db.session.commit()
session["user_id"] = new_user.id
return jsonify({
"id": new_user.id,
"email": new_user.email,
"first_name": new_user.first_name,
"last_name": new_user.last_name,
"phone_number": new_user.phone_number,
"grade": new_user.grade,
"school": new_user.school
})
@app.route("/remove-user", methods=["POST"])
def remove_user():
user_id = request.json["user_id"]
if not user_id:
return jsonify({"error": "User ID not found."}), 404
user = User.query.filter_by(id=user_id).first()
if user:
db.session.delete(user)
db.session.commit()
return jsonify({"message": "User removed successfully."}), 200
@app.route("/login", methods=["POST"])
def login_user():
email = request.json["email"]
password = request.json["password"]
user = User.query.filter_by(email = email).first()
if user is None:
return jsonify({"error": "User unauthorized."}), 401
if not bcrypt.check_password_hash(user.password, password):
return jsonify({"error": "User unauthorized."}), 401
session["user_id"] = user.id
return jsonify({
"id": user.id,
"email": user.email,
})
@app.route("/logout", methods=["POST"])
def logout_user():
session.pop("user_id")
return "200"
if __name__ == "__main__":
app.run(debug = True)
import axios from "axios";
axios.defaults.withCredentials = true;
export default axios.create({
withCredentials: true,
});
import "./App.css";
import "./styles/Fonts.css";
import Navbar from "./components/Navbar.js";
import Footer from "./components/Footer.js";
import Home from "./pages/Home";
import Timeline from "./pages/Timeline";
import Registration from "./pages/Registration";
import Submission from "./pages/Submission";
import Contact from "./pages/Contact";
import About from "./pages/About";
import Login from "./pages/Login";
import Profile from "./pages/Profile";
import React, { useState, useEffect } from "react";
import httpClient from "./util/httpClient.js";
import styled from "styled-components";
import { HashRouter as Router, Route, Routes } from "react-router-dom";
import backendLink from "./util/backendLink.js";
import axios from "axios";
axios.defaults.withCredentials = true;
const AppStyle = styled.div`
text-align: center;
font-family: "Regular";
`;
function App() {
const [user, setUser] = useState(null);
useEffect(() => {
(async () => {
try {
const resp = await httpClient.get(`${backendLink}/@me`, {
withCredentials: true,
});
setUser(resp.data);
} catch (error) {
console.log("Unauthenticated");
}
})();
}, []);
return (
<AppStyle>
<Router>
<Navbar />
<Routes>
<Route path="/" exact element={<Home />} />
<Route path="/timeline" exact element={<Timeline />} />
<Route path="/registration" exact element={<Registration />} />
<Route path="/submission" exact element={<Submission />} />
<Route path="/contact" exact element={<Contact />} />
<Route path="/about" exact element={<About />} />
<Route path="/login" exact element={<Login />} />
{user != null ? (
<Route path={`/profile/${user.id}`} exact element={<Profile />} />
) : (
<></>
)}
{/* TODO: add 404 not found page, fix fade out animation for alerts */}
</Routes>
<Footer />
</Router>
</AppStyle>
);
}
export default App;
from dotenv import load_dotenv
import os
import redis
load_dotenv()
class ApplicationConfig:
SECRET_KEY = os.environ["SECRET_KEY"]
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_ECHO = True
SQLALCHEMY_DATABASE_URI = r"sqlite:///./db.sqlite"
SESSION_TYPE = "redis"
SESSION_PERMANENT = False
SESSION_USE_SIGNER = True
SESSION_REDIS = redis.from_url("redis://127.0.0.1:6379")
SESSION_COOKIE_SAMESITE = "None"
SESSION_COOKIE_SECURE = True
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at ‘https://fe10-162-199-93-254.ngrok-free.app/@me’. (Reason: Credential is not supported if the CORS header ‘Access-Control-Allow-Origin’ is ‘*’).
When I did all of the listed items below AND had this code for my CORS configuration in my app.py:
CORS(app, supports_credentials=True, origins=[
"http://localhost:3000",
"http://thecasecomp.com"
])
Seems like I needed my online domain as well for both to work.