README.md
1# Flask-Login
2
3[![build status](https://travis-ci.org/maxcountryman/flask-login.svg?branch=master)](https://travis-ci.org/maxcountryman/flask-login)
4[![coverage](https://coveralls.io/repos/maxcountryman/flask-login/badge.svg?branch=master&service=github)](https://coveralls.io/github/maxcountryman/flask-login?branch=master)
5
6Flask-Login provides user session management for Flask. It handles the common
7tasks of logging in, logging out, and remembering your users' sessions over
8extended periods of time.
9
10Flask-Login is not bound to any particular database system or permissions
11model. The only requirement is that your user objects implement a few methods,
12and that you provide a callback to the extension capable of loading users from
13their ID.
14
15## Installation
16
17Install the extension with pip:
18
19```sh
20$ pip install flask-login
21```
22
23## Usage
24
25Once installed, the Flask-Login is easy to use. Let's walk through setting up
26a basic application. Also please note that this is a very basic guide: we will
27be taking shortcuts here that you should never take in a real application.
28
29To begin we'll set up a Flask app:
30
31```python
32import flask
33
34app = flask.Flask(__name__)
35app.secret_key = 'super secret string' # Change this!
36```
37
38Flask-Login works via a login manager. To kick things off, we'll set up the
39login manager by instantiating it and telling it about our Flask app:
40
41```python
42import flask_login
43
44login_manager = flask_login.LoginManager()
45
46login_manager.init_app(app)
47```
48
49To keep things simple we're going to use a dictionary to represent a database
50of users. In a real application, this would be an actual persistence layer.
51However it's important to point out this is a feature of Flask-Login: it
52doesn't care how your data is stored so long as you tell it how to retrieve it!
53
54```python
55# Our mock database.
56users = {'foo@bar.tld': {'password': 'secret'}}
57```
58
59We also need to tell Flask-Login how to load a user from a Flask request and
60from its session. To do this we need to define our user object, a
61`user_loader` callback, and a `request_loader` callback.
62
63```python
64class User(flask_login.UserMixin):
65 pass
66
67
68@login_manager.user_loader
69def user_loader(email):
70 if email not in users:
71 return
72
73 user = User()
74 user.id = email
75 return user
76
77
78@login_manager.request_loader
79def request_loader(request):
80 email = request.form.get('email')
81 if email not in users:
82 return
83
84 user = User()
85 user.id = email
86
87 # DO NOT ever store passwords in plaintext and always compare password
88 # hashes using constant-time comparison!
89 user.is_authenticated = request.form['password'] == users[email]['password']
90
91 return user
92```
93
94Now we're ready to define our views. We can start with a login view, which will
95populate the session with authentication bits. After that we can define a view
96that requires authentication.
97
98```python
99@app.route('/login', methods=['GET', 'POST'])
100def login():
101 if flask.request.method == 'GET':
102 return '''
103 <form action='login' method='POST'>
104 <input type='text' name='email' id='email' placeholder='email'/>
105 <input type='password' name='password' id='password' placeholder='password'/>
106 <input type='submit' name='submit'/>
107 </form>
108 '''
109
110 email = flask.request.form['email']
111 if flask.request.form['password'] == users[email]['password']:
112 user = User()
113 user.id = email
114 flask_login.login_user(user)
115 return flask.redirect(flask.url_for('protected'))
116
117 return 'Bad login'
118
119
120@app.route('/protected')
121@flask_login.login_required
122def protected():
123 return 'Logged in as: ' + flask_login.current_user.id
124```
125
126Finally we can define a view to clear the session and log users out:
127
128```python
129@app.route('/logout')
130def logout():
131 flask_login.logout_user()
132 return 'Logged out'
133```
134
135We now have a basic working application that makes use of session-based
136authentication. To round things off, we should provide a callback for login
137failures:
138
139```python
140@login_manager.unauthorized_handler
141def unauthorized_handler():
142 return 'Unauthorized'
143```
144
145Complete documentation for Flask-Login is available on [ReadTheDocs](https://flask-login.readthedocs.io/en/latest/).
146
147
148## Contributing
149
150We welcome contributions! If you would like to hack on Flask-Login, please
151follow these steps:
152
1531. Fork this repository
1542. Make your changes
1553. Install the requirements in `dev-requirements.txt`
1564. Submit a pull request after running `make check` (ensure it does not error!)
157
158Please give us adequate time to review your submission. Thanks!
159