Delete the auth token when logging out.

Before this, authentication tokens were kept in the database, even when
someone logged out. This is unwanted behaviour, as logging in will create
yet another token anyway there is no reason to keep the token around.
This commit is contained in:
Sybren A. Stüvel 2017-11-17 12:07:53 +01:00
parent 491c5e1b8c
commit 49a6a6a758
5 changed files with 54 additions and 9 deletions

View File

@ -83,13 +83,19 @@ def update_subscription():
"""
import pprint
from pillar import auth
from pillar.api import blender_id, service
from pillar.api.utils import authentication
my_log: logging.Logger = log.getChild('update_subscription')
user_id = authentication.current_user_id()
bid_user = blender_id.fetch_blenderid_user()
try:
bid_user = blender_id.fetch_blenderid_user()
except blender_id.LogoutUser:
auth.logout_user()
return '', 204
if not bid_user:
my_log.warning('Logged in user %s has no BlenderID account! '
'Unable to update subscription status.', user_id)

View File

@ -20,6 +20,13 @@ blender_id = Blueprint('blender_id', __name__)
log = logging.getLogger(__name__)
class LogoutUser(Exception):
"""Raised when Blender ID tells us the current user token is invalid.
This indicates the user should be immediately logged out.
"""
@blender_id.route('/store_scst', methods=['POST'])
def store_subclient_token():
"""Verifies & stores a user's subclient-specific token."""
@ -180,6 +187,8 @@ def fetch_blenderid_user() -> dict:
}
}
:raises LogoutUser: when Blender ID tells us the current token is
invalid, and the user should be logged out.
"""
import httplib2 # used by the oauth2 package
@ -201,6 +210,10 @@ def fetch_blenderid_user() -> dict:
log.exception('Error getting %s from BlenderID', bid_url)
return {}
if bid_resp.status_code == 403:
log.warning('Error %i from BlenderID %s, logging out user', bid_resp.status_code, bid_url)
raise LogoutUser()
if bid_resp.status_code != 200:
log.warning('Error %i from BlenderID %s: %s', bid_resp.status_code, bid_url, bid_resp.text)
return {}

View File

@ -177,11 +177,23 @@ def validate_this_token(token, oauth_subclient=None):
return db_user
def remove_token(token: str):
"""Removes the token from the database."""
tokens_coll = current_app.db('tokens')
token_hashed = hash_auth_token(token)
# TODO: remove matching on unhashed tokens once all tokens have been hashed.
lookup = {'$or': [{'token': token}, {'token_hashed': token_hashed}]}
del_res = tokens_coll.delete_many(lookup)
log.debug('Removed token %r, matched %d documents', token, del_res.deleted_count)
def find_token(token, is_subclient_token=False, **extra_filters):
"""Returns the token document, or None if it doesn't exist (or is expired)."""
tokens_collection = current_app.data.driver.db['tokens']
tokens_coll = current_app.db('tokens')
token_hashed = hash_auth_token(token)
# TODO: remove matching on unhashed tokens once all tokens have been hashed.
@ -190,7 +202,7 @@ def find_token(token, is_subclient_token=False, **extra_filters):
'expire_time': {"$gt": datetime.datetime.now(tz=tz_util.utc)}}
lookup.update(extra_filters)
db_token = tokens_collection.find_one(lookup)
db_token = tokens_coll.find_one(lookup)
return db_token

View File

@ -202,8 +202,6 @@ def config_login_manager(app):
def login_user(oauth_token: str, *, load_from_db=False):
"""Log in the user identified by the given token."""
from flask import g
if load_from_db:
user = _load_user(oauth_token)
else:
@ -212,6 +210,20 @@ def login_user(oauth_token: str, *, load_from_db=False):
g.current_user = user
def logout_user():
"""Forces a logout of the current user."""
from ..api.utils import authentication
token = get_blender_id_oauth_token()
if token:
authentication.remove_token(token)
session.clear()
flask_login.logout_user()
g.current_user = AnonymousUser()
def get_blender_id_oauth_token() -> str:
"""Returns the Blender ID auth token, or an empty string if there is none."""
@ -231,6 +243,9 @@ def get_blender_id_oauth_token() -> str:
if request.authorization and request.authorization.username:
return request.authorization.username
if current_user.is_authenticated and current_user.id:
return current_user.id
return ''

View File

@ -2,7 +2,7 @@ import logging
from flask import abort, Blueprint, redirect, render_template, request, session, \
url_for
from flask_login import login_required, logout_user
from flask_login import login_required
from werkzeug import exceptions as wz_exceptions
import pillar.api.blender_cloud.subscription
@ -108,8 +108,7 @@ def login_local():
@blueprint.route('/logout')
def logout():
logout_user()
session.clear()
pillar.auth.logout_user()
return redirect('/')