facebookがRedirect URIsのために Strict Modeを使ってほしそうにしている

facebookに見慣れぬアラートが。
![alert.png](https://qiita-image-store.s3.amazonaws.com/0/49825/e3e85bf2-e2ba-3fba-7d43-579cc565b8e5.png)

![message.png](https://qiita-image-store.s3.amazonaws.com/0/49825/55072001-d516-5410-af3c-5ed8a6735a68.png)

> In 90 days, we're making a security update to Facebook Login that will invalidate calls from URIs not listed in the Valid OAuth redirect URIs field of your Facebook Login settings.  
This update comes in response to malicious activity we saw on our platform, and we want to protect your app or website by requiring a new strict mode for redirect URIs. Take action now to ensure your redirect traffic continues to work. Learn More

モニョモニョ言ってた。
要するに90日以内にstrict modeにしないとだめだよってことかな

いい機会なので見直すことにした。

## python-social-authに乗り換えた
* まず、メンテされていなかった[omab/django-social-auth](https://github.com/omab/django-social-auth)から[python-social-auth/social-app-django](https://github.com/python-social-auth/social-app-django)
に乗り換えた。
    * [ドキュメント](http://python-social-auth.readthedocs.io/en/latest/index.html)よんで、もろもろの`settings.py`の設定変更

## 実装方法を決めた
* ソースを読んでみたけど、facebookに対して何か特別なoptionがあるわけではなく、現状対応できてないっぽい。
    * issueにあがってた
        * [social_core.backends.facebook.FacebookOAuth2 should have REDIRECT_STATE set to False · Issue #141 · python-social-auth/social-core](https://github.com/python-social-auth/social-core/issues/141)
    * `redirect_state`を固定にするか、なくすかのどちらかなのだけど、`redirect_state`を固定にする方向で実装していくことにした

## backendを自作
といってもまったく難しいことはしてなくて、クラスを継承して、対象メソッドを上書きしただけ。

```python:custom_backends.py
from social_core.backends.facebook import FacebookOAuth2

class FacebookOAuth2Override(FacebookOAuth2):
    # 現在はデフォルトでTrueなので、これはなくても良い
    REDIRECT_STATE = True

    # get_or_create_stateを上書く
    def get_or_create_state(self):
        if self.STATE_PARAMETER or self.REDIRECT_STATE:
            # Store state in session for further request validation. The state
            # value is passed as state parameter (as specified in OAuth2 spec),
            # but also added to redirect, that way we can still verify the
            # request if the provider doesn't implement the state parameter.
            # Reuse token if any.
            name = self.name + '_state'
            state = self.strategy.session_get(name)
            try:
                # settings.pyのSOCIAL_AUTH_FACEBOOK_REDIRECT_STATEを見に行く
                static_state = self.strategy.get_setting('SOCIAL_AUTH_FACEBOOK_REDIRECT_STATE')
                # sessionに保存する必要があるかどうか
                if state != static_state:
                    self.strategy.session_set(name, static_state)
                state = static_state
            except:
                # SOCIAL_AUTH_FACEBOOK_REDIRECT_STATEがない場合
                # sessionにも何も保管されていなかったら新たに取得する
                if state is None:
                    state = self.state_token()
                    self.strategy.session_set(name, state)
        else:
            state = None
        return state
```

上記を適当なところにおいて(たとえば`myapp/custom_backends.py`としたら)

```python:settings.py
AUTHENTICATION_BACKENDS = (
    'social_core.backends.twitter.TwitterOAuth',
    # 'social_core.backends.facebook.FacebookOAuth2',
    'myapp.custom_backends.FacebookOAuth2Override',
    'django.contrib.auth.backends.ModelBackend',
)
SOCIAL_AUTH_FACEBOOK_REDIRECT_STATE = '{{static_state}}'
```
今の所こんな感じで問題なさそう。

facebook側の設定も忘れずに:(

# 追記
上であげたissueだけどfixされました。
[social_core.backends.facebook.FacebookOAuth2 should have REDIRECT_STATE set to False · Issue #141 · python-social-auth/social-core](https://github.com/python-social-auth/social-core/issues/141)
なので上記の作業は不要ですね。
redirect stateを使用しないような変更のようです。