Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

default_reauthn_handler does not redirect correctly when SECURITY_URL_PREFIX is set #526

Closed
djpnewton opened this issue Sep 12, 2021 · 1 comment · Fixed by #529
Closed
Assignees
Labels

Comments

@djpnewton
Copy link
Contributor

I am not sure exactly why but the default_reauthn_handler() does not prepend the SECURITY_URL_PREFIX before redirecting to the SECURITY_VERIFY_URL endpoint

@djpnewton
Copy link
Contributor Author

url_for('security.verify') works but I think the problem is default_reauthn_handler() does something more like url_for(_security.verify_url)

Below is a minimal reproduction of the problem:

import os
from datetime import timedelta
from flask import Flask, current_app, render_template, redirect
from flask.helpers import url_for
from flask_sqlalchemy import SQLAlchemy
from flask_security import Security, SQLAlchemyUserDatastore, \
    UserMixin, RoleMixin, auth_required
from flask_mail import Mail

# Create app
app = Flask(__name__)
app.config['DEBUG'] = True
# Generate a nice key using secrets.token_urlsafe()
app.config['SECRET_KEY'] = os.environ.get("SECRET_KEY", 'pf9Wkove4IKEAXvy-cQkeDPhv9Cb3Ag-wyJILbq_dFw')
# Bcrypt is set as default SECURITY_PASSWORD_HASH, which requires a salt
# Generate a good salt using: secrets.SystemRandom().getrandbits(128)
app.config['SECURITY_PASSWORD_SALT'] = os.environ.get("SECURITY_PASSWORD_SALT", '146585145368132386173505678016728509634')

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://'

app.config['SECURITY_URL_PREFIX'] = "/security"

# Create database connection object
db = SQLAlchemy(app)

# Define models
roles_users = db.Table('roles_users',
    db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
    db.Column('role_id', db.Integer(), db.ForeignKey('role.id')))

class Role(db.Model, RoleMixin):
  id = db.Column(db.Integer(), primary_key=True)
  name = db.Column(db.String(80), unique=True)
  description = db.Column(db.String(255))

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(255), unique=True)
    # Make username unique but not required.
    username = db.Column(db.String(255), unique=True, nullable=True)
    password = db.Column(db.String(255))
    active = db.Column(db.Boolean())
    fs_uniquifier = db.Column(db.String(255), unique=True, nullable=False)
    confirmed_at = db.Column(db.DateTime())
    roles = db.relationship('Role', secondary=roles_users,
                            backref=db.backref('users', lazy='dynamic'))
    tf_phone_number = db.Column(db.String(128), nullable=True)
    tf_primary_method = db.Column(db.String(64), nullable=True)
    tf_totp_secret = db.Column(db.String(255), nullable=True)

# Setup Flask-Security
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore)

mail = Mail(app)

# Create a user to test with
@app.before_first_request
def create_user():
    db.create_all()
    if not user_datastore.find_user(email='test@me.com'):
        user_datastore.create_user(email='test@me.com', password='password')
    db.session.commit()

# Views
@app.route('/')
@auth_required()
def home():
    return 'ok'

@app.route('/blah')
@auth_required(within=0.001, grace=0) # this does not redirect correctly!
def blah():
    return 'ok'

if __name__ == '__main__':
    app.run()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants