How to make a token expire after a while? (without jwt) - python

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

Related

How to do google Sign In with the help of idToken in Django

This is the code I use to retrieve idToken in my flutter app
Future<void> _handleSignIn() async {
try {
final result = await _googleSignIn.signIn();
final ggAuth = await result!.authentication;
print(ggAuth.idToken); // this is the one that I use as token value
print(ggAuth.accessToken);
} catch (error) {
print(error);
}
}
And this is the code I use to access user info in my backend.
from google.oauth2 import id_token
from google.auth.transport import requests
try:
idinfo = id_token.verify_oauth2_token(token, requests.Request(), CLIENT_ID)
userid = idinfo['sub']
print(userid)
except ValueError:
print('Invalid token)
But after replacing the token variable with the token received from flutter app and replacing the CLIENT_ID with the id generated for my app (available in the console) , it still throws the error of invalid token. What am I doing wrong?
EDIT- When I use https://jwt.io/ to decode the token it works as expected and I get all the details.
Authentication Think of the id token as your birth certificate. It just identifies you as a person.
Authorization Think of the access token as your drivers license its what contains the permissions that you have to drive a car.
An Id token does not out write give you permission to access any data on google servers. With an access token you have been authorized to access some data in this case some profile information.
The issue you are having is that you are using sign-in in. Sign in is Open id connect think of it as a birth certificate (Id token). There is a user their who is signing in to your app. They are in fount of their computer. By default with Google signin gives you get basic profile information. What you are doing with Jwt.io is checking the claims that are returned in the Id token. Id tokens are just the token that allows your application to identify that the user is logged in. There should also be a sub claim there you should use this id to map the user to your integral user system. There may be a user name and email address in the claims but you can not guarantee that they will be there every time google has stated they do not always return these claims.
To get user profile information after the user has logged in you should be using the people api the people.get method when passed the access token will return to you the profile information of the currently authenticated user.
beyond that you should IMO not be passing tokens to your backend if you want the token in the backend you should log the user in using your backend language.
Okay so the idToken that I had was correct but flutter terminal was not able to print its full length and because of which I was copying only half the token and was getting a signature error when checking manually.

Does the ouath verifier token remain unique for every request

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! (:

Does OAuth2Decorator store user Credentials and renew Tokens?

I'm working with the OAuth2Decorator() and Pytgon I'm in that stage where i'm still unsure of something about the App Engine. The documentation is not providing any info or I simply can't follow it. So:
Does OAuth2Decorator() store user Crediantials?
Does OAuth2Decorator() retrieve new tokens automatically?
Conside this following example.:
decorator = OAuth2Decorator(...)
service = build("drive", "v2")
class AppHandler(BaseHandler):
#decorator.oauth_aware
def get(self):
if decorator.has_credentials():
init = service.files().list().execute(decorator.http())
items = init['items']
context = {'data': getitems(items)}
self.render_response('index.html',**context)
else:
url = decorator.authorize_url()
self.redirect(url)
The credentials get stored as CredentialsModel in the datastore.
Provided the access that's requested is 'offline' (I believe this is the default), then there will be a 'refresh token' stored alongside the temporary access-token. If a request is made with a credentials-wrapped Http client, then upon receiving a response that indicates the access token has expired, the client make a request to get a new access token automatically, and then the original request will be retried with the new access token, which will then be stored in place of the expired one.

what is the best way to generate a reset token in python?

I'm trying to make a validation process for a password reset, what i've used are two values: the epoch time, and i want to use the users's old password (pbkdf2) as a key,
Since i dont want to get non ASCII characters, i've used SimpleEncode library because it's fast since it's only a BASE64 with a key used, but the problem is that the password is too long (196 chars) so i get a long key!
What i've done is split the result code = simpleencode.encode(key,asci)[::30], but this will not be unique!
To get an idea how it works, i've tried Facebook reset process, but what is given is a number! so how this process works, don't they use a key to make it hard for someone to forge a link to reset someone's password?
Update: how the algorithme will work:
1- get the time using epoche time.time()
2- generate the Base64 of the epoche time (to use for the URL) and the epoch time value + a key, this key is PBKDF2(password).
3- generate the url www.example.com/reset/user/Base64(time.time()) and send this URL + the simpleencode.encode(key,asci)[::30]
4- when the user clicks on the URL, he put the generated code, this generated code, if it matches with the URL, then let him modifiy the password, else, it is a forget URL!
Not sure it's the best way, but I'd probably just generate a UUID4, which can be used in a URL to reset the password and expire it after 'n' amount of time.
>>> import uuid
>>> uuid.uuid4().hex
'8c05904f0051419283d1024fc5ce1a59'
You could use something like http://redis.io to hold that key, with a value of the appropriate user ID and set its time to live. So, when something comes in from http://example.com/password-reset/8c05904f0051419283d1024fc5ce1a59 it looks to see if it's valid and if so then allows changes to set a new password.
If you did want a "validation pin", then store along with the token, a small random key, eg:
>>> from string import digits
>>> from random import choice
>>> ''.join(choice(digits) for i in xrange(4))
'2545'
And request that be entered on the reset link.
Easiest way by far is to use the ItsDangerous library:
You can serialize and sign a user ID for unsubscribing of newsletters into URLs. This way you don’t need to generate one-time tokens and store them in the database. Same thing with any kind of activation link for accounts and similar things.
You can also embed a timestamp, so very easily to set time periods without having to involve databases or queues. It's all cryptographically signed, so you can easily see if it's been tampered with.
>>> from itsdangerous import TimestampSigner
>>> s = TimestampSigner('secret-key')
>>> string = s.sign('foo')
>>> s.unsign(string, max_age=5)
Traceback (most recent call last):
...
itsdangerous.SignatureExpired: Signature age 15 > 5 seconds
Why not just use a jwt as token for this purpose, its also possible to set an expiration time to it, so its also possible to put an expiration date to the token.
Generate token(JWT) encrypted with a secret key
Send mail containg a link with the token as a query paramater(When the user opens the link the page can read the token)
Verify the token before saving the new password
For generating jwt tokens I use pyjwt. The below code snippet shows how it can be done with an expiry time of 24 hours(1 day) and signed with a secret key:
import jwt
from datetime import datetime, timedelta, timezone
secret = "jwt_secret"
payload = {"exp": datetime.now(timezone.utc) + timedelta(days=1), "id": user_id}
token = jwt.encode(payload, secret, algorithm="HS256")
reset_token = token.decode("utf-8")
Below snippet shows how the verification of token and the new password can be set in django. If the token has expired or has been tampered with, it will raise an exception.
secret = "jwt_secret"
claims = jwt.decode(token, secret, options={"require_exp": True})
# Check if the user exists
user = User.objects.get(id=claims.get("id"))
user.set_password(password)
user.save()

Handle incorrect user/password repoze.who gracefully in Python/Pylons

im using FriendlyFormPlugin, but would like to retrieve the username that was input as part of the request.params, but its no longer there when i check. this way i can set the default for username if the password is incorrect. thanks
I think what you need to do is to setup a post login handler action when you setup the middleware. In that action you can then check params, set a session var, etc. I had to hook into here in order to create a message to the user that their login had failed. I check for a 'login_failed' param on the login form.
def post_login(self):
""" Handle logic post a user's login
I want to create a login_handler that's redirected to after login. This would
check
- if user was logged in, if not then send back to login
- if user is admin, go to job list
- adjust the max age on the existing cookie to XX remember me timeframe
"""
if auth.check(not_anonymous()):
log.debug('checked auth')
else:
# login failed, redirect back to login
log.debug('failed auth')
redirect_to(controller="root", action="login", login_failed=True)
# expire this cookie into the future
ck = request.cookies['authtkt']
response.set_cookie('authtkt', ck,
max_age=60*60*24*7,
path='/'
)
redirect_to(controller="job", action="list")
In response for more details, too big to add as another comment:
So I've got a few things you can look at. First, this is my docs I'm writing as a repoze 'summary' to help explain to other devs how this stuff works/terminology used:
http://72.14.191.199/docs/morpylons/auth_overview.html
I started out using the repoze sql quickstart plugin:
http://code.gustavonarea.net/repoze.what-quickstart/
I then ripped out their setup_sql_auth and modified it for our own needs since we do both SQL and LDAP auth in our apps. Go make sure to look at the plugin source for setup_sql_auth and go through it until you really understand what it's doing.
and since you asked on middleware config...
app = setup_morpace_auth(app, User, Group, Permission, meta.Session,
post_login_url='/root/post_login',
post_logout_url='/login',
log_level='debug',
log_file='stdout'
)

Categories

Resources