Friday, June 17, 2022
HomeWordPress DevelopmentDealing with Refresh Tokens within the OAuth 2.0 Authorization Code Circulation with...

Dealing with Refresh Tokens within the OAuth 2.0 Authorization Code Circulation with PKCE with Flask


We not too long ago launched OAuth 2.0 Authorization Code Circulation with PKCE to be used with most of our v2 endpoints. As a backend-focused Python developer, I struggled with the circulation since a lot of the code I like to write down focuses on automation duties.

This tutorial will stroll you thru vital ideas associated to refresh tokens utilizing v2 of the Twitter API. In the event you don’t have already got entry to the Twitter API, you may join an account. Additionally, you will have to have OAuth 2.0 turned on in your App’s settings.



Tokens are solely legitimate for 2 hours

I used to be used to working with OAuth 1.0a, the place keys and tokens can be found to be used till they’re revoked. This isn’t the case with OAuth 2.0 Authorization Code Circulation with PKCE. Entry Tokens generated utilizing this circulation are solely legitimate for two hours.



Refresh tokens

Contained in the token object generated from the consent circulation is a refresh token. A refresh token permits an utility to acquire a brand new entry token with out prompting the person to log in once more.

To generate a refresh token, you need to set a scope for offline entry. If I used to be utilizing the handle Tweets endpoint and I wished to Tweet on behalf of a person each six months, I’d use the next line of Python code:

scopes = ["tweet.read", "users.read", "tweet.write", "offline.access"]
Enter fullscreen mode

Exit fullscreen mode



How lengthy are refresh tokens legitimate for?

Refresh tokens keep legitimate for six months, so you’ll want to refresh them a minimum of that usually or extra usually.



Producing tokens

To generate a token utilizing OAuth 2.0 Authorization Code Circulation with PKCE you should use a way just like this instance that permits you to search for an authenticated person’s bookmarks. Because the authenticated person might want to log in straight, and you will want to parse the response, I discovered making a Flask utility allowed for a extra automated course of.

The next code will generate a token and save the token right into a dictionary.

You’ll be working with the next libraries:

  • requests for making HTTP requests

  • requests_oauthlib for working with OAuth 2.0

  • os for parsing atmosphere variables and creating random strings

  • re, base64 and hashlib to create the code problem and code verifier

  • flask for creating an online framework

In the event you don’t have already got flask, requests_oauthlib and requests put in you will want to put in these libraries.

You’ll first have to import the next libraries:

import base64
import hashlib
import os
import re
import requests

from requests_oauthlib import OAuth2Session
from flask import Flask, request, redirect, session, url_for
Enter fullscreen mode

Exit fullscreen mode

First, you will want to set a variable in your app, which is the beginning of each Flask app. Moreover, you will want to set a secret key in your app to be a random string.

app = Flask(__name__)
app.secret_key = os.urandom(50)
Enter fullscreen mode

Exit fullscreen mode

The 2 primary credentials you will want to authenticate with OAuth 2.0 Authorization Code Circulation with PKCE are Consumer ID and Consumer Secret. You possibly can set these as atmosphere variables to make sure safety.

client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
Enter fullscreen mode

Exit fullscreen mode

Additionally, you will have to set a variable in your redirect URL, this must be the identical worth as your callback URL in your App’s settings within the Developer Portal.

redirect_uri = os.environ.get("REDIRECT_URI")
auth_url = "https://twitter.com/i/oauth2/authorize"
token_url = "https://api.twitter.com/2/oauth2/token"
Enter fullscreen mode

Exit fullscreen mode

To outline the permissions of your App, you will want to set the scopes of your utility. Try the authentication mapping information to find out what scopes you will want primarily based on the endpoints you’re utilizing. The scope offline.entry permits you to generate refresh tokens. The scopes for this demo are tweet.learn and customers.learn, which supplies you entry to learn Tweets and acquire details about customers.

scopes = ["tweet.read", "users.read", "offline.access"]
Enter fullscreen mode

Exit fullscreen mode

You have to to set a code verifier which is a safe random string. The code verifier is used to create the code problem.

