[Django] restframework + oauth-toolkitでハマった話
2017/01/07 17:40
  • はじめに

    最近、趣味でQRコードを読み取ってログイン(出席)させるような
    iOSアプリを制作中で、サーバーサイドAPIをDjangoのrestframework + django-oauth-toolkit で実装したときにちょっと
    ハマってしまいました、というお話です。

    前提


    Django 1.8.0
    django-restframework
    django-oauth-toolkit
    Apache 2.2系
    

    API通信に認証を入れたくて、かつクライアントアプリ側でも認証情報を持ち回したかったので
    そのサイト独自の認証機能(oauthのaccess_token, refresh_tokenを発行する機能)があるdjango-oauth-toolkitを採用した感じです。

    導入の方法は他のブログ等でたくさん紹介されているので割愛するとして、トークンを発行するリクエストを投げたときに起きた問題と、
    その解決についてまとめたいと思います。

    トークンの発行

    Djangoのビルトインウェブサーバーを使う場合:
    適当に値を書き換えているのであくまで参考で。。
    $ curl -v POST -d "grant_type=password&username=your_username&password=your_password" -u"your_client_id:your_client_secret" http://127.0.0.1:8000/o/token/
    
    *   Trying 127.0.0.1...
    * TCP_NODELAY set
    * Connected to 127.0.0.1 port 8000 (#0)
    * Server auth using Basic with user 'your_client_id'
    > POST /o/token/ HTTP/1.1
    > Host: 127.0.0.1:8000
    > Authorization: Basic (-uの引数をBase64 Encodeした値)
    > User-Agent: curl/7.51.0
    > Accept: */*
    > Content-Length: 50
    > Content-Type: application/x-www-form-urlencoded
    > 
    * upload completely sent off: 50 out of 50 bytes
    * HTTP 1.0, assume close after body
    < HTTP/1.0 200 OK
    < Date: Mon, 02 Jan 2017 11:38:45 GMT
    < Server: WSGIServer/0.2 CPython/3.5.1
    < Cache-Control: no-store
    < Pragma: no-cache
    < Content-Type: application/json
    < X-Frame-Options: SAMEORIGIN
    < 
    * Curl_http_done: called premature == 0
    * Closing connection 0
    {"expires_in": 3600, "scope": "read write", "token_type": "Bearer", "access_token": "cJ0uRtbFuVFTwxFnXdiC9YHa2ywwgo", "refresh_token": "9K8rHrZJExGZ2FbyuXmy9MSZuRY6pL"
    

    こんな感じで正常にトークン情報が受け取れます。

    起きたこと

    しかし、Apache2.2系を使った場合だと、以下のようにエラーが返ってしまいます。
    $ curl -v POST -d "grant_type=password&username=your_username&password=your_password" -u"your_client_id:your_client_secret" http://127.0.0.1:8000/o/token/
    
    *   Trying 127.0.0.1...
    * TCP_NODELAY set
    * Connected to 127.0.0.1 port 8000 (#0)
    * Server auth using Basic with user 'your_client_id'
    > POST /o/token/ HTTP/1.1
    > Host: 127.0.0.1:8000
    > Authorization: Basic (-uの引数をBase64 Encodeした値)
    > User-Agent: curl/7.51.0
    > Accept: */*
    > Content-Length: 50
    > Content-Type: application/x-www-form-urlencoded
    > 
    * upload completely sent off: 50 out of 50 bytes
    < HTTP/1.1 401 UNAUTHORIZED
    < Date: Mon, 02 Jan 2017 11:38:36 GMT
    < Server: Apache/2.2.15 (CentOS)
    < Cache-Control: no-store
    < X-Frame-Options: SAMEORIGIN
    < Pragma: no-cache
    < Connection: close
    < Transfer-Encoding: chunked
    < Content-Type: application/json
    < 
    * Curl_http_done: called premature == 0
    * Closing connection 0
    {"error": "invalid_client"}
    

    解決策

    で、どうしたのか。
    解決策は単純で、Apacheの設定に以下を追記するだけでOKでした。

    WSGIPassAuthorization On
    

    答えが書いてたサイト…w→ {"error": "invalid_client"} #52
    公式のgithubのissueに書かれてたっていうオチ。┐(´д`)┌ヤレヤレ


    Pythonは日本語ドキュメントが充実してないのでハマったときの解決が結構つらいですね。

    人気ブログランキングへ ブログランキング・にほんブログ村へ
    ↑応援よろしくお願いします!m(_ _)m

  • <2017/01/07 17:38>
  • Python
  • PythonDjangorestframeworkoauth-toolkitinvalid_client
  • 新しい記事へ
    Djangoでユーザーログイン後に元いたページにリダイレクトする方法

    古い記事へ
    Vagrant1.8.5とVirtualBox5.1.2でローカル開発環境を作るときにハマった話

profile picture

自己紹介的な何か

@wkmettyでついったーやってます。時々。 6年間勤めたゲーム会社を2018年2月に退職しフリーランスのプログラマに。 WordPress Core, WP-CLI コントリビューター。 お仕事募集中です。