Dropbox auth is not working on Python - python

I'm trying to build an app using Python ( Flask ) and DropBox API. I'm trying to authorize an user, so I followed up the tutorial for python.
from flask import Flask, render_template, url_for
from dropbox import client, rest, session
# Dropbox Settings
APP_KEY = 'gb83a6gpdo4kba6'
APP_SECRET = 'w5q0yhj9ikiw39g'
ACCESS_TYPE = 'app_folder'
# Flask Config
DEBUG = True
app = Flask(__name__)
app.config.from_object(__name__)
#app.route("/")
def home():
dropboxAccount = dropboxAccessToken = dropboxClient = None
# Dropbox Auth
dropboxSession = session.DropboxSession(app.config['APP_KEY'], app.config['APP_SECRET'], app.config['ACCESS_TYPE'])
requestToken = dropboxSession.obtain_request_token()
try:
dropboxAccessToken = dropboxSession.obtain_access_token(requestToken)
dropboxClient = dropboxClient.DropboxClient(dropboxSession)
dropboxAccount = dropboxClient.account_info()
except Exception, e:
print e
dropboxAuthUrl = dropboxSession.build_authorize_url(requestToken, oauth_callback = "http://localhost:5000/")
context = {
'dropboxAuthUrl' : dropboxAuthUrl,
'dropboxAccount' : dropboxAccount
}
return render_template('layout.html', context = context)
if __name__ == "__main__":
app.run()
But, authorization isn't working. Trying from my localhost, the user clicks on the link generated by this line:
dropboxSession.build_authorize_url(requestToken, oauth_callback = "http://localhost:5000/")
And, go to DropBox authorization page, displaying app info and options to allow or refuse. When I click in "Allow" button, it redirects me back, and when I check my account apps, the new app isn't listed there. The callback url looks like this:
http://localhost:5000/dropbox/?uid={some_uid}&oauth_token={some_token}
Anyone knows whats is going on?
Thanks in advance!

Just solved. I didn't notice that I was reseting request_token on every request.

Related

Flask 404 error when initializing a connection with a react applicaiont

import os, re
from flask import Flask, send_from_directory, json,request
from flask_socketio import SocketIO
from flask_cors import CORS
from flask_sqlalchemy import SQLAlchemy
import random
app = Flask(__name__, static_folder='./build/static')
# Point SQLAlchemy to your Heroku database
uri = os.getenv("DATABASE_URL") # or other relevant config var
if uri and uri.startswith("postgres://"):
uri = uri.replace("postgres://", "postgresql://", 1)
app.config['SQLALCHEMY_DATABASE_URI'] = uri
# Gets rid of a warning
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
import models
cors = CORS(app, resources={r"/*": {"origins": "*"}})
socketio = SocketIO(
app,
cors_allowed_origins="*",
json=json,
manage_session=False
)
#app.route('/', defaults={"filename": "index.html"})
#app.route('/<path:filename>')
def index(filename):
return send_from_directory('./build', filename)
# When a client connects from this Socket connection, this function is run
#socketio.on('connect')
def on_connect():
print('User connected!')
# When a client disconnects from this Socket connection, this function is run
#socketio.on('disconnect')
def on_disconnect():
print('User disconnected!')
#socketio.on('index')
def on_index():
all_students = db.Students.query.all()
random1 = random.randint(0,models.Students.query().count())
random2 = random.randint(0,models.Students.query().count())
total_table = []
for student in all_students:
total_table.append(student)
firstStudent = []
secondStudent = []
while(random2 == random1):
random2 = random.randint(0,models.Students.query().count())
firstStudent.append(total_table[random1])
secondStudent.append(total_table[random2])
twoStudents = [firstStudent,secondStudent]
socketio.emit('students', {twoStudents:twoStudents})
# Note we need to add this line so we can import app in the python shell
if __name__ == "__main__":
# Note that we don't call app.run anymore. We call socketio.run with app arg
socketio.run(
app,
)
The react end of the application launches fine with no errors, and the database has no issues. I've used this skeleton for the base of a bunch of other projects and i've never had any issues. But for some reason i'm stuck at a brick wall setting this up. I know the issue is within the #app.route('/') part of the code. i've tried hard coding the html file into the url path, but that just causes other errors like missing 1 required positional argument: 'filename' flask. Any help is greatly appreciated
I tested your configuration and it doesn't give me any errors. Nevertheless I offer you an alternative solution.
You can provide the entire react build folder as a static folder. You can then deliver the "index.html" as a single file in the root route. The prerequisite is that the prefix for the static url path is empty.
# ...
app = Flask(__name__,
static_url_path='',
static_folder='./build'
)
# ...
#app.route('/')
def index():
return app.send_static_file('index.html')
# ...

Use secret key to secure flask API - python

