В моем приложении я использую поток кода авторизации для Spotify.
Вот конечная точка обратного вызова авторизации, где я получаю токены от Spotify.
spotify_auth.py
from flask import Blueprint
from flask import Flask, request, session, redirect
spotify_auth_bp = Blueprint('spotify_auth',
__name__,
template_folder='templates',
static_url_path='static')
@spotify_auth_bp.route("/callback", methods=['GET', 'POST'])
def spotify_callback():
SPOTIFY_TOKEN_URL = "https://accounts.spotify.com/api/token"
CLIENT_ID = os.environ.get('SPOTIPY_CLIENT_ID')
CLIENT_SECRET = os.environ.get('SPOTIPY_CLIENT_SECRET')
REDIRECT_URI = os.environ.get('SPOTIPY_REDIRECT_URI')
auth_token = request.args['code']
code_payload = {
"grant_type": "authorization_code",
"code": auth_token,
"redirect_uri": REDIRECT_URI,
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
}
post_request = requests.post(SPOTIFY_TOKEN_URL, data=code_payload)
response_data = json.loads(post_request.text)
access_token = response_data["access_token"]
refresh_token = response_data["refresh_token"]
token_type = response_data["token_type"]
expires_in = response_data["expires_in"]
# At this point, there is to generate a custom token for the frontend
# Either a self-contained signed JWT or a random token
# In case the token is not a JWT, it should be stored in the session (in case of a stateful API)
# or in the database (in case of a stateless API)
# In case of a JWT, the authenticity can be tested by the backend with the signature so it doesn't need to be stored at all
# Let's assume the resulting token is stored in a variable named "token"
res = Response('http://localhost/about', status=302)
res.set_cookie('auth_cookie', token)
return res
Теперь у меня есть эти функции для обработки моего доступа и обновления sh токенов:
def refresh_access_token():
SPOTIFY_TOKEN_URL = "https://accounts.spotify.com/api/token"
code_payload = {
"grant_type": "refresh_token",
"refresh_token": refresh_token,
}
encode = 'application/x-www-form-urlencoded'
auth = base64.b64encode("{}:{}".format(client_id, client_secret).encode())
headers = {"Content-Type" : encode, "Authorization" : "Basic {}".format(auth)}
post_request = requests.post(SPOTIFY_TOKEN_URL, data=code_payload, headers=headers)
response_data = json.loads(post_request.text)
access_token = response_data["access_token"]
refresh_token = response_data["refresh_token"]
token_type = response_data["token_type"]
expires_in = response_data["expires_in"]
# save new tokens to database
user = User.query.filter_by(refresh_token=refresh_token).first()
user.access_token = access_token
user.refresh_token = refresh_token
db.session.commit()
return access_token
def get_token():
# check for cookies
access_token_cookie = request.cookies.get('access_token')
refresh_token_cookie = request.cookies.get('refresh_token')
# check if this is first User login
user = User.query.filter_by(access_token=access_token_cookie).first()
if user:
# Checking if token has expired
now = int(time.time())
token_is_expired = request.cookies.get('expires_in') - now < 60
# Refreshing token if it has expired
if token_is_expired:
# get token for renewal from db
refresh_token = user.refresh_token
# request another access token
access_token = refresh_access_token(refresh_token)
else:
access_token = user.access_token
else:
# first time user
user = User.query.filter_by(id=1).first()
user.access_token_cookie = access_token_cookie
user.refresh_token = refresh_token_cookie
db.session.commit()
access_token = access_token_cookie
return access_token
В идеале я хотел бы импортировать эти функции в мои модули и передавать токен своим ресурсам просто с помощью:
spotify_utils.py
import get_token
token = get_token()
Как поместить эти функции в контекст?
Я узнал, что copy_current_request_context может помочь мне в этом.
Есть идеи?