Implementing X (Twitter) Single Sign-On in FastAPI
Written on
Introduction to Single Sign-On (SSO)
Single Sign-On (SSO) is a user-friendly authentication method that simplifies access to multiple applications by using just one set of login credentials. Instead of managing various usernames and passwords, SSO centralizes the login process, enhancing user convenience and reducing security risks associated with password management. With the growing need for efficient access control, numerous SSO providers have emerged to meet this demand.
Objective
In this guide, we will illustrate how to integrate X (Twitter) Single Sign-On within a FastAPI application for user authentication. For similar implementations with other providers, check out the following resources:
- Facebook SSO in FastAPI
- Microsoft SSO in FastAPI
- Spotify SSO in FastAPI
- Google SSO in FastAPI
- LinkedIn SSO in FastAPI
Implementation Overview
All code snippets from this guide are available in a dedicated GitHub repository, which you can clone or fork to experiment with the implementation or use it for your projects. If you find it helpful, please consider starring it and sharing with others who may benefit!
Application Structure
Our example will feature a basic FastAPI application, equipped with a minimal User Interface crafted with Jinja templates and utilizing SQLite3 for local user storage. The interface will allow users to log in and display a home page featuring counters for users who have registered through various authentication providers.
FastAPI Authentication Mechanism
In this demonstration, we will implement FastAPI with basic credential and cookie authentication. Users will have the option to sign in using X (Twitter) along with traditional login methods.
FastAPI SSO Library
FastAPI SSO is an open-source library designed to standardize the SSO process across popular providers, facilitating easier integration for developers. While there are many solutions available, this library provides a straightforward and effective way to manage SSO.
Setting Up Your X (Twitter) App
To utilize X (Twitter) Single Sign-On, you will need to create an app on the Twitter Developer platform. Here’s how to do it:
- Click on the "Create an App" button to begin.
Create a developer account by filling out a brief form explaining your intended use case. Typically, there is no lengthy review process (as of March 2024). This account will automatically generate a default project and app, which you can modify as needed.
- Select your app from the default project and navigate to "User authentication settings."
- Begin configuring your app. For our purposes, read permissions are sufficient. Set the app type to "Web app."
- Provide your app with a name (you can retain the default) and a homepage URL (using your repository URL if you lack a dedicated page). Specify a "Callback URI / Redirect URL." This URL is where the X (Twitter) sign-in process will redirect after user authentication. For local testing, use a localhost URI. If deploying, ensure this URL corresponds to your actual server settings.
- Save your settings. An information page will appear, displaying your OAuth 2 Client ID and Secret, which you’ll need for the code.
User Interface
Our minimal user interface consists of a simple form that allows users to log in using different sign-in methods.
<!-- HTML Code for the Sign-In Button -->
<a href="/v1/xtwitter/login">Sign in with X (Twitter)</a>
When this button is clicked, it triggers a GET request to the relative path /v1/xtwitter/login. We’ll explore this in the API endpoints section.
API Endpoints
The essential API endpoints for this process are as follows:
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.responses import RedirectResponse
from database_crud import users_db_crud as db_crud
from schemas import UserSignUp
from sqlalchemy.orm import Session
from database import get_db
from fastapi_sso.sso.twitter import TwitterSSO
from starlette.requests import Request
from authentication import create_access_token, SESSION_COOKIE_NAME
from dotenv import load_dotenv
from pathlib import Path
import os
directory_path = Path(__file__).parent
env_file_path = directory_path.parent / '.env'
load_dotenv()
XTWITTER_CLIENT_ID = os.getenv("XTWITTER_CLIENT_ID")
XTWITTER_CLIENT_SECRET = os.getenv("XTWITTER_CLIENT_SECRET")
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
xtwitter_sso = TwitterSSO(
XTWITTER_CLIENT_ID,
XTWITTER_CLIENT_SECRET,
"http://localhost:9999/v1/xtwitter/callback",
allow_insecure_http=True
)
router = APIRouter(prefix="/v1/xtwitter")
@router.get("/login", tags=['X(Twitter) SSO'])
async def xtwitter_login():
with xtwitter_sso:
return await xtwitter_sso.get_login_redirect()
@router.get("/callback", tags=['X(Twitter) SSO'])
async def xtwitter_callback(request: Request, db: Session = Depends(get_db)):
"""Handle the login response from X(Twitter) and return user info."""
try:
with xtwitter_sso:
user = await xtwitter_sso.verify_and_process(request)username = user.email if user.email else user.display_name
user_stored = db_crud.get_user(db, username, user.provider)
if not user_stored:
user_to_add = UserSignUp(
username=username,
fullname=user.display_name
)
user_stored = db_crud.add_user(
db,
user_to_add,
provider=user.provider
)
access_token = create_access_token(
username=user_stored.username,
provider=user.provider
)
response = RedirectResponse(url="/", status_code=status.HTTP_302_FOUND)
response.set_cookie(SESSION_COOKIE_NAME, access_token)
return response
except db_crud.DuplicateError as e:
raise HTTPException(status_code=403, detail=f"{e}")except ValueError as e:
raise HTTPException(status_code=400, detail=f"{e}")except Exception as e:
raise HTTPException(
status_code=500,
detail=f"An unexpected error occurred. Report this message to support: {e}"
)
In this code, environment variables for the X (Twitter) OAuth Client ID and Secret are loaded. The TwitterSSO class from the SSO library manages the authentication flow.
User Sign-In Process
When the user clicks the X (Twitter) sign-in button, the login flow begins. After successful authentication, the app redirects to the specified callback URI, where user data is processed.
user = await xtwitter_sso.verify_and_process(request)
The user's information is captured and can be utilized as needed. In this example, we store the user’s email as their username in the database and issue a JWT token as a cookie in the response. This ensures the user remains signed in during their browser session, and they are then redirected to the home page.
Conclusion
Thank you for taking the time to explore this implementation of X (Twitter) Single Sign-On in FastAPI. I hope you found it insightful!
Support and Feedback
If you found this guide helpful, please consider:
- Leaving a round of applause
- Sharing your thoughts in the comments
- Highlighting your favorite sections
- Sharing it with others who may find it useful
Want more content? Hit the follow button for updates, or subscribe for new releases! You can also connect with me on GitHub, LinkedIn, or X.
Enjoyed this article? Consider buying me a coffee to support future content creation!