Is it possible to use a secret key to secure just an API without a website or webpage?
I made an app that uses flask and when I test it from the client app, it works. However I want to secure the get request from the client to the server by using a secret key or token if possible.
The problem is that most examples I have seen assumed you are using this for a website with login credentials. I don't have any webpages or any routes in my flask app.
Here is the server side:
from flask import Flask, stream_with_context, request, Response
from flask_restful import Api, Resource
from flask_socketio import SocketIO
import intermedia_choose_action_flask
import subprocess
from io import StringIO
import sys
import sqlite_companysearch
import time
app = Flask(__name__)
api = Api(app)
SECRET_KEY = "a long set of strings I got from running a command in linux terminal"
app.secret_key = SECRET_KEY
class addspamblacklistspecific(Resource):
def get(self, emailordomain):
count = 0
sqlite_companysearch.comp_searchall_intermedia()
selection_cid = sqlite_companysearch.comp_searchall_intermedia.cid_selection_results
for cid in selection_cid:
subprocess.Popen(["python3", "/home/tech/scripts/Intermedia_automate/intermedia_choose_action.py", "--addblockspecific", "--cp", cid, "--ed", emailordomain], bufsize=10, errors='replace')
count = count + 1
if count == 3:
time.sleep(60)
count = 0
return "command completed succesfully"
api.add_resource(addspamblacklistspecific, "/addspamblacklistspecific/<string:emailordomain>")
if __name__ == "__main__":
app.run(debug=True)
Here is the client side:
from flask import json
import requests
#where do I put in a secret key?
def email_or_domain_selection():
email_or_domain_selection.email_select = input("""Enter an email or domain.
(NOTE: domains must have a "*" symbol infront of the name. For example *company.com)
Enter Email or Domain :""")
eselect = email_or_domain_selection.email_select
return email_or_domain_selection.email_select
email_or_domain_selection()
BASE = "http://127.0.0.1:5000/"
response = requests.get(BASE + "addspamblacklistspecific/"+email_or_domain_selection.email_select)
print(response.text)
I figure I should learn this before learning how to put my app in the cloud.
Thank you for your time,
Edit - I was told to read this: demystify Flask app.secret_key which I already did. That is for if you have webpages. I don't have any webpages and am just trying to secure an API only. It doesn't explain how or if I should be using session information for just calling an api from a client side. It doesn't explain how to use a secret key on the client side.
You could look into flask-httpauth. I used this a while back on one of my projects to add a layer of security to some API's running on flask. Keep in mind that this is only a basic authentication (base-64 encoded strings).
from flask import Flask, jsonify, request
from flask_restful import Resource, Api
from flask_httpauth import HTTPBasicAuth
# import credentials from env (suggested)
API_UNAME = "username"
API_PASS = "password"
USER_DATA = {API_UNAME: API_PASS}
# initialize flask/flask-restful instance
app = Flask(__name__)
api = Api(app)
auth = HTTPBasicAuth()
class API_Class(Resource):
#auth.login_required
def post(self):
# do api stuff
return jsonify("result")
# verify API authentication
#auth.verify_password
def verify(username, password):
if not (username and password):
return False
return USER_DATA.get(username) == password
api.add_resource(API_Class, "/post")
You might want to look into other methods like OAuth for extra security.

How to use Python 3 imports properly in Google Cloud Functions

I am making a simple function to check a URL status and redirect on 404. This app works fine in Flask localhost but when I move this to Google Cloud Functions, I keep getting "Error: could not handle the request". This is when my parameters on both the Cloud Function and the localhost are the exact same.
Am I doing something wrong with importing 'redirect' from Flask?
GCLOUD CODE: NOT WORKING
from flask import Flask, redirect
from flask import request
import requests
def urlincoming():
custID = request.args['custID']
token = request.args['token']
custEmail = request.args['custEmail']
storeDomain = request.args['domain']
adminEmail = request.args['adminEmail']
baseUrl = f"{storeDomain}/account/reset/{custID}/{token}"
baseUrlFailedAuth = f"{storeDomain}/account/invalid_token"
requestBaseUrl = requests.head(baseUrl)
if(requestBaseUrl.status_code == 200):
return redirect(baseUrl)
else:
return redirect(baseUrlFailedAuth)
LOCALHOST CODE: WORKING
from flask import Flask, redirect
from flask import request
import requests
app = Flask(__name__)
#app.route('/urlincoming')
def urlincoming():
custID = request.args['custID']
token = request.args['token']
custEmail = request.args['custEmail']
storeDomain = request.args['domain']
adminEmail = request.args['adminEmail']
baseUrl = f"{storeDomain}/account/reset/{custID}/{token}"
baseUrlFailedAuth = f"{storeDomain}/account/invalid_token"
requestBaseUrl = requests.head(baseUrl)
if(requestBaseUrl.status_code == 200):
return redirect(baseUrl)
else:
return redirect(baseUrlFailedAuth)
All Google Cloud Functions need to have one of the following two signatures:
HTTP Functions:
function_name(request):
...
Background functions:
function_name(data, context):
...
Depending on the type of function you're creating, you either need to add the request or data, context arguments.
from flask import redirect
import requests
def urlincoming(request):
I was able to fix things by adding the request as a argument but I'm not sure why it worked :/

