Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
8 views7 pages

Oauth2.0 Custom

This document outlines the implementation of an OAuth2 server using FastAPI, featuring both Authorization Code and Client Credentials grants. It includes user and client registration, token generation, and protected routes, utilizing SQLite for database management and JWT for authentication. The document also provides example API requests for registering clients, obtaining authorization codes, and exchanging codes for access tokens.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views7 pages

Oauth2.0 Custom

This document outlines the implementation of an OAuth2 server using FastAPI, featuring both Authorization Code and Client Credentials grants. It includes user and client registration, token generation, and protected routes, utilizing SQLite for database management and JWT for authentication. The document also provides example API requests for registering clients, obtaining authorization codes, and exchanging codes for access tokens.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 7

pip install fastapi uvicorn sqlalchemy sqlite3 passlib bcrypt pyjwt python-dotenv httpx

from fastapi import FastAPI, Depends, HTTPException, status

from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm

from sqlalchemy import Column, Integer, String, create_engine

from sqlalchemy.ext.declarative import declarative_base

from sqlalchemy.orm import sessionmaker, Session

from passlib.context import CryptContext

import jwt

import datetime

import os

from dotenv import load_dotenv

load_dotenv()

# Configuración de JWT

SECRET_KEY = os.getenv("SECRET_KEY", "mysecret")

ALGORITHM = "HS256"

# Configuración de la base de datos SQLite

DATABASE_URL = "sqlite:///./test.db"

engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})

SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base = declarative_base()

# Modelo de usuario y cliente

class User(Base):

__tablename__ = "users"

id = Column(Integer, primary_key=True, index=True)


username = Column(String, unique=True, index=True)

hashed_password = Column(String)

class Client(Base):

__tablename__ = "clients"

id = Column(Integer, primary_key=True, index=True)

client_id = Column(String, unique=True, index=True)

client_secret = Column(String)

redirect_uri = Column(String)

Base.metadata.create_all(bind=engine)

# Contexto de cifrado para contraseñas

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

# OAuth2 esquema para autenticación

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

app = FastAPI()

# Dependencia de sesión de base de datos

def get_db():

db = SessionLocal()

try:

yield db

finally:

db.close()

# Funciones para manejar contraseñas


def get_password_hash(password):

return pwd_context.hash(password)

def verify_password(plain_password, hashed_password):

return pwd_context.verify(plain_password, hashed_password)

# Función para generar tokens JWT

def create_access_token(data: dict, expires_delta: datetime.timedelta = None):

to_encode = data.copy()

expire = datetime.datetime.utcnow() + (expires_delta or datetime.timedelta(minutes=30))

to_encode.update({"exp": expire})

return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)

# **Registro de usuarios**

@app.post("/register/")

def register(username: str, password: str, db: Session = Depends(get_db)):

hashed_password = get_password_hash(password)

db_user = User(username=username, hashed_password=hashed_password)

db.add(db_user)

db.commit()

return {"message": "Usuario registrado correctamente"}

# **Registro de clientes OAuth2**

@app.post("/register_client/")

def register_client(client_id: str, client_secret: str, redirect_uri: str, db: Session =


Depends(get_db)):

hashed_secret = get_password_hash(client_secret)

db_client = Client(client_id=client_id, client_secret=hashed_secret, redirect_uri=redirect_uri)

db.add(db_client)
db.commit()

return {"message": "Cliente registrado correctamente"}

# **Flujo de autorización OAuth2 (Authorization Code)**

@app.get("/authorize")

def authorize(client_id: str, redirect_uri: str, response_type: str = "code", db: Session =
Depends(get_db)):

client = db.query(Client).filter(Client.client_id == client_id, Client.redirect_uri ==


redirect_uri).first()

if not client:

raise HTTPException(status_code=400, detail="Cliente no válido")

auth_code = create_access_token({"client_id": client_id},


expires_delta=datetime.timedelta(minutes=5))

return {"authorization_code": auth_code}

# **Intercambio de authorization code por un token**

@app.post("/token")

def token(grant_type: str, client_id: str = None, client_secret: str = None, code: str = None, db:
Session = Depends(get_db)):

if grant_type == "authorization_code":

if not code:

raise HTTPException(status_code=400, detail="Código de autorización requerido")

try:

payload = jwt.decode(code, SECRET_KEY, algorithms=[ALGORITHM])

access_token = create_access_token({"client_id": payload["client_id"]})

return {"access_token": access_token, "token_type": "bearer"}

except jwt.ExpiredSignatureError:

raise HTTPException(status_code=400, detail="Código expirado")

except jwt.PyJWTError:

raise HTTPException(status_code=400, detail="Código inválido")


elif grant_type == "client_credentials":

if not client_id or not client_secret:

raise HTTPException(status_code=400, detail="Credenciales requeridas")

client = db.query(Client).filter(Client.client_id == client_id).first()

if not client or not verify_password(client_secret, client.client_secret):

raise HTTPException(status_code=400, detail="Credenciales inválidas")

access_token = create_access_token({"client_id": client_id})

return {"access_token": access_token, "token_type": "bearer"}

raise HTTPException(status_code=400, detail="Tipo de grant inválido")

# **Ruta protegida**

@app.get("/protected/")

def protected_route(token: str = Depends(oauth2_scheme)):

try:

payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])

return {"message": f"Acceso concedido a {payload['client_id']}"}

except jwt.PyJWTError:

raise HTTPException(status_code=401, detail="Token inválido")

A) Authorization Code Grant

1. Registrar un cliente OAuth2

sh
CopiarEditar
curl -X POST "http://127.0.0.1:8000/register_client/" \
-H "Content-Type: application/json" \
-d '{"client_id": "my_client", "client_secret": "secret123",
"redirect_uri": "http://localhost/callback"}'

2. Solicitar autorización (Obtener Authorization Code)

sh
CopiarEditar
curl -X GET "http://127.0.0.1:8000/authorize?
client_id=my_client&redirect_uri=http://localhost/callback"

Respuesta esperada:

json
CopiarEditar
{"authorization_code": "eyJhbGciOiJIUzI1NiIsInR5cC..." }

3. Intercambiar Authorization Code por un token

sh
CopiarEditar
curl -X POST "http://127.0.0.1:8000/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code&code=AUTHORIZATION_CODE"

Respuesta esperada:

json
CopiarEditar
{"access_token": "eyJhbGciOiJIUzI1NiIsInR5cC...", "token_type":
"bearer"}

B) Client Credentials Grant

1. Solicitar un token con client credentials

sh
CopiarEditar
curl -X POST "http://127.0.0.1:8000/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d
"grant_type=client_credentials&client_id=my_client&client_secret=se
cret123"

Respuesta esperada:

json
CopiarEditar
{"access_token": "eyJhbGciOiJIUzI1NiIsInR5cC...", "token_type":
"bearer"}
Este ejemplo implementa Authorization Code y Client Credentials en un servidor
OAuth2 en FastAPI. 🚀

You might also like