title: Override Flask-Security's /login endpoint
body: <p>I'm working on a site where the users login via OAuth, not a password-based system.</p>
  
  <p>Because of this, Flask-Security's default login page doesn't actually work for my use case, because I need the <code>/login</code> endpoint for the OAuth setup. I was able to make it so that my <code>/login</code> route wasn't being overridden by Flask-Security's by changing the <code>SECURITY_LOGIN_URL</code> setting option. </p>
  
  <p>This is all working fine, the OAuth login page shows up and returns all the information needed.</p>
  
  <p>The problem kicks in because I'm also trying to utilize the <code>@login_required</code> decorator.</p>
  
  <p>If the user isn't logged in, instead of redirecting to my <code>/login</code> page, the <code>@login_required</code> decorator is redirecting to Flask-Security's page.</p>
  
  <p>Obviously, the config endpoint doesn't help in this situation.</p>
  
  <p>Is it possible to force Flask-Security to use my login route (OAuth) instead of its page?</p>
  
  <p>Here's some example code that shows what I'm talking about with Flask-Security overriding defined routes:</p>
  
  <pre><code>from flask import Flask
  from flask_sqlalchemy import SQLAlchemy
  from flask_login import LoginManager, request
  from flask_security import (Security, SQLAlchemyUserDatastore,
                              UserMixin, RoleMixin, login_required,
                              login_user, logout_user, current_user)
  from passlib.context import CryptContext
  import os
  
  
  class Config:
      basedir = os.path.abspath(os.path.dirname(__file__))
  
      SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'app.db')
      SQLALCHEMY_MIGRATE_REPO = os.path.join(basedir, 'db_repository')
      SQLALCHEMY_TRACK_MODIFICATIONS = False
  
      DEBUG = True
      PORT = 8000
      HOST = "0.0.0.0"
  
      SECRET_KEY = "foobar123"
  
  
  config = Config()
  
  
  app = Flask(__name__, instance_relative_config=True)
  
  app.config.from_object(config)
  
  db = SQLAlchemy(app)
  
  lm = LoginManager()
  
  lm.init_app(app)
  lm.login_view = "login"
  
  
  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 User(UserMixin, db.Model):
      id = db.Column(db.Integer, primary_key=True)
      username = db.Column(db.String(64), index=True, unique=True)
      email = db.Column(db.String(120), index=True, unique=True)
      roles = db.relationship('Role', secondary=roles_users,
                              backref=db.backref('users', lazy='dynamic'))
      provider_id = db.Column(db.String(64), index=True, unique=True)
  
      @property
      def is_authenticated(self):
          return True
  
      @property
      def is_active(self):
          return True
  
      @property
      def is_anonymous(self):
          return True
  
      def get_id(self):
          return str(self.id)
  
      def hash_password(self, password):
          self.hashed_password = pwd_context.encrypt(password)
  
      def verify_password(self, password):
          return pwd_context.verify(password, self.hashed_password)
  
  
  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))
  
  
  user_datastore = SQLAlchemyUserDatastore(db, User, Role)
  security = Security(app, user_datastore)
  
  pwd_context = CryptContext(
      schemes=["bcrypt", "pbkdf2_sha256", "des_crypt"],
      default="bcrypt",
      all__vary_rounds=0.1
  )
  
  
  @lm.user_loader
  def load_user(id):
      return User.query.get(int(id))
  
  
  @app.route("/")
  @app.route("/index")
  @login_required
  def index():
      """Handles calls to / and /index, return the panel"""
      return render_template("index.html")
  
  
  @app.route("/login")
  def login():
      """Would include a bunch of OAuth stuff, not required for this example
      If you try going to this endpoint, you'll get the Flask-Security /login
      instead."""
      return render_template("login.html")
  
  app.run(debug=True)
  </code></pre>