replace encrypted cookies with proper session tokens
This commit is contained in:
parent
4c134b75f5
commit
7c38270223
|
@ -13,18 +13,6 @@ only postgresql with psycopg2 driver is officially supported
|
||||||
"""
|
"""
|
||||||
SQLALCHEMY_DATABASE_URI='postgresql+psycopg2:///forget'
|
SQLALCHEMY_DATABASE_URI='postgresql+psycopg2:///forget'
|
||||||
|
|
||||||
"""
|
|
||||||
SECRET KEY
|
|
||||||
|
|
||||||
this key is used to encrypt session cookies
|
|
||||||
you can generate a random key by running
|
|
||||||
openssl rand -base64 102 | tr -d "\n"; echo
|
|
||||||
or if you don't have openssl installed
|
|
||||||
cat /dev/random | head -c 102 | base64 | tr -d "\n"; echo
|
|
||||||
the latter might take a while if your system entropy is low, give it time
|
|
||||||
"""
|
|
||||||
SECRET_KEY='change me!'
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
TWITTER CREDENTIALS
|
TWITTER CREDENTIALS
|
||||||
|
|
||||||
|
@ -35,7 +23,7 @@ TWITTER_CONSUMER_KEY='vdsvdsvds'
|
||||||
TWITTER_CONSUMER_SECRET='hjklhjklhjkl'
|
TWITTER_CONSUMER_SECRET='hjklhjklhjkl'
|
||||||
|
|
||||||
"""
|
"""
|
||||||
blablabl
|
this will be necessary so we can tell twitter where to redirect
|
||||||
"""
|
"""
|
||||||
SERVER_NAME="localhost:5000"
|
SERVER_NAME="localhost:5000"
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: c3faafd828ad
|
||||||
|
Revises:
|
||||||
|
Create Date: 2017-07-27 01:16:34.114238
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'c3faafd828ad'
|
||||||
|
down_revision = None
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('accounts',
|
||||||
|
sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=True),
|
||||||
|
sa.Column('updated_at', sa.DateTime(), server_default=sa.text('now()'), nullable=True),
|
||||||
|
sa.Column('remote_id', sa.String(), nullable=False),
|
||||||
|
sa.Column('remote_display_name', sa.String(), nullable=True),
|
||||||
|
sa.Column('remote_avatar_url', sa.String(), nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint('remote_id', name=op.f('pk_accounts'))
|
||||||
|
)
|
||||||
|
op.create_table('oauth_tokens',
|
||||||
|
sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=True),
|
||||||
|
sa.Column('updated_at', sa.DateTime(), server_default=sa.text('now()'), nullable=True),
|
||||||
|
sa.Column('token', sa.String(), nullable=False),
|
||||||
|
sa.Column('token_secret', sa.String(), nullable=False),
|
||||||
|
sa.Column('remote_id', sa.String(), nullable=True),
|
||||||
|
sa.ForeignKeyConstraint(['remote_id'], ['accounts.remote_id'], name=op.f('fk_oauth_tokens_remote_id_accounts')),
|
||||||
|
sa.PrimaryKeyConstraint('token', name=op.f('pk_oauth_tokens'))
|
||||||
|
)
|
||||||
|
op.create_table('sessions',
|
||||||
|
sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=True),
|
||||||
|
sa.Column('updated_at', sa.DateTime(), server_default=sa.text('now()'), nullable=True),
|
||||||
|
sa.Column('id', sa.String(), nullable=False),
|
||||||
|
sa.Column('remote_id', sa.String(), nullable=True),
|
||||||
|
sa.ForeignKeyConstraint(['remote_id'], ['accounts.remote_id'], name=op.f('fk_sessions_remote_id_accounts')),
|
||||||
|
sa.PrimaryKeyConstraint('id', name=op.f('pk_sessions'))
|
||||||
|
)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_table('sessions')
|
||||||
|
op.drop_table('oauth_tokens')
|
||||||
|
op.drop_table('accounts')
|
||||||
|
# ### end Alembic commands ###
|
8
model.py
8
model.py
|
@ -3,6 +3,7 @@ from datetime import datetime
|
||||||
from app import db
|
from app import db
|
||||||
|
|
||||||
from twitter import Twitter, OAuth
|
from twitter import Twitter, OAuth
|
||||||
|
import secrets
|
||||||
|
|
||||||
class TimestampMixin(object):
|
class TimestampMixin(object):
|
||||||
created_at = db.Column(db.DateTime, server_default=db.func.now())
|
created_at = db.Column(db.DateTime, server_default=db.func.now())
|
||||||
|
@ -34,3 +35,10 @@ class OAuthToken(db.Model, TimestampMixin):
|
||||||
remote_id = db.Column(db.String, db.ForeignKey('accounts.remote_id'))
|
remote_id = db.Column(db.String, db.ForeignKey('accounts.remote_id'))
|
||||||
account = db.relationship(Account)
|
account = db.relationship(Account)
|
||||||
|
|
||||||
|
class Session(db.Model, TimestampMixin):
|
||||||
|
__tablename__ = 'sessions'
|
||||||
|
|
||||||
|
id = db.Column(db.String, primary_key=True, default=lambda: secrets.token_urlsafe())
|
||||||
|
|
||||||
|
remote_id = db.Column(db.String, db.ForeignKey('accounts.remote_id'))
|
||||||
|
account = db.relationship(Account, lazy='joined')
|
||||||
|
|
39
routes.py
39
routes.py
|
@ -1,18 +1,27 @@
|
||||||
from app import app
|
from app import app
|
||||||
from flask import render_template, session, url_for, redirect, request
|
from flask import render_template, url_for, redirect, request, g, Response
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import lib.twitter
|
import lib.twitter
|
||||||
from model import Account
|
from model import Account, Session
|
||||||
from app import db
|
from app import db
|
||||||
|
|
||||||
|
@app.before_request
|
||||||
|
def load_viewer():
|
||||||
|
g.viewer = None
|
||||||
|
sid = request.cookies.get('forget_sid', None)
|
||||||
|
if sid:
|
||||||
|
g.viewer = Session.query.get(sid)
|
||||||
|
|
||||||
|
@app.after_request
|
||||||
|
def touch_viewer(resp):
|
||||||
|
if g.viewer:
|
||||||
|
g.viewer.touch()
|
||||||
|
db.session.commit()
|
||||||
|
return resp
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def index():
|
def index():
|
||||||
viewer = None
|
return render_template('index.html')
|
||||||
if 'remote_id' in session:
|
|
||||||
viewer = Account.query.get(session['remote_id'])
|
|
||||||
viewer.touch()
|
|
||||||
db.session.commit()
|
|
||||||
return render_template('index.html', viewer = viewer)
|
|
||||||
|
|
||||||
@app.route('/login/twitter')
|
@app.route('/login/twitter')
|
||||||
def twitter_login_step1():
|
def twitter_login_step1():
|
||||||
|
@ -26,12 +35,16 @@ def twitter_login_step2():
|
||||||
oauth_token = request.args['oauth_token']
|
oauth_token = request.args['oauth_token']
|
||||||
oauth_verifier = request.args['oauth_verifier']
|
oauth_verifier = request.args['oauth_verifier']
|
||||||
token = lib.twitter.receive_verifier(oauth_token, oauth_verifier, **app.config.get_namespace("TWITTER_"))
|
token = lib.twitter.receive_verifier(oauth_token, oauth_verifier, **app.config.get_namespace("TWITTER_"))
|
||||||
session['remote_id'] = token.remote_id
|
session = Session(remote_id = token.remote_id)
|
||||||
return redirect(url_for('index'))
|
db.session.add(session)
|
||||||
|
db.session.commit()
|
||||||
|
resp = Response(status=301, headers={"location": url_for('index')})
|
||||||
|
resp.set_cookie('forget_sid', session.id)
|
||||||
|
return resp
|
||||||
|
|
||||||
@app.route('/logout')
|
@app.route('/logout')
|
||||||
def logout():
|
def logout():
|
||||||
keys = list(session.keys())
|
if(g.viewer):
|
||||||
for key in keys:
|
db.session.delete(g.viewer)
|
||||||
del session[key]
|
db.session.commit()
|
||||||
return redirect(url_for('index'))
|
return redirect(url_for('index'))
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
{% if viewer %}
|
{% if g.viewer %}
|
||||||
<p>Hello,
|
<p>Hello,
|
||||||
<img src="{{viewer.remote_avatar_url}}"/>
|
<img src="{{g.viewer.account.remote_avatar_url}}"/>
|
||||||
{{viewer.remote_display_name}}! <a href="/logout">Log out</a></p>
|
{{g.viewer.account.remote_display_name}}! <a href="/logout">Log out</a></p>
|
||||||
<p><code>{{session}}</code></p>
|
|
||||||
<p><code>{{viewer}}</code></p>
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>Hello, stranger! <a href="/login/twitter">Log in with Twitter</a></p>
|
<p>Hello, stranger! <a href="/login/twitter">Log in with Twitter</a></p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
Loading…
Reference in New Issue