Как добавить Oauth2 авторизацию к JWT?
Пытаюсь сделать авторизацию с помощью Oauth2 и JWT вместе с FastAPI. Получилось пока сделать так, чтобы при регистрации создавался пользователь и его учетная запись с почтой и паролем и возвращался JWT токен с id пользователя. И чтобы при входе возвращался пользователь.
class Identity(SQLModel):
name: str
username: str
mail: str
password: str
identity_router = APIRouter(prefix="/identity", tags=["Identity"])
@identity_router.post("/signin")
async def signin(response: Response, identity: Identity):
user_identity, token = await identity_service.signin(identity)
if user_identity is None:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
)
response.set_cookie(
key="session_token", value=token, httponly=True, samesite='lax',
expires=datetime.now(timezone.utc) + timedelta(days=JWT_TOKEN_EXPIRE_DAYS)
)
return user_identity
@identity_router.post("/signup")
async def signup(response: Response, identity: Identity):
user_identity, token = await identity_service.signup(identity)
if user_identity is None:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User already registered",
)
response.set_cookie(
key="session_token", value=token, httponly=True, samesite='lax',
expires=datetime.now(timezone.utc) + timedelta(days=JWT_TOKEN_EXPIRE_DAYS)
)
return user_identity
Сейчас пытаюсь добавить получение текущего пользователя, но не совсем понимаю как это сделать. В документации говорят, что нужно использовать oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") и импротировать его в функцию get_current_user(...) Depends(oauth2_scheme). Но что дает oauth2_scheme? В чем отличие oauth2_scheme от моей модели Identity, если мне не нужно использовать скоупы Oauth2?
Ответы (1 шт):
Разобрался как работает Oauth2 авторизация. В документации всё правильно говорят.
Я думал как сделать так, чтобы токен возвращался при регистрации, но оказывается, при регистрации не нужно возвращать токен. Нужно только создавать пользователя в базе. Токен нужно возвращать только при логине в виде {"access_token": token, "token_type": "bearer"}, либо в виде Pydentic модельки с такими же полями.
Сам ентрипоинт с логином должен принимать form_data: OAuth2PasswordRequestForm = Depends(), чтобы потом из него достать пароль password и второе значение с почтой, логином или чем угодно еще username. Можно и принимать свою модель, но тогда уже не будет работать встроенная Oauth2 авторизация, потому что своя модель уже не будет соответствовать стандарту. И в oauth2_scheme = OAuth2PasswordBearer(tokenUrl=...) уже нужно передать путь к логину.
То есть процесс выдачи доступа будет выглядеть так:
- Пользователь регистрируется и сохраняется в базу
- Пользователь логинится и получает токен
- Этот токен передает в заголовке запроса на защищенный энтрипоинт
def get_current_user(token: str = Depends(oauth2_scheme)): ...сам достанет токен из заголовка запроса и его останется только расшифровать
То есть JWT используется только для того, чтобы валидировать токен на бэкенде.