How to get 'jti', not mine but by the "username" ?
On registration/login jti for access and refresh were assigned to 'username'.
All instructions and docs note only how to get my own jti to logout with smth. like this code:
class UserLogoutRefresh(Resource):
#jwt_refresh_token_required
def post(self):
jti = get_raw_jwt()['jti']
try:
revoked_token = RevokedTokenModel(jti = jti)
revoked_token.add()
return {'message': 'Refresh token has been revoked'},200
except:
return {'message': 'Something went wrong'}, 500
How to get jti for another user.
I suppose smth like:
jti = get_raw_jwt(identity='someusername')['jti']
has to exist for this, who knows ???
Each token will have a unique jti, it’s not scoped per username. If the same user creates 3 tokens, all of them will have a different jti for example. If you want to have access to these jti then you will use the decode_token function when you create your token and save it in a datastore somewhere you can look it up later
Related
I have a dictionary of users with (username, password) as key, value pair.
i would like to restrict the authorisation creation to only users in my dictionary.
So any other user who is not in the dictionary shouldn't be able to create a token.
I try this but it's not working, I can still create token to a new user.
#api.post("/token")
async def get_token(form_data: OAuth2PasswordRequestForm = Depends()):
if not authenticate_user(username=form_data.username,
password=form_data.password):
raise HTTPException(status_code=403, detail='Authentication failed')
else:
return {
"access_token": form_data.username,
"token_type": "bearer"
}
raise HTTPException(status_code=403,
detail='Authentication failed')
You never compare anything against form_data.username - the only thing you do is that you start looping over the user, and you check whether the first users password match - well, the user's password. This will always be true.
Instead, retrieve the user you're looking for and compare the password if present:
#api.post("/token")
async def get_token(form_data: OAuth2PasswordRequestForm = Depends()):
user = users.get(form_data.username)
if user and authenticate_user(form_data=username, password=form_data.password):
return {
"access_token": form_data.username,
"token_type": "bearer"
}
raise HTTPException(status_code=403,
detail='Authentication failed')
I'd also like to point out that you're using the users username as the token. This means that anyone can fake a token by simply supplying the username they want to be authenticated as.
Instead, use secrets.token_urlsafe() to generate a token that can be used as an authentication secret. You'll need to store these tokens somewhere, but in this example it seems like you're storing everything in the currently running Python application for users, so you can do the same for tokens. Define valid_tokens = {} somewhere when initializing your application, then insert rows into this dict to assign a username.
token = secrets.token_urlsafe(32)
valid_tokens[token] = form_data.user_name
return {
"access_token": token,
"token_type": "bearer"
}
You can then verify this token in a separate function and use it to look up the username of the logged in user from the token.
I'm trying the get all orders that belonging the user that already login to the system.
I want to get the id information of the current user with the get() method below and get the order information belonging to current user from the order table.
My goal is to get the current user's id from the JWT token using flask-jwt-extended.
How can I do that?
#api.route('/orders')
#jwt_required()
def get(self):
# current_user_info
user_id = current_user_info["id"]
return UserService.get_orders(user_id)
flask_jwt_extended provides the get_jwt_identity() function, which returns the identity used to create the token used in the current call: create_access_token(identity=username).
Link to the documentation
So in your case, it should become something like this
#api.route('/orders')
#jwt_required()
def get(self):
# current_user_info
user_id = get_jwt_identity()
return UserService.get_orders(user_id)
You can see the complete documentation for user loading and retrieval here: https://flask-jwt-extended.readthedocs.io/en/stable/automatic_user_loading/
I am using this tutorial to incorporate authentication into my app: http://blog.miguelgrinberg.com/post/restful-authentication-with-flask
At the moment I have the following route:
#app.route('/checkin/venue/<int:venue_id>', methods = ['POST'])
#auth.login_required
My verify_password function is quite similar to that specified in the tutorial except I am accessing my own db.
The issue is that when I generate a token, it can be used across multiple venue_id's even though the token was generated using the credentials of a singlevenue.
Is there a way that I could pass the venue_id variable to the function verify_password(email_or_token, password) so when I call verify_auth_token I will be able to check that the venue_id encoded in the token actually corresponds to that made in the call:
#app.route('/checkin/venue/<int:venue_id>', methods = ['POST'])
Thanks for your help.
You don't say this explicitly, but I assume you have the venue_id in the token, correct? If not, you should add it. The token can store any data you want so add the venue_id there in addition to the user_id.
So what you need is to compare the venue_id given in your request URL against the one in the token. And this is easy to do, since you can access the venue id in your URL as request.view_args['venue_id'].
So assuming you followed the design in my tutorial, you now have a User.verify_auth_token(token) method that decodes the token and verifies it. You can add an argument to this method that is the venue_id, and incorporate that verification in the logic of that method.
Then in your verify_password callback you can do something like this:
#auth.verify_password
def verify_password(token, password):
user = User.verify_auth_token(token, request.view_args.get('venue_id', 0))
if not user:
return False
g.user = user
return True
Note that I chose a default of 0 for the case of a request that does not include a venue_id argument. This is just to avoid a crash. In your verification function you can choose to accept a venue_id of 0 as meaning that this request works for all venues, so in that case you skip the check on the venue.
Hope this helps!
I am try to write a function that gets the username of the person logged and right after that changes de session_key into a new one.
What I have written so far is this:
def get_username(request):
try:
for coisa in request:
session_key = coisa # This seems to be wrong, but it works
session = Session.objects.get(session_key=session_key)
user_id = session.get_decoded().get('_auth_user_id')
user = User.objects.get(id=user_id) # Works very well until here, trust me
session.cycle_key() #this is where I'm getting the error
return HttpResponse(user.username)
except Exception, e:
print 'Erro: ' + str(e)
return HttpResponseServerError(str(e))
That request variable I'm passing is not the usual django request, it's a request built by a javascript script and has only the session_key on its data.
The error I'm getting is this: 'Session' object has no attribute 'cycle_key'
The session_key I'm using on this function came from a function that runs when the page is going to load, so that request is a "normal" request variable from django:
session_key = request.session.session_key
I don't understand why you're doing all this at all. The user is already in request.user, so there's no need to get it from the session, and similarly the session itself is in request.session - so you can just do request.session.cycle_key().
cycle_key() belongs to sessions.backends.db.SessionStore (inherited from SessionBase), and what you are trying to use
here is models.Session, which is a session model. Normally request.session IIRC is an instance of SessionStore.
So you need to create a new SessionStore here. It initialized with session key:
session = SessionStore(session_key)
I am using flask-login https://github.com/maxcountryman/flask-login and the field remember in login_user does not seem to work.
The session gets destroyed after every restart of the apache ..ideally the remember field should take care of this.. even the session values gets destroyed. this is really frustrating... anyone knowing the solution please ping .. thanks
i am using login_user as
login_user(user, remember=True)
If anyone is suffering with this problem, you have to write the function user_loader properly.
#login_manager.user_loader
def load_user(id):
return "get the user properly and create the usermixin object"
I ran into this issue, but it was because we were setting Flask.secret_key to a new GUID on startup. We moved this to a configuration file (unique ID per environment) and now the session is persisted.
you have to set the get_auth_token in the user mixen as well as the user_loader
class User(UserMixin):
def get_auth_token(self):
"""
Encode a secure token for cookie
"""
data = [str(self.id), self.password]
return login_serializer.dumps(data)
And
#login_manager.token_loader
def load_token(token):
"""
Flask-Login token_loader callback.
The token_loader function asks this function to take the token that was
stored on the users computer process it to check if its valid and then
return a User Object if its valid or None if its not valid.
"""
#The Token itself was generated by User.get_auth_token. So it is up to
#us to known the format of the token data itself.
#The Token was encrypted using itsdangerous.URLSafeTimedSerializer which
#allows us to have a max_age on the token itself. When the cookie is stored
#on the users computer it also has a exipry date, but could be changed by
#the user, so this feature allows us to enforce the exipry date of the token
#server side and not rely on the users cookie to exipre.
max_age = app.config["REMEMBER_COOKIE_DURATION"].total_seconds()
#Decrypt the Security Token, data = [username, hashpass]
data = login_serializer.loads(token, max_age=max_age)
#Find the User
user = User.get(data[0])
#Check Password and return user or None
if user and data[1] == user.password:
return user
return None
Both of those methods use the module itsdangerous to encrypt the remember me cookie
from itsdangerous import URLSafeTimedSerializer
I wrote a blog post about how I did it
Flask-Login Auth Tokens