# twitter OAUTH2 PKCE 實做紀錄

By [!!!0xFOMOer#3825](https://paragraph.com/@0xfomoer-3825) · 2022-06-24

---

1\. 前言
------

本文實做如何使用 OAUTH2 PKCE 的方法，來取得不同帳號間的 access token，如此可以只用一支程式控制多個帳號。 由於需要回到 callback url ，所以使用 flask 以及搭配 tweepy 來實做整體的操作。

2\. 實做
------

這份實做是參考 [twauth\_web](https://twauth-web) 來做的，替我省了不少工夫。

### 2.1 twitter developer 設定

首先在 twitter 上需進行以下設定

1.  ebable oauth 2.0
    

![](https://storage.googleapis.com/papyrus_images/6b208d7e9c0aa8c6c8c1333cfd10ab7e718d7ddad15e4a8e9def1288515770f7.png)

1.  填入callback url，我查到有人是沒有辦法用 localhost ，直接用 ip 是比較快也常見的做法。
    
2.  填入website url，一般來說沒特別，可以填自己的 twitter 即可。
    

![](https://storage.googleapis.com/papyrus_images/fb40c1341466a26c9c207303edab52705f595d2e2e4d131323cbd23061652dac.png)

### 2.2 開啟 flask web 與取得使用者 access token

在程式一開始除了啟動 flask 外，我們還需要去連接 twitter server 來取得 handler。範例如下

    oauth2_user_handler = tweepy.OAuth2UserHandler(
        client_id=Client_ID,
        redirect_uri="http://127.0.0.1:5000/callback", 
        scope=["tweet.read","tweet.write", "users.read", "follows.read", "follows.write", "like.read", "like.write", "offline.access"],
        # Client Secret is only necessary if using a confidential client
        client_secret=Client_Secret,
    )
    

*   scope 在 [twitter developer docs](https://developer.twitter.com/en/docs/authentication/oauth-2-0/authorization-code) 上可以看到完整的細節，這邊所選取主要是為了可以完成 like/retweet/reply 、 tag 3 位朋友參加抽獎和可以一直 refresh token 。
    

此外要在 flask 的首頁中開啟 session ，不然在頁面轉換時，會因為 session id 不同，而導致與 twitter 的認證無法通過。

    @app.route('/')
    def hello():
        session_secret_key= os.urandom(24)
        app.config['SECRET_KEY'] =session_secret_key
        app.config['SESSION_COOKIE_NAME'] = "my_session"
    
        return render_template('index.html', SECRET_KEY=session_secret_key)
    
    @app.route('/callback')
    def callback():
        app.config['SECRET_KEY'] =session_secret_key
        app.config['SESSION_COOKIE_NAME'] = "my_session"
    

然後透過下面這行，來產生連到 twitter 做驗證的連節

    authorize_url= oauth2_user_handler.get_authorization_url()
    

點入連結後，可以看到以下畫面。

![](https://storage.googleapis.com/papyrus_images/fe6f76f0e342d8e4d2935d8ced1900e7f3958411c5cdcddac9d9e399a7c4f835.png)

在點下 Authorize app 後，會回到你所提供的 callback 頁面，這時就可以用取得的 state 和 code ，再去要求 access token ，也因此重複此步驟，你可以得到不同 twitter 帳號的 token 來操作。

        response= "http://127.0.0.1:5000/callback?state="+oauth_state+"&code="+oauth_code
        access_token = oauth2_user_handler.fetch_token(response)
    

### 2.3 Refresh token

雖然我們有使用 offline.access 來取得 token ，但 twitter 仍只給這個 token 兩個小時的有效時間，所以可以用以下的方是來更新 token ，達到一直可以使用的目的，範例如下，

    new_access_token= oauth2_user_handler.refresh_token(access_token["refresh_token"])
    access_token= new_access_token
    

### 2.4 其他指令使用注意

由於 ESSENTIAL 只能用 APIv2，且我們又用 ouath2 ，所以很多指令要多給 user\_auth= False ，才能確保指令可以被執行。

    client.like(tweet_id, user_auth= False)
    client.retweet(tweet_id, user_auth= False)
    

如果你也遇到 oauthlib.oauth2.rfc6749.errors.InsecureTransportError 的問題，可以設定以下參數去避開。

    os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
    

3\. 指令限制
--------

最後要注意的是由於 ESSENTIAL 給與的流量不大，所以很容易不小心爆掉。以我自己為例，我剛上線時，應該是指令短時間內送太快，結果 app 整個被限制，並於八小時後被封鎖。還好可以砍掉重練。

4\. 補充資料
--------

*   [教你开发一个简易的推特白名单机器人](https://mirror.xyz/zlexdl.eth/-SLMZ8BPOIalMcxCwfxdMNIDsAF_0hplA1H0p38t37A)，由於我只能用 APIv2 所以裡面許多指令無法套用，但整體的概念是很有用的。
    
*   [OAuth 2.0 系列文目錄](https://blog.yorkxin.org/posts/oauth2-1-introduction.html)，想深入了解 OAuth 2.0 可以看這篇。
    
*   [Twitter 對 OAuth 2.0 所畫的流程圖](https://cdn.cms-twdigitalassets.com/content/dam/developer-twitter/docs/OAuth.png.twimg.1920.png)，或是可以到[文件](https://developer.twitter.com/en/docs/authentication/oauth-2-0/authorization-code)中看，我覺得這個圖很清楚。

---

*Originally published on [!!!0xFOMOer#3825](https://paragraph.com/@0xfomoer-3825/twitter-oauth2-pkce)*
