Flask session does't work - react & flask app - python

I'm working on an app with flask backend and react front,
I want to save the username in a session and display it in the front post-login.
here is the current process:
configurations at the head of app.py (flask-server main file)
app = Flask(__name__)
app.config["JWT_SECRET_KEY"] = "key"
app.config["SECRET_KEY"] = "pass"
app.config["JWT_ACCESS_TOKEN_EXPIRES"] = timedelta(hours=1)
app.config["SESSION_TYPE"] = 'filesystem'
app.config["SESSION_PERMANENT"] = False
# app.config.from_object(__name__)
CORS(app)
Session(app)
jwt = JWTManager(app)
Login button with handler:
const data = {
username: loginForm.username,
password: loginForm.password
}
fetch("http://localhost:5000/token", {
method: "POST",
body: JSON.stringify(data)
})
.then((response) => {...
the route for "/token" - if the credentials are ok it renders my user homepage, and it works fine.
#app.route('/token', methods=["POST"])
def create_token():
username = json.loads(request.data)["username"]
password = json.loads(request.data)["password"]
sql_string = f"""select username, password from admins where username='{username}'"""
result = sql_call(sql_string) //this is a helper functino in db_connector file
if(result):
session["username"] = username
access_token = create_access_token(identity=username) //another helper function
response = app.response_class(response=json.dumps({"access_token": access_token}),
status=200,
mimetype='application/json')
response.headers.add('Access-Control-Allow-Origin', '*')
return response
on the app main page i have a span of "Hello " that tries to fetch the username from the session, sending request to route "/username":
#app.route("/username")
def getUsername():
username = session["username"]
response = jsonify({"username": "admin"})
return response
But it finds no key "username" in the session, and also the SID in 4 and SID in 3 are different.
how can I retrieve this data back?
my flask runs on port 5000 and react on port 3000,
thanks

In step 4 use this to get username
session.get("username")

Ok, I didn't manage to fix it,
session.get("username" also didn't work)
I noticed that the server is working fine when sending requests from postman, so the problem might be in React.
I used the get_jtw()
over the session and it works well :)

Related

Access Token From Spotify API is the Same One For Each User

So during testing, I was able to sign in with 1 spotify account at the login page and receive a correct access code and token. However, when I run and close the app, and run it again, I went on an incognito tab (with no cookies) and was able to successfully sign into a new Spotify account through the same login page (which sends you to authenticate through spotify). But, for some reason, the spotify API sent me the same access code and token as the first user.
Thanks for your help!
import spotipy
from spotipy.oauth2 import SpotifyOAuth
from flask import Flask, request, url_for, session, redirect, render_template
import time
from os import urandom
# App Initialization
app = Flask(__name__)
# Setup Cookies
app.secret_key = urandom(64)
app.config['SESSION_COOKIE_NAME'] = 'A Session Cookie'
TOKEN_INFO = "token_info"
#app.route('/login')
def login():
sp_oauth = create_spotify_oauth()
auth_url = sp_oauth.get_authorize_url()
return redirect(auth_url)
#app.route('/redirect')
def redirectPage():
sp_oauth = create_spotify_oauth()
session.clear()
code = request.args.get('code')
token_info = sp_oauth.get_access_token(code)
# print(token_info)
session[TOKEN_INFO] = token_info
return redirect(url_for('profile', _external=True))
# Universal Functions
def create_spotify_oauth():
return SpotifyOAuth(
client_id = 'INSERT CLIENT ID',
client_secret = 'INSERT CLIENT SECRET',
redirect_uri=url_for('redirectPage', _external=True),
scope='user-library-read user-read-recently-played user-read-playback-position playlist-read-collaborative user-read-playback-state user-top-read playlist-modify-public user-read-currently-playing user-library-read playlist-read-private playlist-modify-private',
)
def get_token():
token_info = session.get(TOKEN_INFO, None)
if not token_info:
raise "exception"
now = int(time.time())
is_expired = token_info['expires_at'] - now < 60
if is_expired:
sp_oauth = create_spotify_oauth()
token_info = sp_oauth.refresh_access_token(token_info['refresh_token'])
return token_info
app.run()
Essentially, the function "get_access_token()" returns an access token if it can find any on your system through environment variables, so this isn't even an issue for my application. It's working as intended.

401 UNAUTHORIZED status when attempting login from client side to backend flask api

I am trying to login from my website developed in Angular to the back end flask API, The backend uses bcrypt for encoding and pymongo for interacting with a MongoDB. In postman, the login endpoint works fine but when an attempt to log in on the client side is made I receive a 401: UNAUTHORIZED ERROR. Can someone advise what the issue is/where I am going wrong?
The login function on the client side:
onLogin() {
let postData = new FormData();
postData.append('username', this.loginForm.get('username').value);
postData.append('password', this.loginForm.get('password').value);
this.http.post('http://localhost:5000/api/v1.0/login', postData)
.subscribe((_response: any) => {
console.log(this.loginForm.value);
this.loginForm.reset();
})
}
The login endpoint in backend:
app = Flask(__name__)
CORS(app)
#app.route('/api/v1.0/login', methods=['POST'])
def login():
auth = request.authorization
if auth:
user = users.find_one({'username': auth.username})
if user is not None:
if bcrypt.checkpw(bytes(auth.password, 'utf-8'),
user["password"]):
token = jwt.encode( \
{'user' : auth.username,
'admin': user["admin"],
'exp' : datetime.datetime.utcnow() + \
datetime.timedelta(minutes=30)
}, app.config['SECRET_KEY'])
return make_response(jsonify( \
{'token':token.decode('UTF-8')}), 200)
else:
return make_response(jsonify( \
{'message':'Bad password'}), 401)
else:
return make_response(jsonify( \
{'message':'Bad username'}), 401)
In order to use request.authorization you need to send the credentials in the Authorization-header. Try this on the client:
onLogin() {
const usn = this.loginForm.get('username').value;
const pwd = this.loginForm.get('password').value;
this.http.post('http://localhost:5000/api/v1.0/login', null, {
headers: new HttpHeaders({
Authorization: `Basic ${btoa(`${usn}:${pwd}`)}`
})
}).subscribe((_response: any) => {
console.log(_response);
});
}
As a sidenote; the credentials can be easily decoded by using atob(), so make sure you are using a secure connection (HTTPS) when not on localhost.

Flask Sessions - Session isn't always removed on logout (Works sometimes)

I have a javascript fetch call to an api (on a different domain) and I'm passing along credentials. On the other Python Flask API, I have CORS and 'Access-Control-Allow-Credentials' set to true on all requests.
Python Webservice
app = Flask(__name__)
app.secret_key = os.getenv('SESSION_SECRET')
app.config.from_object(__name__)
CORS(app)
#app.after_request
def add_header(response):
response.headers['Access-Control-Allow-Credentials'] = 'true'
return response
#app.route('/login', methods=['POST'])
#captcha_check
def login():
data = request.get_json(force=True) # Force body to be read as JSON
email = data.get('email')
password = data.get('password')
# Authenticate users account and password
if auth.verify_password(email, password):
# Password is correct, return temporary session ID
username_query = db.get_username_by_email(email)
if username_query['found']:
session['email'] = email
return jsonify({'status': 200, 'email': email}), 200
else:
return jsonify({'status': 404, 'error': 'user-email-not-found'}), 404
else:
# Incorrect password specified, return Unauthorized Code
return jsonify({'status': 401, 'error': 'incorrect-password'}), 401
#app.route('/logout', methods=['POST'])
def logout():
print(session, file=sys.stdout)
session.clear()
print(session.pop('email', None), file=sys.stdout)
return jsonify({'status': 200}), 200
Javascript fetch call
async function signInPost(data) {
const response = await fetch(serverAddress + '/login', {
method: 'POST',
credentials: 'include',
headers: {
'Access-Control-Allow-Origin': 'http://localhost:5000',
'Access-Control-Allow-Credentials': 'true'
},
body: JSON.stringify(data)
});
// Wait for response from server, then parse the body of the response in json format
return await response.json();
}
async function signOutPost() {
const response = await fetch(serverAddress + '/logout', {
method: 'POST',
headers: {
'Access-Control-Allow-Origin': 'http://localhost:5000',
'Access-Control-Allow-Credentials': 'true'
},
credentials: 'include'
});
return await response.json();
}
I know the cookie is being set with login becuase I have other endpoints that check the status of the cookie to see if a person is signed in or not. What I'm confused about is why this doesn't always invalidate the cookie. On chrome the network syas the status of the first api call is "(cancled)", but then sometimes if I click it one or two more times it will eventually sign out. On Firefox and Safari it will esentially never sign me out.
Flask is getting the api calls and returning a 200 status, but the browsers are not respecting what is being returned.
My current assumption is that it has something to do with the OPTIONS method that get's called in advance blocking the request, but I'm not sure how to get around this.
Why dont you pass in your config.py file something like this
CORS_SUPPORTS_CREDENTIALS = True
instead of passing in the requests?

trying to forward request with chalice

im trying to build a simple api+lambda with chalice which can receive a POST request and then forward it to another API while adding some authentication. when i run my chalice code locally i can send a request and print the payload which i sent inside chalice console yet i cannot forward my request. i don't get back any errors or other print statements which i have in my code. i don't know where else to look for more answers so im asking here.
from chalice import Chalice
import requests
app = Chalice(app_name='redirect_url')
app.debug = True
TOKEN_URL = "https://redirect.com/v0/token"
USERNAME = 'email#email.com'
PASSWORD = 'Password01021'
#app.route('/redirect_url', methods=['POST'])
def get_payload():
update_payload = app.current_request.json_body
print(update_payload)
def fetch_auth_token():
username = USERNAME
password = PASSWORD
data = {
"grant_type": "password",
"username": username,
"password": password
}
response = requests.post(TOKEN_URL, data=data)
token = response.json()
print(token)
IF I send a request to the endpoint (http://127.0.0.1:8000/redirect_url) I see my request printed inside chalice logs, but i don't see the token request.
I would appreciate any help
This is a bit old, but I thought I would answer it for the community for those new to Chalice.
You are expecting to fire the function without calling it. It should be:
from chalice import Chalice
import requests
app = Chalice(app_name='redirect_url')
app.debug = True
TOKEN_URL = "https://redirect.com/v0/token"
USERNAME = 'email#email.com'
PASSWORD = 'Password01021'
#app.route('/redirect_url', methods=['POST'])
def get_payload():
update_payload = app.current_request.json_body
APIresponse = fetch_auth_token()
print(APIresponse) ## If you want to show it right before the update_payload
print(update_payload)
def fetch_auth_token():
username = USERNAME
password = PASSWORD
data = {
"grant_type": "password",
"username": username,
"password": password
}
response = requests.post(TOKEN_URL, data=data)
return response.json()

App Engine Python not receiving GET parameter value from Django page

I'm trying to send a GET request to a App Engine server from a page built with Django. I set the parameters in Django part, but in App Engine the parameter value is empty.
I've logged its value in Django side, and the parameters values are ok.
Here is my Django code:
try:
username = request.session['username']
params = urllib.urlencode('user', username)
headers = {"Content-type":"application/x-www-form-urlencoded", "Accept":"text/plain"}
conn = httplib.HTTPConnection(connections_strings.auth)
conn.request("GET", connections_strings.auth, params, headers)
response = conn.getresponse()
jsonString = response.read()
return render_to_response('home/index.html', locals(), context_instance=RequestContext(request))
And here is the App Engine code:
def get(self):
username = self.request.get('user') # Get the username parameter
query_user = UserEntity.all()
query_user.filter('username = ', username)
user_data = []
for user in query_user:
record = { //Create the JSON.. }
user_data.append(record)
self.response.headers['Content-Type'] = 'application/json'
self.response.out.write(simplejson.dumps(user_data))
The get(self) method in App Engine is being called, I've put a log message there and it has been printed.
So, what is happening is that in the App Engine side, self.request.get('user') returns nothing. And it's weird, I've made GET request from mobile side, and it works perfectly with this same method.
Any idea??
Thanks!
In a HTTP GET method, the query parameters are passed in the URL:
http://example.com?user=foo
The request() method is defined like this:
HTTPConnection.request(method, url[, body[, headers]])
So by doing this:
conn.request("GET", connections_strings.auth, params, headers)
you've sent the params in the request body instead.
Try this instead:
selector = '{}?{}'.format(connections_strings.auth, params)
conn.request("GET", selector, headers=headers)

Categories

Resources