code_verifier = base64.urlsafe_b64encode(os.urandom(30)).decode("utf-8")
code_verifier = re.sub("[^a-zA-Z0-9]+", "", code_verifier
Enter fullscreen mode

Exit fullscreen mode

With PKCE the code problem is a base64 encoded string of the SHA256 hash of the code verifier.

code_challenge = hashlib.sha256(code_verifier.encode("utf-8")).digest()
code_challenge = base64.urlsafe_b64encode(code_challenge).decode("utf-8")
code_challenge = code_challenge.exchange("=", "")

Enter fullscreen mode

Exit fullscreen mode

Now you can begin with making a login web page that would be the first web page you’ll go to if you run your utility. @app.route("https://dev.to/") signifies it’s the primary touchdown web page. This web page would be the web page that an authenticated person logs into.

@app.route("https://dev.to/")
def demo():
    world twitter
    twitter = OAuth2Session(client_id, redirect_uri=redirect_uri, scope=scopes)
    authorization_url, state = twitter.authorization_url(
        auth_url, code_challenge=code_challenge, code_challenge_method="S256"
    )
    session["oauth_state"] = state
    return redirect(authorization_url)

Enter fullscreen mode

Exit fullscreen mode

After the person logs in, they are going to be directed to the callback. Within the callback you’ll generate an object known as token that comprises a sequence of tokens that features an entry token and a refresh token.

@app.route("/oauth/callback", strategies=["GET"])
def callback():
    code = request.args.get("code")
    token = twitter.fetch_token(
        token_url=token_url,
        client_secret=client_secret,
        code_verifier=code_verifier,
        code=code,
    )
Enter fullscreen mode

Exit fullscreen mode

Now that you simply’ve generated a token object, now you can make a request to the authenticated person lookup, to acquire a person ID that can be utilized to entry lots of our v2 Customers endpoints resembling handle Tweets or handle blocks.
The access_token variable within the token object is the bearer token you’d use to hook up with any of the endpoints that assist OAuth 2.0 Authorization Code Circulation with PKCE.

    user_me = requests.request(
        "GET",
        "https://api.twitter.com/2/customers/me",
        headers={"Authorization": "Bearer {}".format(token["access_token"])},
    ).json()
    print(user_me)
    user_id = user_me["data"]["id"]
Enter fullscreen mode

Exit fullscreen mode

Now that you simply’ve created a token and saved right into a dictionary now you can entry the token dictionary and create a refreshed token by means of this course of. This code must be added to your callback technique. This refreshed_token will comprise a brand new entry token as properly.

tokens = {"new_token": token}
    t = tokens["new_token"]
    refreshed_token = twitter.refresh_token(
          client_id=client_id,
          client_secret=client_secret,
          token_url=token_url,
          refresh_token=t["refresh_token"],
        )
    tokens.replace({"new_token": refreshed_token})
    return "You need to now have a refreshed token"


if __name__ == "__main__":
    app.run()
Enter fullscreen mode

Exit fullscreen mode



Full code

Right here is the total code which you can save as app.py

import base64
import hashlib
import os
import re
import requests

from requests_oauthlib import OAuth2Session
from flask import Flask, request, redirect, session, url_for


app = Flask(__name__)
app.secret_key = os.urandom(50)


client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")

redirect_uri = os.environ.get("REDIRECT_URI")
auth_url = "https://twitter.com/i/oauth2/authorize"
token_url = "https://api.twitter.com/2/oauth2/token"

scopes = ["tweet.read", "users.read", "offline.access"]

code_verifier = base64.urlsafe_b64encode(os.urandom(30)).decode("utf-8")
code_verifier = re.sub("[^a-zA-Z0-9]+", "", code_verifier)

code_challenge = hashlib.sha256(code_verifier.encode("utf-8")).digest()
code_challenge = base64.urlsafe_b64encode(code_challenge).decode("utf-8")
code_challenge = code_challenge.exchange("=", "")


@app.route("https://dev.to/")
def demo():
    world twitter
    twitter = OAuth2Session(client_id, redirect_uri=redirect_uri, scope=scopes)
    authorization_url, state = twitter.authorization_url(
        auth_url, code_challenge=code_challenge, code_challenge_method="S256"
    )
    session["oauth_state"] = state
    return redirect(authorization_url)


@app.route("/oauth/callback", strategies=["GET"])
def callback():
    code = request.args.get("code")
    token = twitter.fetch_token(
        token_url=token_url,
        client_secret=client_secret,
        code_verifier=code_verifier,
        code=code,
    )
    user_me = requests.request(
        "GET",
        "https://api.twitter.com/2/customers/me",
        headers={"Authorization": "Bearer {}".format(token["access_token"])},
    ).json()
    print(user_me)
    user_id = user_me["data"]["id"]
    tokens = {"new_token": token}
    t = tokens["new_token"]
    refreshed_token = twitter.refresh_token(
          client_id=client_id,
          client_secret=client_secret,
          token_url=token_url,
          refresh_token=t["refresh_token"],
        )
    tokens.replace({"new_token": refreshed_token})
    return "You need to now have a refreshed token"


if __name__ == "__main__":
    app.run()

Enter fullscreen mode

Exit fullscreen mode

To run the file domestically you may run the next line:

python app.py
Enter fullscreen mode

Exit fullscreen mode



Subsequent steps

Hopefully, this is usually a place to begin so that you can get began with producing refresh tokens. As a subsequent step, if you’re utilizing Flask you could wish to think about using a schedular to replace your refresh tokens usually in an automatic vogue. Moreover you could wish to contemplate saving your tokens to a database in a safe vogue. This code pattern will also be prolonged to permit you to hook up with any of the endpoints that assist v2 and may be deployed to a server as a part of a extra full utility.

Make sure to tell us on the boards in case you run into any troubles alongside the best way, or Tweet us at @TwitterDev if this tutorial evokes you to create something.



RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments