JWT Authentication in FastAPI | Generating and Verifying Tokens | Password and Encryption using bcrypt

Posted by


JSON Web Token (JWT) – это стандартизированный способ передачи информации между двумя сторонами в формате JSON. JWT не только позволяет аутентифицировать пользователя, но и передавать данные, которые можно использовать для авторизации и проверки подлинности. В этом уроке мы рассмотрим, как использовать JWT для аутентификации пользователей в FastAPI.

FastAPI – это современный фреймворк для создания API с использованием Python. Он предоставляет простой и эффективный способ создания веб-сервисов с автоматической документацией и поддержкой асинхронного программирования.

Для начала нам нужно установить несколько библиотек для работы с JWT и bcrypt. Мы можем сделать это с помощью pip:

pip install pyjwt fastapi uvicorn bcrypt

После установки библиотек мы можем приступить к созданию нашего приложения. Давайте начнем с создания основного файла приложения (например, main.py).

from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer
from pydantic import BaseModel
from typing import Optional
import jwt
import bcrypt

app = FastAPI()

secret_key = "mysecretkey"
algorithm = "HS256"

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

class User(BaseModel):
    username: str
    password: str

class UserInDB(User):
    hashed_password: str

fake_users_db = {
    "johndoe": {
        "username": "johndoe",
        "full_name": "John Doe",
        "email": "johndoe@example.com",
        "hashed_password": bcrypt.hashpw("secret".encode('utf-8'), bcrypt.gensalt())
    }
}

def verify_password(plain_password, hashed_password):
    return bcrypt.checkpw(plain_password.encode('utf-8'), hashed_password)

def get_user(username: str):
    if username in fake_users_db:
        user_dict = fake_users_db[username]
        return UserInDB(**user_dict)

def create_access_token(data: dict):
    encoded_jwt = jwt.encode(data, secret_key, algorithm=algorithm)
    return encoded_jwt

@app.post("/token")
async def login_for_access_token(user: User):
    user_obj = get_user(user.username)
    if not user_obj or not verify_password(user.password, user_obj.hashed_password):
        raise HTTPException(status_code=400, detail="Incorrect username or password")
    access_token = create_access_token(data={"sub": user.username})
    return {"access_token": access_token, "token_type": "bearer"}

@app.get("/users/me")
async def read_users_me(token: str = Depends(oauth2_scheme)):
    try:
        payload = jwt.decode(token, secret_key, algorithms=[algorithm])
        return {"username": payload.get("sub")}
    except jwt.ExpiredSignatureError:
        raise HTTPException(status_code=401, detail="Token has expired")
    except jwt.JWTError:
        raise HTTPException(status_code=401, detail="Could not validate credentials")

В этом примере мы создали два эндпоинта: один для проверки учетных данных и выдачи JWT-токена, а другой для получения информации о текущем пользователе.

Когда пользователь отправляет свои учетные данные на эндпоинт /token, мы проверяем их с помощью функции verify_password и метода bcrypt.checkpw. Если учетные данные верны, мы создаем JWT-токен с помощью функции create_access_token и возвращаем его.

При обращении к эндпоинту /users/me пользователь должен передать полученный ранее JWT-токен в заголовке запроса. Мы декодируем токен с помощью метода jwt.decode и проверяем его подпись и срок действия. Если токен прошел проверку, мы возвращаем информацию о текущем пользователе.

Этот пример показывает основы работы с JWT и bcrypt в FastAPI. Теперь вы можете расширить его функционал и добавить авторизацию пользователей, использование refresh-токенов и многое другое. Надеюсь, этот урок был полезен для вас!

0 0 votes
Article Rating
32 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
@Alex-zl7wg
1 month ago

Превосходная подача материала! Всё подробно и в то же время ничего лишнего. Преподавать ваше призвание! Спасибо за курс.

@Паша-н9ь
1 month ago

спасибо! Все четко и понятно!

@Antinormanisto
1 month ago

мне кажется, я тупой

@user-fo8yv6cf9h
1 month ago

как сделать логаут при такой реализации. у меня как у тебя, но подключена бд. Пробувала через занос токена в блеклист, но в свагере он все равно сохраняеться

@AlexanderITandEng
1 month ago

Сурен, Вы просто легенда. Спасибо вам за такие информативные ролики, где вы показываете не только как сделать, но и как принято/правильно делать. Тем самым создается отличная база знаний для разработчика и он не будет белой вороной в команде. Спасибо Вам!! Продолжайте в том же духе💪💪💪

@helloiveqw5290
1 month ago

Очень классное и понятное видео. Мне как человеку который долгую часть времени изучал плюсы приятно что везде указываются типы данных так как в других видео просто переменные и что где и как хранится не понятно)

@АнтонКородян
1 month ago

Спасибо вам большое за такой детальный материал,
перехожу с django и скажу разница существенная.

@ГлебФёдоров-ч1л
1 month ago

а как в ходе работы быть с токеном? мне каждый раз вручную прописывать добавление его в заголовки или есть какая-то автоматизация?

@sayomortal
1 month ago

Блин, у тебя просто офигенная подача материала, все по делу, с нужными пояснениями, без инфоцыганства. Рад, что вышел на этот канал

@tonyborbozo
1 month ago

при попытки генерации ключей,
выдало 'openssl' is not recognized as an internal or external command,

operable program or batch file.

@Alex89muller
1 month ago

Сурен, Спасибо за видео! Очень круто. Правда на замедленной перемотки приходится смотреть – очень быстро. В остальном объяснения прям супер.

@Artem-sz4rc
1 month ago

легенда

@staid389
1 month ago

Пересматривал последние 15 минут видео пару раз, но никак не могу понять в чем разница между HTTPBearer и OAuth2PasswordBearer🥲

@user-fo8yv6cf9h
1 month ago

дякую

@АлександрАлёхин-р7ю
1 month ago

Сурен, спасибо за твои старания. очень нравятся твои видео. Подписался, лайк поставил. Подскажи пожалуйста, У меня есть задача написать приложение для получения данных с внешнего ресурса, (huntflow). Условно Раз в день мне нужно отправлять запросы на пару endpoint-ов , получать ответы в виде json и писать их в БД. Значит ли это, что мне как таковой . Хватит requests+Pydantic+SqlAlchemy. Для отправки запросов FastApi не используется. Только для обработки входящих?

@CounterSuny
1 month ago

жаль, что в OAuth2PasswordBearer нельзя использовать вместо username какой-нибудь email или login. Я читал где-то решение этой проблемы, но пока без костылей и велосипедов её нормально не решить. Больше всего поржал от документации fastapi где написано что-то вроде: "Забейте, для конечного пользователя вы можете использовать свои обозначения, но на стороне сервера это должно быть username"))))

@arturzhukovets7951
1 month ago

Спасибо за урок! Очень круто! А можешь тезисно описать хронологию использования вот такого вот способа аутентификации со стороны фронта? Я хочу использовать React. Если конкретнее то куда правильнее всего положить этот токен для использования в других запросах?
И будет ли это вообще корректно использовать такой способ auth для обычного сайта или jwt auth используется только для каких-то сервисных АПИ?

@__name__397
1 month ago

Сурен, спасибо большое за видео! Было очень познавательно.
У меня возник такой вопрос после просмотра видео
Есть такое понятие как готовая аутентификация
Получается, это понятие не относится к нашей, так как мы писали его сами?
Или же наша аутентификация считается "готовой"?
Спасибо за ответ!

@antonmislawsky
1 month ago

Классные уроки очень высокого уровня без воды
спасибо

@DaniilReshetnev
1 month ago

Последнее обновление библиотеки JWT Auth 30 минут назад