I am trying to make an application to sign in user using twitter.
I want to identify the users that have at some point in the past already logged in the application so I save the oauth verifier token received at the call back in the database and every time I am logging in a user I match the verifier that I receive at the call back if I have a token for this particular user and then fetch the access token and access token secret from the database.
courtesy this post
This is the code I am using:
Please let me know if there is anything wrong with this, I am already confused why is the code breaking.
verifier= request.args['oauth_verifier']
this_user = user_exists(verifier) #checks if a user is returned for the verification token
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
if this_user is None:
auth, error = authenticate_user(auth) #handles the oauth
clean_up(auth) #saves in db and logs in the user
else:
try:
auth.set_access_token(this_user[access_token], this_user[access_token_secret])
clean_up(auth)
except tweepy.TweepError:
auth, error = authenticate_user(auth)
if type(error) is None:
clean_up(auth)
else:
flash('Oops! That shouldn\'t have happened! ):')
return redirect(url_for('index'))
return redirect(url_for('profile'))
Any help would be highly appreciated.
Thanks! (:
Related
# create/login local user on successful OAuth login
#oauth_authorized.connect_via(google)
def google_logged_in(blueprint, token):
#
# Token is accessible in this scope with token=xyz
#
# One Time Commit to unlock the database
# db.session.commit()
##########################################
if not token:
flash("Failed to log in.", category="error")
return False
resp = blueprint.session.get("/oauth2/v1/userinfo")
if not resp.ok:
msg = "Failed to fetch user info."
flash(msg, category="error")
return False
info = resp.json()
user_id = str(info["id"])
# Find this OAuth token in the database, or create it
query = OAuth.query.filter_by(provider=blueprint.name, provider_user_id=user_id)
try:
oauth = query.one()
db.session.commit()
except NoResultFound:
oauth = OAuth(provider=blueprint.name, provider_user_id=user_id, token=token)
if oauth.user:
# If this OAuth token already has an associated local account,
# log in that local user account.
# Note that if we just created this OAuth token, then it can't
# have an associated local account yet.
#
try:
update=OAuth.query.filter_by(provider=blueprint.name, provider_user_id=user_id)
update.token=token
db.session.commit()
except:
print('cannot update login token')
login_user(oauth.user)
flash("Successfully signed in.")
else:
# Create a new local user account for this user
user = User(email=info["email"],image_url=info["picture"])
# Associate the new local user account with the OAuth token
oauth.user = user
# Save and commit our database models
db.session.add_all([user, oauth])
db.session.commit()
# Log in the new local user account
login_user(user)
flash("Successfully signed in.")
# Disable Flask-Dance's default behavior for saving the OAuth token
return False
What I am trying to do is following:
Flowchart of my Process
I am database noob so i am not sure if I am doing what I want.
The problem is that my database locks after my token expires so something is not working with this part:
if oauth.user:
# If this OAuth token already has an associated local account,
# log in that local user account.
# Note that if we just created this OAuth token, then it can't
# have an associated local account yet.
#
try:
update=OAuth.query.filter_by(provider=blueprint.name, provider_user_id=user_id)
update.token=token
db.session.commit()
except:
print('cannot update login token')
login_user(oauth.user)
flash("Successfully signed in.")
But I couldnt find out where the problem is.
Docs didnt help and following SO posts didnt help either:
How do I unlock a SQLite database?
SQLAlchemy and SQLite: database is locked
https://www.reddit.com/r/flask/comments/36g2g7/af_sqlite_database_locking_problem/
Can someone get my ass out of existential chrisis and SQL dumbness?
Edit:
After the token has expired I now only get the message:
oauthlib.oauth2.rfc6749.errors.InvalidGrantError: (invalid_grant) Token has been expired or revoked.
I fixed a little bit when i replaced
query = OAuth.query.filter_by(provider=blueprint.name, provider_user_id=user_id)
with
query = db.session.query(OAuth).filter_by(provider=blueprint.name, provider_user_id=user_id)
but I seem not to write the new token to the database since I still get:
oauthlib.oauth2.rfc6749.errors.InvalidGrantError: (invalid_grant) Token has been expired or revoked.
So now my question how do I properly update refresh token?
I did not catch an error in:
update=db.session.query(OAuth).filter_by(provider=blueprint.name, provider_user_id=user_id) update.token=token
because of try statement(i know its noobish). I than updated my code like this:
if oauth.user:
# If this OAuth token already has an associated local account,
# log in that local user account.
# Note that if we just created this OAuth token, then it can't
# have an associated local account yet.
#
#try:
print('Trying to update the token')
update=db.session.query(OAuth).filter_by(provider=blueprint.name, provider_user_id=user_id)
update.token=token
db.session.commit()
print('User has been updated:', update.token==token)
#except:
# print('cannot update login token')
login_user(oauth.user)
flash("Successfully signed in.")
Found out that
AttributeError: 'BaseQuery' object has no attribute 'token'
googled it quickly and found out that i need to use the first() like that:
update=db.session.query(OAuth).filter_by(provider=blueprint.name, provider_user_id=user_id).first()
Thanks to myself for being such noob and still get an answer to my question.
I have a simple login system that I did with flask.
After logging in, I return to the user a type of token with which the user can send messages like chat at another route.
I would like to expire that token after some time (a minute for example), the token will expire and the user will have to log in again to get a new token.
So my question is, how do you get the token erased or something like that after expiry time?
After the user log in, I save the login time in a dict like this:
login_time[datetime.datetime.now()] = data['username']
and then I thought of doing something like this before or in the chat route:
for time, user in login_time.items():
if datetime.datetime.now() >= time + datetime.timedelta(seconds=30):
del login_time[time]
But I dont know where should I put it and how it will work.
this is a part of the chat route:
#app.route('/chat', methods=['POST'])
def chat():
try:
data = request.get_json()
username = verify_token(data['token']) # Verifying if token is in tokens list
validate_message(data['message']) # Verifying if message is not empty
chats.append(username + ": " + data['message'])
for i, u in login_time.items(): # Not sure about this part
if i != u:
abort(400, 'Your token is expired, please login again')
return jsonify(chats)
One easy to implement solution, if you do not want to use JWT, is :
When you generate your token, generate the expiration date at the same time
Log both in a database
When the user tries to post a message, its token is sent with the message
check if the token is still valid (either you check if datetime.now() > token_expiration_time or you can even have a script delete every expired token from the database every x minuts and then just check if the token is found in the database or not)
If the token is expired you redirect the user and ask him to log in again to generate another token.
when using a token based auth, you'll have to identify and verify the access by that token, i.e identify the client (which user is this) and verify check the token validity like expiration
you can incorporate this data in the token itself (JWT)
let's say the token is smth like 'token-1571153241', where the number is unix timestamp of expiration
1) parse the expiration timestamp from the token
2) if expiration reached return expiry message, else serve the request
* keep in mind to issue the token with the expiry date
or
use any db to store the token's information
1) parse the token from the request
2) check the db for the token validity
3) pass or reject based the criteria
method 1 is better performance wise, no access to external source (db) is required, but less control of the token attribute, e,g very hard to implement a manual expiration of the token (or change the user privileges access) manually
I need to validate if servicenow login credentials are correct or not.
I am using pysnow
def validate_conn(self, data):
instance = data['url']
user = data['uname']
password = data['pwd']
try:
pysnow.client.Client(instance=instance, host=None, user=user, password='xfgdfgdf', raise_on_empty=None,
request_params=None, session=None)
print("valid")
except:
print("invalid")
return data['pwd']
In the above code I gave the invalid password so it have to come to the except block but i am getting valid as output. I need to validate if credentials are valid or not
The ServiceNow Web Services API does not provide a mechanism to validate credentials. One way to validate credentials from a Web Services client is to attempt to read a record that you know exists. One record that must exist is your own user record from sys_user.
The following code attempts to read your own user record from sys_user. If you are unable to read this record, then something must be wrong.
try:
client = pysnow.Client(instance=instance, user=user, password=password)
response = (client
.resource(api_path='/table/sys_user')
.get(query={'user_name': user})
.one())
print('credentials are valid')
except:
print('credentials are not valid')
I'm trying to set up oauth in Django using Tweepy. I am getting the following error.
AttributeError at /auth/
'dict' object has no attribute 'key'
This occurs in the following code when I try to store the request token for later access when the user is forwarded to the callback url (http://localhost:8000/callback).
def auth(request):
# start the OAuth process, set up a handler with our details
oauth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET, CALLBACK)
# direct the user to the authentication url
# if user is logged-in and authorized then transparently goto the callback URL
try:
auth_url = oauth.get_authorization_url()
except tweepy.TweepError:
return HttpResponse('error', status=500)
# store the request token
request.session['unauthed_token_tw'] = (oauth.request_token.key, oauth.request_token.secret)
return HttpResponseRedirect(auth_url)
I am new to Python and Django, does this error mean that the oauth.request_token is null? Could it be a problem with my callback url? Do I need to forward port 8000? Any help or pointers would be much appreciated!
I changed this line of code:
request.session['unauthed_token_tw'] = (oauth.request_token.key, oauth.request_token.secret)
to this:
request.session['unauthed_token_tw'] = oauth.request_token
... after reading this documentation. And now it works!
I'm consistently getting an "Invalid response from Facebook" error when authenticating over Facebook with Oauthlib when building off of the sample code here.
I've outlined the sections of relevant code below.
Setup:
Setting up the Oauth request object.
Not pictured: Navigational routes and Flask app initialization.
from flask_oauthlib.client import OAuth, OAuthException
oauth = OAuth()
facebook = oauth.remote_app('facebook',
base_url='https://graph.facebook.com/',
request_token_url=None,
access_token_url='/oauth/access_token',
authorize_url='https://www.facebook.com/dialog/oauth',
consumer_key=config.get("app_id"),
consumer_secret=config.get("app_secret"),
request_token_params={'scope': 'public_profile,email'}
)
#facebook.tokengetter
def get_facebook_token():
if current_user.is_authenticated():
return current_user.get_facebook_token()
else:
return None
Login handler:
Sending users here in order to begin the process, with the url for the facebook callback appended to the root URL.
#app.route('/facebook/login')
def facebook_login():
return facebook.authorize(callback="http://example.com%s" % url_for('facebook_callback'))
Facebook callback, source of the issue:
From here I can garner that a code (presumably the token) is returned but Oauthlib fails to parse it correctly.
#app.route('/facebook/callback')
def facebook_callback(response):
response = facebook.authorized_response()
if response is None:
flash("You denied the request to sign in.", "error")
return redirect(url_for('index'))
if isinstance(response, OAuthException):
flash("Access denied: %s" % response.message, "error")
return redirect(url_for('index'))
# Request fails here, returns the redirect above.
From dumping the request args I can see fairly clearly that after being directed to Facebook and successfully connecting, there is a very long token being returned to the callback along the lines of '?code=1234567890-abcdefghijklmnop', however actually trying to authenticate with this fails with "Invalid response from Facebook".
Here is a sample request dump:
ImmutableMultiDict([('code', 'AQAPedwWavTb_cBx6NVy-qy3AL5YPr780oG5tA1LfITpVwkk-kr_4I0lG6B-vlhcYEubhuKhEM46bPs-1WpWUpJzcWfhkQ64lIkdLm9uSHSqeBHBM_6zw7SDpvVmGK-JKWBpAqRJuBKenl9zslQizthox96104iiul0uYQY67cmZgPXZi9uL-mcgZ5dRj387eKJIjNninBXxwCGgFkg5kLVHYt7t0ktUH58stYlxn2f98AXuSlrIvWsA5NeHsVbM8XY0XQrDrNbCvjDmEwHQGkZ3uZRbyaecN7MAi0bM0TrZzpuQ8j3M34DnQp_v9n4ktM4')])
Having used similar code based off of the Twitter sample that works, I'm thinking this could be a possible library bug due to Facebook API changes, but I would appreciate any pointers!
For anyone who stumbles upon this from Google in the future, I solved this in a solution that can be read here.
Hey there, I solved this issue in a very hacky way which I would not
recommend for production environments, but I eventually found the
issue a few days after my last message.
When you ask Facebook for an access token, it does NOT give you an
access token in the way you might expect. What I assumed to be a
failure on Facebook's side was instead a (perhaps intentional)
formatting error.
What you might expect:
http://example.com/callback?access_token=00000000000
or
http://example.com/callback with the access token passed as a POST
argument in the headers.
What actually happens is that Facebook responds like this:
http://example.com/callback?#access_token=0000000000
Because of this, it is -impossible- for any server side language
to parse it, as the access token will now only be visible to the
browser itself. It is not passed to the backend whatsoever.
Capturing the request:
#app.route('/facebook/translate', methods=['GET'])
def facebook_translate():
# Facebook responds with the access token as ?#access_token,
# rather than ?access_token, which is only accessible to the browser.
# This part is where things get really, really dumb.
return ''' <script type="text/javascript">
var token = window.location.href.split("access_token=")[1];
window.location = "/facebook/callback?access_token=" + token;
</script> '''
Proceeding as usual:
#app.route('/facebook/callback', methods=['GET', 'POST'])
def facebook_callback():
access_token = request.args.get("access_token")
if access_token == "undefined":
flash("You denied the request to sign in.", "error")
return redirect(url_for('index'))
graph = facebooksdk.GraphAPI(access_token)
profile = graph.get_object("me")