<a id="flask-framework"></a>

# Flask Framework

Flask reusable applications are tricky (or I’m not capable enough). Here are
details on how to enable this application on Flask.

<a id="dependencies"></a>

## Dependencies

The Flask app does not depend on any storage backend by
default. There’s support for [SQLAlchemy](http://www.sqlalchemy.org/), [MongoEngine](http://mongoengine.org) and [Peewee](http://docs.peewee-orm.com/en/latest/).

<a id="installing"></a>

## Installing

Install the flask core from [pypi](http://pypi.python.org/pypi/social-auth-app-flask/):

```default
$ pip install social-auth-app-flask
```

Install any of the storage solutions:

```default
$ pip install social-auth-app-flask-sqlalchemy
$ pip install social-auth-app-flask-mongoengine
$ pip install social-auth-app-flask-peewee
```

<a id="enabling-the-application"></a>

## Enabling the application

The applications define a [Flask Blueprint](http://flask.pocoo.org/docs/blueprints/), which needs to be registered once
the Flask app is configured by:

```default
from social_flask.routes import social_auth

app.register_blueprint(social_auth)
```

For [MongoEngine](http://mongoengine.org) you need this setting:

```default
SOCIAL_AUTH_STORAGE = 'social_flask_mongoengine.models.FlaskStorage'
```

For [Peewee](http://docs.peewee-orm.com/en/latest/) you need this setting:

```default
SOCIAL_AUTH_STORAGE = 'social_flask_peewee.models.FlaskStorage'
```

<a id="models-setup"></a>

## Models Setup

At the moment the models for [python-social-auth](https://github.com/python-social-auth) are defined inside a function
because they need the reference to the current db session and the User model
used on your project (check *User model reference* below). Once the Flask app
and the database are defined, call `init_social` to register the models:

```default
from social_flask_sqlalchemy.models import init_social

init_social(app, session)
```

For [MongoEngine](http://mongoengine.org):

```default
from social_flask_mongoengine.models import init_social

init_social(app, session)
```

For [Peewee](http://docs.peewee-orm.com/en/latest/):

```default
from social_flask_peewee.models import init_social

init_social(app, session)
```

So far I wasn’t able to find another way to define the models on another way
rather than making it as a side-effect of calling this function since the
database is not available and `current_app` cannot be used on init time, just
run time.

<a id="user-model-reference"></a>

## User model reference

The application keeps a reference to the User model used by your project,
define it by using this setting:

```default
SOCIAL_AUTH_USER_MODEL = 'foobar.models.User'
```

The value must be the import path to the User model.

<a id="global-user"></a>

## Global user

The application expects the current logged in user accessible at `g.user`,
define a handler like this to ensure that:

```default
@app.before_request
def global_user():
    g.user = get_current_logged_in_user
```

<a id="flask-login"></a>

## Flask-Login

The application works quite well with [Flask-Login](https://github.com/maxcountryman/flask-login), ensure to have some similar
handlers to these:

```default
@login_manager.user_loader
def load_user(userid):
    try:
        return User.query.get(int(userid))
    except (TypeError, ValueError):
        pass


@app.before_request
def global_user():
    g.user = login.current_user


# Make current user available on templates
@app.context_processor
def inject_user():
    try:
        return {'user': g.user}
    except AttributeError:
        return {'user': None}
```

<a id="remembering-sessions"></a>

## Remembering sessions

The users session can be remembered when specified on login. The common
implementation for this feature is to pass a parameter from the login form
(`remember_me`, `keep`, etc), to flag the action. [Flask-Login](https://github.com/maxcountryman/flask-login) will mark
the session as persistent if told so.

[python-social-auth](https://github.com/python-social-auth) will check for a given name (`keep`) by default, but
since providers won’t pass parameters back to the application, the value must
be persisted in the session before the authentication process happens.

So, the following setting is required for this to work:

```default
SOCIAL_AUTH_FIELDS_STORED_IN_SESSION = ['keep']
```

It’s possible to override the default name with this setting:

```default
SOCIAL_AUTH_REMEMBER_SESSION_NAME = 'remember_me'
```

Don’t use the value `remember` since that will clash with [Flask-Login](https://github.com/maxcountryman/flask-login) which
pops the value from the session.

Then just pass the parameter `keep=1` as a GET or POST parameter.

<a id="exceptions-handling"></a>

## Exceptions handling

The Django application has a middleware (that fits in the framework
architecture) to facilitate the different [exceptions](https://github.com/python-social-auth/social-core/blob/master/social_core/exceptions.py) handling raised by
[python-social-auth](https://github.com/python-social-auth). The same can be accomplished (even in a simple way) in
Flask by defining an [errorhandler](http://flask.pocoo.org/docs/api/#flask.Flask.errorhandler). For example the next code will redirect any
social-auth exception to a `/socialerror` URL:

```default
from social_core.exceptions import SocialAuthBaseException


@app.errorhandler(500)
def error_handler(error):
    if isinstance(error, SocialAuthBaseException):
        return redirect('/socialerror')
```

Be sure to set your debug and test flags to `False` when testing this on your
development environment, otherwise the exception will be raised and error
handlers won’t be called.