Flask_dance with Google API; Missing required parameter: refresh_token

I trid to make authorization system with flask_dance and Google.
I was successful in authorize first but after a while, the program caused this error even though I didn't change it at all.
My whole code is here (It's almost the same as the tutorial one though
from flask import Flask, redirect, url_for
from flask_dance.contrib.google import make_google_blueprint, google
app = Flask(__name__)
app.secret_key = "supersekrit"
blueprint = make_google_blueprint(
client_id="",
client_secret="",
scope=["profile", "email"]
)
app.register_blueprint(blueprint, url_prefix="/login")
#app.route("/")
def index():
if not google.authorized:
return redirect(url_for("google.login"))
resp = google.get("/oauth2/v2/userinfo")
assert resp.ok, resp.text
return "You are {email} on Google".format(email=resp.json()["email"])
if __name__ == "__main__":
app.run()
How can I fix this error?
This problem seems to be the one referenced in this Github issue. The suggested solution is to request offline access:
google_blueprint = make_google_blueprint(
client_id='',
client_secret='',
scope=['profile', 'email'],
offline=True
)

Python's Requests on IIS with Flask | Connection Error

I've been working to get Flask applications up running on my IIS server and have made some progress thanks to the below link:
http://netdot.co/2015/03/09/flask-on-iis
With that stated, I am running into a head scratcher when attempting to use the "requests" python module when I deploy over IIS. The application works fine when I launch it locally -- that is, I get a proper <200> response when requesting the JSON data if I launch the app via terminal
> python app.py.
Essentially, the application requests JSON data from my Stash repository via their API. Stash's API requires user authentication for this get request. The requests module made it easy to do... I'm avoiding raw HTML as much as possible (web noob... >.<;).
I am getting the following error exception in Python when deployment is on IIS and not sure why:
ConnectionError: ('Connection aborted.', error(13, 'Permission denied'))
You can reference the entire code below (confidential stuff omitted).
Basically, I have a login.html page that takes user credentials.
Then, I use those credentials to send the get request
try:
reqLib = requests.get('https://stash/rest/api/latest/projects/PLAN/repos/sqlquerylibrary/files?at=refs%2Fheads%2Fmaster&limit=100000', auth=(usr, pwd), verify=False)
except Exception as e:
return str(e)
Entire App:
import requests
from flask import Flask, render_template, redirect, url_for, request, send_from_directory
from flask_login import LoginManager, UserMixin, login_required, login_user
import sys
import os
app = Flask(__name__)
login_manager = LoginManager()
login_manager.init_app(app)
user = ''
reqLib = ''
#Add headers to force no-cache
#app.after_request
def add_header(r):
r.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
r.headers["Pragma"] = "no-cache"
r.headers["Expires"] = "0"
r.headers["Cache-Control"] = "public, max-age=0"
return r
#post-processing/loading screen -- you can ignore this route
#app.route("/scripting")
#login_required
def script():
scrape()
return redirect(url_for('display'))
#Page displays AFTER a successful <200> response
#app.route("/sqlLibraryDisplay",methods=["GET"])
#login_required
def display():
return send_from_directory("static","index.html")
#Login Page
#app.route('/sqlLibrary', methods=['GET', 'POST'])
def login():
error = None
global reqLib
global user
if request.method == 'POST':
#Grabs username & password entered by user
usr = str(request.form['username'])
pwd = str(request.form['password'])
#Requests SQL Library list from Stash repository
try:
reqLib = requests.get('https://stash/rest/api/latest/projects/PLAN/repos/sqlquerylibrary/files?at=refs%2Fheads%2Fmaster&limit=100000', auth=(usr, pwd), verify=False)
except Exception as e:
return str(e)
if reqLib.status_code != 200:
error = 'Invalid Credentials. Please try again.'
else:
user = User(usr,pwd)
login_user(user)
return redirect(url_for('script'))
return render_template('login.html', error=error)
#login_manager.user_loader
def load_user(id):
global user
global reqLib
if user != '':
if reqLib.status_code == 200:
return user
return None
class User(UserMixin):
def __init__(self, name, id, active=True):
self.name = name
self.id = id
self.active = active
def is_active(self):
return self.active
def is_anonymous(self):
return False
def is_authenticated(self):
return True
def scrape():
#confidential. Just some post-processing using reqLib data.
if __name__ == "__main__":
app.config["SECRET_KEY"] = "MAD_SECRET_KEY"
app.run()
I found the answer. Posting to help out anyone who decides to implement Flask on IIS that might run into this same issue.
The permission error was indeed an issue on the IIS side.
You have to change IIS's permission settings. This link helped me out:
IIS7 Permission Denied - ASP File Write
In IIS Manager I clicked Application Pools in the Connections pane.
Then instead selected my Flask application (not DefaultAppPool as stated in the link).
I right-clicked it and selected Advanced settings.
Then I changed the Identity field under Process Model section to LocalSystem.
Hit OK.
After this change, the python requests module gets a <200> response with successful authentication credentials & avoids the connection error! ^^

Categories