2f55f898ed
- Implemented Spotify OAuth handling in spotify_client_manager.py to ensure valid access tokens for users. - Created helper functions in spotify_helper.py for refreshing tokens and retrieving user information. - Developed manage_spotify.html template for connecting and managing Spotify accounts, displaying connection status and token information. - Added logging for token management processes to enhance debugging and monitoring. - Introduced a debug client for Spotify interactions to facilitate easier testing and development.
91 lines
4.0 KiB
Python
91 lines
4.0 KiB
Python
"""
|
|
Authentication routes for the Music Round application
|
|
"""
|
|
import os
|
|
from flask import Blueprint, render_template, redirect, url_for, request, flash, current_app, session
|
|
from flask_login import login_user, current_user, logout_user, login_required
|
|
from werkzeug.security import check_password_hash, generate_password_hash
|
|
from musicround.models import User, db
|
|
from datetime import datetime
|
|
import requests
|
|
import secrets
|
|
from musicround.helpers.auth_helpers import oauth, find_or_create_user, update_oauth_tokens, get_spotify_user_info
|
|
|
|
# Create blueprint
|
|
auth_bp = Blueprint('auth', __name__)
|
|
|
|
@auth_bp.route('/')
|
|
def index():
|
|
"""Landing page"""
|
|
if current_user.is_authenticated:
|
|
return redirect(url_for('core.index'))
|
|
return render_template('auth/index.html')
|
|
|
|
@auth_bp.route('/login')
|
|
def login():
|
|
"""Redirect to user login page"""
|
|
return redirect(url_for('users.login'))
|
|
|
|
@auth_bp.route('/login-with-spotify')
|
|
def login_with_spotify():
|
|
"""Start Spotify OAuth flow for login using Authlib."""
|
|
if current_user.is_authenticated:
|
|
return redirect(url_for('core.index'))
|
|
|
|
if not current_app.config.get('SPOTIFY_CLIENT_ID') or not current_app.config.get('SPOTIFY_CLIENT_SECRET'):
|
|
flash('Spotify login is not configured.', 'danger')
|
|
return redirect(url_for('users.login'))
|
|
|
|
# The redirect URI should point to *this* blueprint's callback
|
|
redirect_uri = url_for('auth.callback', _external=True)
|
|
|
|
# Ensure 'show_dialog': 'true' is part of authorize_params in auth_helpers.py
|
|
# when registering the Spotify client.
|
|
return oauth.spotify.authorize_redirect(redirect_uri)
|
|
|
|
@auth_bp.route('/callback')
|
|
def callback():
|
|
"""Handle Spotify OAuth callback for login using Authlib."""
|
|
try:
|
|
token = oauth.spotify.authorize_access_token()
|
|
current_app.logger.debug(f"Spotify token received for login: {token}")
|
|
|
|
# Fetch user info using the token
|
|
spotify_info = get_spotify_user_info(token)
|
|
|
|
if not spotify_info or not spotify_info.get('id'):
|
|
flash('Could not fetch Spotify user information. Please try again.', 'danger')
|
|
current_app.logger.error(f"Failed to get Spotify user info for login. Response: {spotify_info}")
|
|
return redirect(url_for('users.login'))
|
|
|
|
# Find or create user based on Spotify profile
|
|
# This function needs to handle new user creation if they don't exist
|
|
# or link to an existing user if email matches, etc.
|
|
user = find_or_create_user(spotify_info, 'spotify')
|
|
|
|
if not user:
|
|
flash('Could not sign in with Spotify. If you are a new user, registration might be disabled. Please try again or contact support.', 'danger')
|
|
current_app.logger.error(f"Failed to find or create user for Spotify login: {spotify_info.get('email')}")
|
|
return redirect(url_for('users.login'))
|
|
|
|
# Update tokens in the User model
|
|
if update_oauth_tokens(user, token, 'spotify'):
|
|
login_user(user) # Log in the user
|
|
user.last_login = datetime.now()
|
|
db.session.commit()
|
|
flash('Successfully logged in with Spotify!', 'success')
|
|
current_app.logger.info(f"User {user.username} logged in via Spotify ({spotify_info.get('name')})")
|
|
|
|
next_page = request.args.get('next') or session.pop('next_url', None)
|
|
if not next_page or not next_page.startswith('/'):
|
|
next_page = url_for('core.index')
|
|
return redirect(next_page)
|
|
else:
|
|
flash('Failed to store Spotify tokens. Please try again.', 'danger')
|
|
current_app.logger.error(f"Failed to update Spotify tokens for user {user.username} during login.")
|
|
return redirect(url_for('users.login'))
|
|
|
|
except Exception as e:
|
|
current_app.logger.error(f"Error in Spotify login callback: {str(e)}")
|
|
flash(f'An error occurred during Spotify login: {str(e)}.', 'danger')
|
|
return redirect(url_for('users.login')) |