Skip to content

Oauth2๏ธโƒฃ โฎ๏ธ ๐Ÿ” (& ๐Ÿ”), ๐Ÿ“จ โฎ๏ธ ๐Ÿฅ™ ๐Ÿค

๐Ÿ”œ ๐Ÿ‘ˆ ๐Ÿ‘ฅ โœ”๏ธ ๐ŸŒ ๐Ÿ’‚โ€โ™‚ ๐Ÿ’ง, โžก๏ธ โš’ ๐Ÿˆธ ๐Ÿค™ ๐Ÿ”, โš™๏ธ ๐Ÿฅ™ ๐Ÿค & ๐Ÿ” ๐Ÿ” ๐Ÿ”.

๐Ÿ‘‰ ๐Ÿ“Ÿ ๐Ÿ•ณ ๐Ÿ‘† ๐Ÿ’ช ๐Ÿค™ โš™๏ธ ๐Ÿ‘† ๐Ÿˆธ, ๐Ÿ–Š ๐Ÿ” #๏ธโƒฃ ๐Ÿ‘† ๐Ÿ’ฝ, โ™’๏ธ.

๐Ÿ‘ฅ ๐Ÿ”œ โ–ถ๏ธ โšช๏ธโžก๏ธ ๐ŸŒโ” ๐Ÿ‘ฅ โ—€๏ธ โฎ๏ธ ๐Ÿ“ƒ & ๐Ÿ“ˆ โšซ๏ธ.

๐Ÿ”ƒ ๐Ÿฅ™

๐Ÿฅ™ โ›“ "๐ŸŽป ๐Ÿ•ธ ๐Ÿค".

โšซ๏ธ ๐Ÿฉ ๐Ÿšซ ๐ŸŽป ๐ŸŽš ๐Ÿ“ ๐Ÿ’ง ๐ŸŽป ๐Ÿต ๐Ÿš€. โšซ๏ธ ๐Ÿ‘€ ๐Ÿ’– ๐Ÿ‘‰:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

โšซ๏ธ ๐Ÿšซ ๐Ÿ—œ,, ๐Ÿ™† ๐Ÿ’ช ๐Ÿ›ก โ„น โšช๏ธโžก๏ธ ๐ŸŽš.

โœ‹๏ธ โšซ๏ธ ๐Ÿ›‘. , ๐Ÿ•โ” ๐Ÿ‘† ๐Ÿ“จ ๐Ÿค ๐Ÿ‘ˆ ๐Ÿ‘† โ™จ, ๐Ÿ‘† ๐Ÿ’ช โœ” ๐Ÿ‘ˆ ๐Ÿ‘† ๐Ÿค™ โ™จ โšซ๏ธ.

๐Ÿ‘ˆ ๐ŸŒŒ, ๐Ÿ‘† ๐Ÿ’ช โœ ๐Ÿค โฎ๏ธ ๐Ÿ‘”, โžก๏ธ ๐Ÿ’ฌ, 1๏ธโƒฃ ๐Ÿ—“๏ธ. & โคด๏ธ ๐Ÿ•โ” ๐Ÿ‘ฉโ€๐Ÿ’ป ๐Ÿ‘Ÿ ๐Ÿ”™ โญ ๐Ÿ“† โฎ๏ธ ๐Ÿค, ๐Ÿ‘† ๐Ÿ’ญ ๐Ÿ‘ˆ ๐Ÿ‘ฉโ€๐Ÿ’ป ๐Ÿ•น ๐Ÿ‘† โš™๏ธ.

โฎ๏ธ ๐Ÿ—“๏ธ, ๐Ÿค ๐Ÿ”œ ๐Ÿ•› & ๐Ÿ‘ฉโ€๐Ÿ’ป ๐Ÿ”œ ๐Ÿšซ โœ” & ๐Ÿ”œ โœ”๏ธ ๐Ÿ›‘ ๐Ÿ”„ ๐Ÿคš ๐Ÿ†• ๐Ÿค. & ๐Ÿšฅ ๐Ÿ‘ฉโ€๐Ÿ’ป (โš–๏ธ ๐Ÿฅ‰ ๐Ÿฅณ) ๐Ÿ”„ ๐Ÿ”€ ๐Ÿค ๐Ÿ”€ ๐Ÿ‘”, ๐Ÿ‘† ๐Ÿ”œ ๐Ÿ’ช ๐Ÿ”Ž โšซ๏ธ, โ†ฉ๏ธ ๐Ÿ’ณ ๐Ÿ”œ ๐Ÿšซ ๐Ÿ.

๐Ÿšฅ ๐Ÿ‘† ๐Ÿ’š ๐Ÿคพ โฎ๏ธ ๐Ÿฅ™ ๐Ÿค & ๐Ÿ‘€ โ” ๐Ÿ‘ซ ๐Ÿ‘ท, โœ… https://jwt.io.

โŽ python-jose

๐Ÿ‘ฅ ๐Ÿ’ช โŽ python-jose ๐Ÿ— & โœ” ๐Ÿฅ™ ๐Ÿค ๐Ÿ:

$ pip install "python-jose[cryptography]"

---> 100%

๐Ÿ-๐Ÿ‡ฉ๐Ÿ‡ฌ ๐Ÿšš ๐Ÿ” ๐Ÿ‘ฉโ€๐Ÿ’ป โž•.

๐Ÿ“ฅ ๐Ÿ‘ฅ โš™๏ธ ๐Ÿ‘ 1๏ธโƒฃ: )/โš›.

Tip

๐Ÿ‘‰ ๐Ÿ”ฐ โช โš™๏ธ PyJWT.

โœ‹๏ธ โšซ๏ธ โ„น โš™๏ธ ๐Ÿ-๐Ÿ‡ฉ๐Ÿ‡ฌ โ†ฉ๏ธ โšซ๏ธ ๐Ÿšš ๐ŸŒ โš’ โšช๏ธโžก๏ธ PyJWT โž• โž• ๐Ÿ‘ˆ ๐Ÿ‘† ๐Ÿ’ช ๐Ÿ’ช โช ๐Ÿ•โ” ๐Ÿ— ๐Ÿ› ๏ธ โฎ๏ธ ๐ŸŽ ๐Ÿงฐ.

๐Ÿ” ๐Ÿ”

"๐Ÿ”" โ›“ ๐Ÿญ ๐ŸŽš (๐Ÿ” ๐Ÿ‘‰ ๐Ÿ’ผ) ๐Ÿ”˜ ๐Ÿ” ๐Ÿ”ข (๐ŸŽป) ๐Ÿ‘ˆ ๐Ÿ‘€ ๐Ÿ’– ๐Ÿ™ƒ.

๐Ÿ•โ” ๐Ÿ‘† ๐Ÿšถโ€โ™€๏ธ โšซ๏ธโ” ๐ŸŽ ๐ŸŽš (โšซ๏ธโ” ๐ŸŽ ๐Ÿ”) ๐Ÿ‘† ๐Ÿคš โšซ๏ธโ” ๐ŸŽ ๐Ÿ™ƒ.

โœ‹๏ธ ๐Ÿ‘† ๐Ÿšซ๐Ÿ”œ ๐Ÿ—œ โšช๏ธโžก๏ธ ๐Ÿ™ƒ ๐Ÿ”™ ๐Ÿ”.

โšซ๏ธโ” โš™๏ธ ๐Ÿ” ๐Ÿ”

๐Ÿšฅ ๐Ÿ‘† ๐Ÿ’ฝ ๐Ÿ“Ž, ๐Ÿง™โ€โ™€ ๐Ÿ† ๐Ÿšซ โœ”๏ธ ๐Ÿ‘† ๐Ÿ‘ฉโ€๐Ÿ’ป' ๐Ÿ”ข ๐Ÿ”, ๐Ÿ•ด#๏ธโƒฃ.

, ๐Ÿง™โ€โ™€ ๐Ÿ† ๐Ÿšซ ๐Ÿ’ช ๐Ÿ”„ โš™๏ธ ๐Ÿ‘ˆ ๐Ÿ” โž•1๏ธโƒฃ โš™๏ธ (๐Ÿ“š ๐Ÿ‘ฉโ€๐Ÿ’ป โš™๏ธ ๐ŸŽ ๐Ÿ” ๐ŸŒ, ๐Ÿ‘‰ ๐Ÿ”œ โš ).

โŽ passlib

๐Ÿ‡ธ๐Ÿ‡ฒ ๐Ÿ‘‘ ๐Ÿ ๐Ÿ“ฆ ๐Ÿต ๐Ÿ”#๏ธโƒฃ.

โšซ๏ธ ๐Ÿ•โ€๐Ÿฆบ ๐Ÿ“š ๐Ÿ” ๐Ÿ” ๐Ÿ“Š & ๐Ÿš™ ๐Ÿ‘ท โฎ๏ธ ๐Ÿ‘ซ.

๐Ÿ‘ ๐Ÿ“Š "๐Ÿก".

, โŽ ๐Ÿ‡ธ๐Ÿ‡ฒ โฎ๏ธ ๐Ÿก:

$ pip install "passlib[bcrypt]"

---> 100%

Tip

โฎ๏ธ passlib, ๐Ÿ‘† ๐Ÿ’ช ๐Ÿ”— โšซ๏ธ ๐Ÿ’ช โœ ๐Ÿ” โœ โœณ, ๐Ÿบ ๐Ÿ’‚โ€โ™‚ ๐Ÿ”Œ-โš–๏ธ ๐Ÿ“š ๐ŸŽ.

, ๐Ÿ‘† ๐Ÿ”œ ๐Ÿ’ช, ๐Ÿ–ผ, ๐Ÿ’ฐ ๐ŸŽ ๐Ÿ“Š โšช๏ธโžก๏ธ โœณ ๐Ÿˆธ ๐Ÿ’ฝ โฎ๏ธ FastAPI ๐Ÿˆธ. โš–๏ธ ๐Ÿ“‰ โ†” โœณ ๐Ÿˆธ โš™๏ธ ๐ŸŽ ๐Ÿ’ฝ.

& ๐Ÿ‘† ๐Ÿ‘ฉโ€๐Ÿ’ป ๐Ÿ”œ ๐Ÿ’ช ๐Ÿ’ณ โšช๏ธโžก๏ธ ๐Ÿ‘† โœณ ๐Ÿ“ฑ โš–๏ธ โšช๏ธโžก๏ธ ๐Ÿ‘† FastAPI ๐Ÿ“ฑ, ๐ŸŽ ๐Ÿ•ฐ.

#๏ธโƒฃ & โœ” ๐Ÿ”

๐Ÿ—„ ๐Ÿงฐ ๐Ÿ‘ฅ ๐Ÿ’ช โšช๏ธโžก๏ธ passlib.

โœ ๐Ÿ‡ธ๐Ÿ‡ฒ "๐Ÿ”‘". ๐Ÿ‘‰ โšซ๏ธโ” ๐Ÿ”œ โš™๏ธ #๏ธโƒฃ & โœ” ๐Ÿ”.

Tip

๐Ÿ‡ธ๐Ÿ‡ฒ ๐Ÿ”‘ โœ”๏ธ ๐Ÿ› ๏ธ โš™๏ธ ๐ŸŽ ๐Ÿ” ๐Ÿ“Š, ๐Ÿ”Œ ๐Ÿ˜ข ๐Ÿ— ๐Ÿ• ๐Ÿ•ด โœ” โœ” ๐Ÿ‘ซ, โ™’๏ธ.

๐Ÿ–ผ, ๐Ÿ‘† ๐Ÿ’ช โš™๏ธ โšซ๏ธ โœ & โœ” ๐Ÿ” ๐Ÿ— โž•1๏ธโƒฃ โš™๏ธ (๐Ÿ’– โœณ) โœ‹๏ธ #๏ธโƒฃ ๐Ÿ™† ๐Ÿ†• ๐Ÿ” โฎ๏ธ ๐ŸŽ ๐Ÿ“Š ๐Ÿ’– ๐Ÿก.

& ๐Ÿ”— โฎ๏ธ ๐ŸŒ ๐Ÿ‘ซ ๐ŸŽ ๐Ÿ•ฐ.

โœ ๐Ÿš™ ๐Ÿ”ข #๏ธโƒฃ ๐Ÿ” ๐Ÿ‘Ÿ โšช๏ธโžก๏ธ ๐Ÿ‘ฉโ€๐Ÿ’ป.

& โž•1๏ธโƒฃ ๐Ÿš™ โœ” ๐Ÿšฅ ๐Ÿ“จ ๐Ÿ” ๐Ÿ #๏ธโƒฃ ๐Ÿช.

& โž•1๏ธโƒฃ 1๏ธโƒฃ ๐Ÿ”“ & ๐Ÿ“จ ๐Ÿ‘ฉโ€๐Ÿ’ป.

from datetime import datetime, timedelta, timezone
from typing import Union

from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError, jwt
from passlib.context import CryptContext
from pydantic import BaseModel

# to get a string like this run:
# openssl rand -hex 32
SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30


fake_users_db = {
    "johndoe": {
        "username": "johndoe",
        "full_name": "John Doe",
        "email": "johndoe@example.com",
        "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW",
        "disabled": False,
    }
}


class Token(BaseModel):
    access_token: str
    token_type: str


class TokenData(BaseModel):
    username: Union[str, None] = None


class User(BaseModel):
    username: str
    email: Union[str, None] = None
    full_name: Union[str, None] = None
    disabled: Union[bool, None] = None


class UserInDB(User):
    hashed_password: str


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

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

app = FastAPI()


def verify_password(plain_password, hashed_password):
    return pwd_context.verify(plain_password, hashed_password)


def get_password_hash(password):
    return pwd_context.hash(password)


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


def authenticate_user(fake_db, username: str, password: str):
    user = get_user(fake_db, username)
    if not user:
        return False
    if not verify_password(password, user.hashed_password):
        return False
    return user


def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.now(timezone.utc) + expires_delta
    else:
        expire = datetime.now(timezone.utc) + timedelta(minutes=15)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt


async def get_current_user(token: str = Depends(oauth2_scheme)):
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
        token_data = TokenData(username=username)
    except JWTError:
        raise credentials_exception
    user = get_user(fake_users_db, username=token_data.username)
    if user is None:
        raise credentials_exception
    return user


async def get_current_active_user(current_user: User = Depends(get_current_user)):
    if current_user.disabled:
        raise HTTPException(status_code=400, detail="Inactive user")
    return current_user


@app.post("/token", response_model=Token)
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
    user = authenticate_user(fake_users_db, form_data.username, form_data.password)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": user.username}, expires_delta=access_token_expires
    )
    return {"access_token": access_token, "token_type": "bearer"}


@app.get("/users/me/", response_model=User)
async def read_users_me(current_user: User = Depends(get_current_active_user)):
    return current_user


@app.get("/users/me/items/")
async def read_own_items(current_user: User = Depends(get_current_active_user)):
    return [{"item_id": "Foo", "owner": current_user.username}]
from datetime import datetime, timedelta, timezone

from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError, jwt
from passlib.context import CryptContext
from pydantic import BaseModel

# to get a string like this run:
# openssl rand -hex 32
SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30


fake_users_db = {
    "johndoe": {
        "username": "johndoe",
        "full_name": "John Doe",
        "email": "johndoe@example.com",
        "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW",
        "disabled": False,
    }
}


class Token(BaseModel):
    access_token: str
    token_type: str


class TokenData(BaseModel):
    username: str | None = None


class User(BaseModel):
    username: str
    email: str | None = None
    full_name: str | None = None
    disabled: bool | None = None


class UserInDB(User):
    hashed_password: str


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

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

app = FastAPI()


def verify_password(plain_password, hashed_password):
    return pwd_context.verify(plain_password, hashed_password)


def get_password_hash(password):
    return pwd_context.hash(password)


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


def authenticate_user(fake_db, username: str, password: str):
    user = get_user(fake_db, username)
    if not user:
        return False
    if not verify_password(password, user.hashed_password):
        return False
    return user


def create_access_token(data: dict, expires_delta: timedelta | None = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.now(timezone.utc) + expires_delta
    else:
        expire = datetime.now(timezone.utc) + timedelta(minutes=15)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt


async def get_current_user(token: str = Depends(oauth2_scheme)):
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
        token_data = TokenData(username=username)
    except JWTError:
        raise credentials_exception
    user = get_user(fake_users_db, username=token_data.username)
    if user is None:
        raise credentials_exception
    return user


async def get_current_active_user(current_user: User = Depends(get_current_user)):
    if current_user.disabled:
        raise HTTPException(status_code=400, detail="Inactive user")
    return current_user


@app.post("/token", response_model=Token)
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
    user = authenticate_user(fake_users_db, form_data.username, form_data.password)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": user.username}, expires_delta=access_token_expires
    )
    return {"access_token": access_token, "token_type": "bearer"}


@app.get("/users/me/", response_model=User)
async def read_users_me(current_user: User = Depends(get_current_active_user)):
    return current_user


@app.get("/users/me/items/")
async def read_own_items(current_user: User = Depends(get_current_active_user)):
    return [{"item_id": "Foo", "owner": current_user.username}]

Note

๐Ÿšฅ ๐Ÿ‘† โœ… ๐Ÿ†• (โŒ) ๐Ÿ’ฝ fake_users_db, ๐Ÿ‘† ๐Ÿ”œ ๐Ÿ‘€ โ” #๏ธโƒฃ ๐Ÿ” ๐Ÿ‘€ ๐Ÿ’– ๐Ÿ”œ: "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW".

๐Ÿต ๐Ÿฅ™ ๐Ÿค

๐Ÿ—„ ๐Ÿ•น โŽ.

โœ ๐ŸŽฒ ใŠ™ ๐Ÿ”‘ ๐Ÿ‘ˆ ๐Ÿ”œ โš™๏ธ ๐Ÿ›‘ ๐Ÿฅ™ ๐Ÿค.

๐Ÿ— ๐Ÿ” ๐ŸŽฒ ใŠ™ ๐Ÿ”‘ โš™๏ธ ๐Ÿ“‹:

$ openssl rand -hex 32

09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7

& ๐Ÿ“ ๐Ÿ”ข ๐Ÿ”ข SECRET_KEY (๐Ÿšซ โš™๏ธ 1๏ธโƒฃ ๐Ÿ–ผ).

โœ ๐Ÿ”ข ALGORITHM โฎ๏ธ ๐Ÿ“Š โš™๏ธ ๐Ÿ›‘ ๐Ÿฅ™ ๐Ÿค & โš’ โšซ๏ธ "HS256".

โœ ๐Ÿ”ข ๐Ÿ‘” ๐Ÿค.

๐Ÿ”ฌ Pydantic ๐Ÿท ๐Ÿ‘ˆ ๐Ÿ”œ โš™๏ธ ๐Ÿค ๐Ÿ”— ๐Ÿ“จ.

โœ ๐Ÿš™ ๐Ÿ”ข ๐Ÿ— ๐Ÿ†• ๐Ÿ” ๐Ÿค.

from datetime import datetime, timedelta, timezone
from typing import Union

from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError, jwt
from passlib.context import CryptContext
from pydantic import BaseModel

# to get a string like this run:
# openssl rand -hex 32
SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30


fake_users_db = {
    "johndoe": {
        "username": "johndoe",
        "full_name": "John Doe",
        "email": "johndoe@example.com",
        "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW",
        "disabled": False,
    }
}


class Token(BaseModel):
    access_token: str
    token_type: str


class TokenData(BaseModel):
    username: Union[str, None] = None


class User(BaseModel):
    username: str
    email: Union[str, None] = None
    full_name: Union[str, None] = None
    disabled: Union[bool, None] = None


class UserInDB(User):
    hashed_password: str


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

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

app = FastAPI()


def verify_password(plain_password, hashed_password):
    return pwd_context.verify(plain_password, hashed_password)


def get_password_hash(password):
    return pwd_context.hash(password)


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


def authenticate_user(fake_db, username: str, password: str):
    user = get_user(fake_db, username)
    if not user:
        return False
    if not verify_password(password, user.hashed_password):
        return False
    return user


def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.now(timezone.utc) + expires_delta
    else:
        expire = datetime.now(timezone.utc) + timedelta(minutes=15)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt


async def get_current_user(token: str = Depends(oauth2_scheme)):
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
        token_data = TokenData(username=username)
    except JWTError:
        raise credentials_exception
    user = get_user(fake_users_db, username=token_data.username)
    if user is None:
        raise credentials_exception
    return user


async def get_current_active_user(current_user: User = Depends(get_current_user)):
    if current_user.disabled:
        raise HTTPException(status_code=400, detail="Inactive user")
    return current_user


@app.post("/token", response_model=Token)
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
    user = authenticate_user(fake_users_db, form_data.username, form_data.password)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": user.username}, expires_delta=access_token_expires
    )
    return {"access_token": access_token, "token_type": "bearer"}


@app.get("/users/me/", response_model=User)
async def read_users_me(current_user: User = Depends(get_current_active_user)):
    return current_user


@app.get("/users/me/items/")
async def read_own_items(current_user: User = Depends(get_current_active_user)):
    return [{"item_id": "Foo", "owner": current_user.username}]
from datetime import datetime, timedelta, timezone

from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError, jwt
from passlib.context import CryptContext
from pydantic import BaseModel

# to get a string like this run:
# openssl rand -hex 32
SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30


fake_users_db = {
    "johndoe": {
        "username": "johndoe",
        "full_name": "John Doe",
        "email": "johndoe@example.com",
        "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW",
        "disabled": False,
    }
}


class Token(BaseModel):
    access_token: str
    token_type: str


class TokenData(BaseModel):
    username: str | None = None


class User(BaseModel):
    username: str
    email: str | None = None
    full_name: str | None = None
    disabled: bool | None = None


class UserInDB(User):
    hashed_password: str


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

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

app = FastAPI()


def verify_password(plain_password, hashed_password):
    return pwd_context.verify(plain_password, hashed_password)


def get_password_hash(password):
    return pwd_context.hash(password)


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


def authenticate_user(fake_db, username: str, password: str):
    user = get_user(fake_db, username)
    if not user:
        return False
    if not verify_password(password, user.hashed_password):
        return False
    return user


def create_access_token(data: dict, expires_delta: timedelta | None = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.now(timezone.utc) + expires_delta
    else:
        expire = datetime.now(timezone.utc) + timedelta(minutes=15)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt


async def get_current_user(token: str = Depends(oauth2_scheme)):
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
        token_data = TokenData(username=username)
    except JWTError:
        raise credentials_exception
    user = get_user(fake_users_db, username=token_data.username)
    if user is None:
        raise credentials_exception
    return user


async def get_current_active_user(current_user: User = Depends(get_current_user)):
    if current_user.disabled:
        raise HTTPException(status_code=400, detail="Inactive user")
    return current_user


@app.post("/token", response_model=Token)
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
    user = authenticate_user(fake_users_db, form_data.username, form_data.password)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": user.username}, expires_delta=access_token_expires
    )
    return {"access_token": access_token, "token_type": "bearer"}


@app.get("/users/me/", response_model=User)
async def read_users_me(current_user: User = Depends(get_current_active_user)):
    return current_user


@app.get("/users/me/items/")
async def read_own_items(current_user: User = Depends(get_current_active_user)):
    return [{"item_id": "Foo", "owner": current_user.username}]

โ„น ๐Ÿ”—

โ„น get_current_user ๐Ÿ“จ ๐ŸŽ ๐Ÿค โญ, โœ‹๏ธ ๐Ÿ‘‰ ๐Ÿ•ฐ, โš™๏ธ ๐Ÿฅ™ ๐Ÿค.

๐Ÿ”ฃ ๐Ÿ“จ ๐Ÿค, โœ” โšซ๏ธ, & ๐Ÿ“จ โฎ๏ธ ๐Ÿ‘ฉโ€๐Ÿ’ป.

๐Ÿšฅ ๐Ÿค โŒ, ๐Ÿ“จ ๐Ÿ‡บ๐Ÿ‡ธ๐Ÿ” โŒ โ–ถ๏ธ๏ธ โ†–๏ธ.

from datetime import datetime, timedelta, timezone
from typing import Union

from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError, jwt
from passlib.context import CryptContext
from pydantic import BaseModel

# to get a string like this run:
# openssl rand -hex 32
SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30


fake_users_db = {
    "johndoe": {
        "username": "johndoe",
        "full_name": "John Doe",
        "email": "johndoe@example.com",
        "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW",
        "disabled": False,
    }
}


class Token(BaseModel):
    access_token: str
    token_type: str


class TokenData(BaseModel):
    username: Union[str, None] = None


class User(BaseModel):
    username: str
    email: Union[str, None] = None
    full_name: Union[str, None] = None
    disabled: Union[bool, None] = None


class UserInDB(User):
    hashed_password: str


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

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

app = FastAPI()


def verify_password(plain_password, hashed_password):
    return pwd_context.verify(plain_password, hashed_password)


def get_password_hash(password):
    return pwd_context.hash(password)


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


def authenticate_user(fake_db, username: str, password: str):
    user = get_user(fake_db, username)
    if not user:
        return False
    if not verify_password(password, user.hashed_password):
        return False
    return user


def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.now(timezone.utc) + expires_delta
    else:
        expire = datetime.now(timezone.utc) + timedelta(minutes=15)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt


async def get_current_user(token: str = Depends(oauth2_scheme)):
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
        token_data = TokenData(username=username)
    except JWTError:
        raise credentials_exception
    user = get_user(fake_users_db, username=token_data.username)
    if user is None:
        raise credentials_exception
    return user


async def get_current_active_user(current_user: User = Depends(get_current_user)):
    if current_user.disabled:
        raise HTTPException(status_code=400, detail="Inactive user")
    return current_user


@app.post("/token", response_model=Token)
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
    user = authenticate_user(fake_users_db, form_data.username, form_data.password)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": user.username}, expires_delta=access_token_expires
    )
    return {"access_token": access_token, "token_type": "bearer"}


@app.get("/users/me/", response_model=User)
async def read_users_me(current_user: User = Depends(get_current_active_user)):
    return current_user


@app.get("/users/me/items/")
async def read_own_items(current_user: User = Depends(get_current_active_user)):
    return [{"item_id": "Foo", "owner": current_user.username}]
from datetime import datetime, timedelta, timezone

from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError, jwt
from passlib.context import CryptContext
from pydantic import BaseModel

# to get a string like this run:
# openssl rand -hex 32
SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30


fake_users_db = {
    "johndoe": {
        "username": "johndoe",
        "full_name": "John Doe",
        "email": "johndoe@example.com",
        "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW",
        "disabled": False,
    }
}


class Token(BaseModel):
    access_token: str
    token_type: str


class TokenData(BaseModel):
    username: str | None = None


class User(BaseModel):
    username: str
    email: str | None = None
    full_name: str | None = None
    disabled: bool | None = None


class UserInDB(User):
    hashed_password: str


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

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

app = FastAPI()


def verify_password(plain_password, hashed_password):
    return pwd_context.verify(plain_password, hashed_password)


def get_password_hash(password):
    return pwd_context.hash(password)


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


def authenticate_user(fake_db, username: str, password: str):
    user = get_user(fake_db, username)
    if not user:
        return False
    if not verify_password(password, user.hashed_password):
        return False
    return user


def create_access_token(data: dict, expires_delta: timedelta | None = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.now(timezone.utc) + expires_delta
    else:
        expire = datetime.now(timezone.utc) + timedelta(minutes=15)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt


async def get_current_user(token: str = Depends(oauth2_scheme)):
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
        token_data = TokenData(username=username)
    except JWTError:
        raise credentials_exception
    user = get_user(fake_users_db, username=token_data.username)
    if user is None:
        raise credentials_exception
    return user


async def get_current_active_user(current_user: User = Depends(get_current_user)):
    if current_user.disabled:
        raise HTTPException(status_code=400, detail="Inactive user")
    return current_user


@app.post("/token", response_model=Token)
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
    user = authenticate_user(fake_users_db, form_data.username, form_data.password)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": user.username}, expires_delta=access_token_expires
    )
    return {"access_token": access_token, "token_type": "bearer"}


@app.get("/users/me/", response_model=User)
async def read_users_me(current_user: User = Depends(get_current_active_user)):
    return current_user


@app.get("/users/me/items/")
async def read_own_items(current_user: User = Depends(get_current_active_user)):
    return [{"item_id": "Foo", "owner": current_user.username}]

โ„น /token โžก ๐Ÿ› ๏ธ

โœ timedelta โฎ๏ธ ๐Ÿ‘” ๐Ÿ•ฐ ๐Ÿค.

โœ ๐ŸŽฐ ๐Ÿฅ™ ๐Ÿ” ๐Ÿค & ๐Ÿ“จ โšซ๏ธ.

from datetime import datetime, timedelta, timezone
from typing import Union

from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError, jwt
from passlib.context import CryptContext
from pydantic import BaseModel

# to get a string like this run:
# openssl rand -hex 32
SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30


fake_users_db = {
    "johndoe": {
        "username": "johndoe",
        "full_name": "John Doe",
        "email": "johndoe@example.com",
        "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW",
        "disabled": False,
    }
}


class Token(BaseModel):
    access_token: str
    token_type: str


class TokenData(BaseModel):
    username: Union[str, None] = None


class User(BaseModel):
    username: str
    email: Union[str, None] = None
    full_name: Union[str, None] = None
    disabled: Union[bool, None] = None


class UserInDB(User):
    hashed_password: str


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

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

app = FastAPI()


def verify_password(plain_password, hashed_password):
    return pwd_context.verify(plain_password, hashed_password)


def get_password_hash(password):
    return pwd_context.hash(password)


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


def authenticate_user(fake_db, username: str, password: str):
    user = get_user(fake_db, username)
    if not user:
        return False
    if not verify_password(password, user.hashed_password):
        return False
    return user


def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.now(timezone.utc) + expires_delta
    else:
        expire = datetime.now(timezone.utc) + timedelta(minutes=15)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt


async def get_current_user(token: str = Depends(oauth2_scheme)):
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
        token_data = TokenData(username=username)
    except JWTError:
        raise credentials_exception
    user = get_user(fake_users_db, username=token_data.username)
    if user is None:
        raise credentials_exception
    return user


async def get_current_active_user(current_user: User = Depends(get_current_user)):
    if current_user.disabled:
        raise HTTPException(status_code=400, detail="Inactive user")
    return current_user


@app.post("/token", response_model=Token)
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
    user = authenticate_user(fake_users_db, form_data.username, form_data.password)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": user.username}, expires_delta=access_token_expires
    )
    return {"access_token": access_token, "token_type": "bearer"}


@app.get("/users/me/", response_model=User)
async def read_users_me(current_user: User = Depends(get_current_active_user)):
    return current_user


@app.get("/users/me/items/")
async def read_own_items(current_user: User = Depends(get_current_active_user)):
    return [{"item_id": "Foo", "owner": current_user.username}]
from datetime import datetime, timedelta, timezone

from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError, jwt
from passlib.context import CryptContext
from pydantic import BaseModel

# to get a string like this run:
# openssl rand -hex 32
SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30


fake_users_db = {
    "johndoe": {
        "username": "johndoe",
        "full_name": "John Doe",
        "email": "johndoe@example.com",
        "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW",
        "disabled": False,
    }
}


class Token(BaseModel):
    access_token: str
    token_type: str


class TokenData(BaseModel):
    username: str | None = None


class User(BaseModel):
    username: str
    email: str | None = None
    full_name: str | None = None
    disabled: bool | None = None


class UserInDB(User):
    hashed_password: str


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

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

app = FastAPI()


def verify_password(plain_password, hashed_password):
    return pwd_context.verify(plain_password, hashed_password)


def get_password_hash(password):
    return pwd_context.hash(password)


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


def authenticate_user(fake_db, username: str, password: str):
    user = get_user(fake_db, username)
    if not user:
        return False
    if not verify_password(password, user.hashed_password):
        return False
    return user


def create_access_token(data: dict, expires_delta: timedelta | None = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.now(timezone.utc) + expires_delta
    else:
        expire = datetime.now(timezone.utc) + timedelta(minutes=15)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt


async def get_current_user(token: str = Depends(oauth2_scheme)):
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
        token_data = TokenData(username=username)
    except JWTError:
        raise credentials_exception
    user = get_user(fake_users_db, username=token_data.username)
    if user is None:
        raise credentials_exception
    return user


async def get_current_active_user(current_user: User = Depends(get_current_user)):
    if current_user.disabled:
        raise HTTPException(status_code=400, detail="Inactive user")
    return current_user


@app.post("/token", response_model=Token)
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
    user = authenticate_user(fake_users_db, form_data.username, form_data.password)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": user.username}, expires_delta=access_token_expires
    )
    return {"access_token": access_token, "token_type": "bearer"}


@app.get("/users/me/", response_model=User)
async def read_users_me(current_user: User = Depends(get_current_active_user)):
    return current_user


@app.get("/users/me/items/")
async def read_own_items(current_user: User = Depends(get_current_active_user)):
    return [{"item_id": "Foo", "owner": current_user.username}]

๐Ÿ“ก โ„น ๐Ÿ”ƒ ๐Ÿฅ™ "๐Ÿ“„" sub

๐Ÿฅ™ ๐Ÿ”ง ๐Ÿ’ฌ ๐Ÿ‘ˆ ๐Ÿ“ค ๐Ÿ”‘ sub, โฎ๏ธ ๐Ÿ“„ ๐Ÿค.

โšซ๏ธ ๐Ÿ“ฆ โš™๏ธ โšซ๏ธ, โœ‹๏ธ ๐Ÿ‘ˆ ๐ŸŒโ” ๐Ÿ‘† ๐Ÿ”œ ๐Ÿšฎ ๐Ÿ‘ฉโ€๐Ÿ’ป ๐Ÿ†”, ๐Ÿ‘ฅ โš™๏ธ โšซ๏ธ ๐Ÿ“ฅ.

๐Ÿฅ™ 5๏ธโƒฃ๐Ÿ“† โš™๏ธ ๐ŸŽ ๐Ÿ‘œ โ†–๏ธ โšช๏ธโžก๏ธ โš– ๐Ÿ‘ฉโ€๐Ÿ’ป & ๐Ÿค ๐Ÿ‘ซ ๐ŸŽญ ๐Ÿ› ๏ธ ๐Ÿ”— ๐Ÿ”› ๐Ÿ‘† ๐Ÿ› ๏ธ.

๐Ÿ–ผ, ๐Ÿ‘† ๐Ÿ’ช ๐Ÿ”ฌ "๐Ÿš˜" โš–๏ธ "๐Ÿ“ฐ ๐Ÿค".

โคด๏ธ ๐Ÿ‘† ๐Ÿ’ช ๐Ÿšฎ โœ” ๐Ÿ”ƒ ๐Ÿ‘ˆ ๐Ÿ‘จโ€๐Ÿ’ผ, ๐Ÿ’– "๐Ÿ’พ" (๐Ÿš˜) โš–๏ธ "โœ" (๐Ÿ“ฐ).

& โคด๏ธ, ๐Ÿ‘† ๐Ÿ’ช ๐Ÿค ๐Ÿ‘ˆ ๐Ÿฅ™ ๐Ÿค ๐Ÿ‘ฉโ€๐Ÿ’ป (โš–๏ธ ๐Ÿค–), & ๐Ÿ‘ซ ๐Ÿ’ช โš™๏ธ โšซ๏ธ ๐ŸŽญ ๐Ÿ‘ˆ ๐ŸŽฏ (๐Ÿ’พ ๐Ÿš˜, โš–๏ธ โœ ๐Ÿ“ฐ ๐Ÿค) ๐Ÿต ๐Ÿ’†โ€โ™‚ โœ”๏ธ ๐Ÿง, โฎ๏ธ ๐Ÿฅ™ ๐Ÿค ๐Ÿ‘† ๐Ÿ› ๏ธ ๐Ÿ— ๐Ÿ‘ˆ.

โš™๏ธ ๐Ÿ‘ซ ๐Ÿ’ญ, ๐Ÿฅ™ ๐Ÿ’ช โš™๏ธ ๐ŸŒŒ ๐ŸŒ– ๐Ÿค“ ๐Ÿ˜.

๐Ÿ“š ๐Ÿ’ผ, ๐Ÿ“š ๐Ÿ‘ˆ ๐Ÿ‘จโ€๐Ÿ’ผ ๐Ÿ’ช โœ”๏ธ ๐ŸŽ ๐Ÿ†”, โžก๏ธ ๐Ÿ’ฌ foo (๐Ÿ‘ฉโ€๐Ÿ’ป foo, ๐Ÿš˜ foo, & ๐Ÿ“ฐ ๐Ÿค foo).

, โŽ ๐Ÿ†” ๐Ÿ’ฅ, ๐Ÿ•โ” ๐Ÿ— ๐Ÿฅ™ ๐Ÿค ๐Ÿ‘ฉโ€๐Ÿ’ป, ๐Ÿ‘† ๐Ÿ’ช ๐Ÿ”ก ๐Ÿ’ฒ sub ๐Ÿ”‘, โœ… โฎ๏ธ username:. , ๐Ÿ‘‰ ๐Ÿ–ผ, ๐Ÿ’ฒ sub ๐Ÿ’ช โœ”๏ธ: username:johndoe.

โš  ๐Ÿ‘œ โœ”๏ธ ๐Ÿคฏ ๐Ÿ‘ˆ sub ๐Ÿ”‘ ๐Ÿ”œ โœ”๏ธ ๐Ÿ˜ ๐Ÿ†” ๐Ÿคญ ๐ŸŽ‚ ๐Ÿˆธ, & โšซ๏ธ ๐Ÿ”œ ๐ŸŽป.

โœ… โšซ๏ธ

๐Ÿƒ ๐Ÿ’ฝ & ๐Ÿšถ ๐Ÿฉบ: http://127.0.0.1:8000/docs.

๐Ÿ‘† ๐Ÿ”œ ๐Ÿ‘€ ๐Ÿ‘ฉโ€๐Ÿ’ป ๐Ÿ”ข ๐Ÿ’–:

โœ” ๐Ÿˆธ ๐ŸŽ ๐ŸŒŒ โญ.

โš™๏ธ ๐ŸŽ“:

๐Ÿ†”: johndoe ๐Ÿ”: secret

Check

๐Ÿ‘€ ๐Ÿ‘ˆ ๐Ÿ•ณ ๐Ÿ“Ÿ ๐Ÿ”ข ๐Ÿ” "secret", ๐Ÿ‘ฅ ๐Ÿ•ด โœ”๏ธ #๏ธโƒฃ โฌ.

๐Ÿค™ ๐Ÿ”— /users/me/, ๐Ÿ‘† ๐Ÿ”œ ๐Ÿคš ๐Ÿ“จ:

{
  "username": "johndoe",
  "email": "johndoe@example.com",
  "full_name": "John Doe",
  "disabled": false
}

๐Ÿšฅ ๐Ÿ‘† ๐Ÿ“‚ ๐Ÿ‘ฉโ€๐Ÿ’ป ๐Ÿงฐ, ๐Ÿ‘† ๐Ÿ’ช ๐Ÿ‘€ โ” ๐Ÿ“Š ๐Ÿ“จ ๐Ÿ•ด ๐Ÿ”Œ ๐Ÿค, ๐Ÿ” ๐Ÿ•ด ๐Ÿ“จ ๐Ÿฅ‡ ๐Ÿ“จ ๐Ÿ”“ ๐Ÿ‘ฉโ€๐Ÿ’ป & ๐Ÿคš ๐Ÿ‘ˆ ๐Ÿ” ๐Ÿค, โœ‹๏ธ ๐Ÿšซ โฎ๏ธ:

Note

๐Ÿ‘€ ๐ŸŽš Authorization, โฎ๏ธ ๐Ÿ’ฒ ๐Ÿ‘ˆ โ–ถ๏ธ โฎ๏ธ Bearer.

๐Ÿง โš™๏ธ โฎ๏ธ scopes

Oauth2๏ธโƒฃ โœ”๏ธ ๐Ÿ”‘ "โ†”".

๐Ÿ‘† ๐Ÿ’ช โš™๏ธ ๐Ÿ‘ซ ๐Ÿšฎ ๐ŸŽฏ โš’ โœ” ๐Ÿฅ™ ๐Ÿค.

โคด๏ธ ๐Ÿ‘† ๐Ÿ’ช ๐Ÿค ๐Ÿ‘‰ ๐Ÿค ๐Ÿ‘ฉโ€๐Ÿ’ป ๐Ÿ”— โš–๏ธ ๐Ÿฅ‰ ๐Ÿฅณ, ๐Ÿ”— โฎ๏ธ ๐Ÿ‘† ๐Ÿ› ๏ธ โฎ๏ธ โš’ ๐Ÿšซ.

๐Ÿ‘† ๐Ÿ’ช ๐Ÿ’ก โ” โš™๏ธ ๐Ÿ‘ซ & โ” ๐Ÿ‘ซ ๐Ÿ› ๏ธ ๐Ÿ”˜ FastAPI โช ๐Ÿง ๐Ÿ‘ฉโ€๐Ÿ’ป ๐Ÿฆฎ.

๐ŸŒƒ

โฎ๏ธ โšซ๏ธโ” ๐Ÿ‘† โœ”๏ธ ๐Ÿ‘€ ๐Ÿ†™ ๐Ÿ”œ, ๐Ÿ‘† ๐Ÿ’ช โš’ ๐Ÿ†™ ๐Ÿ” FastAPI ๐Ÿˆธ โš™๏ธ ๐Ÿฉ ๐Ÿ’– Oauth2๏ธโƒฃ & ๐Ÿฅ™.

๐ŸŒ– ๐Ÿ™† ๐Ÿ› ๏ธ ๐Ÿšš ๐Ÿ’‚โ€โ™‚ โ–ถ๏ธ๏ธ ๐Ÿ‘ ๐Ÿ— ๐Ÿ“„ ๐Ÿ”œ.

๐Ÿ“š ๐Ÿ“ฆ ๐Ÿ‘ˆ ๐Ÿ“‰ โšซ๏ธ ๐Ÿ“š โœ”๏ธ โš’ ๐Ÿ“š โš  โฎ๏ธ ๐Ÿ’ฝ ๐Ÿท, ๐Ÿ’ฝ, & ๐Ÿ’ช โš’. & ๐Ÿ‘‰ ๐Ÿ“ฆ ๐Ÿ‘ˆ ๐Ÿ“‰ ๐Ÿ‘œ ๐Ÿ’โ€โ™‚๏ธ ๐ŸŒ… ๐Ÿค™ โœ”๏ธ ๐Ÿ’‚โ€โ™‚ โš  ๐Ÿ”˜.


FastAPI ๐Ÿšซ โš’ ๐Ÿ™† โš  โฎ๏ธ ๐Ÿ™† ๐Ÿ’ฝ, ๐Ÿ’ฝ ๐Ÿท โš–๏ธ ๐Ÿงฐ.

โšซ๏ธ ๐Ÿค ๐Ÿ‘† ๐ŸŒ ๐Ÿ’ช โš’ ๐Ÿ• ๐Ÿ‘ˆ ๐Ÿ‘– ๐Ÿ‘† ๐Ÿ— ๐Ÿ†.

& ๐Ÿ‘† ๐Ÿ’ช โš™๏ธ ๐Ÿ”— ๐Ÿ“š ๐Ÿ‘ ๐Ÿšง & ๐Ÿ›Ž โš™๏ธ ๐Ÿ“ฆ ๐Ÿ’– passlib & python-jose, โ†ฉ๏ธ FastAPI ๐Ÿšซ ๐Ÿšš ๐Ÿ™† ๐Ÿ— ๐Ÿ› ๏ธ ๐Ÿ› ๏ธ ๐Ÿ”ข ๐Ÿ“ฆ.

โœ‹๏ธ โšซ๏ธ ๐Ÿšš ๐Ÿ‘† ๐Ÿงฐ ๐Ÿ“‰ ๐Ÿ› ๏ธ ๐ŸŒ… ๐Ÿ’ช ๐Ÿต ๐ŸŽฏ ๐Ÿ’ช, โš–, โš–๏ธ ๐Ÿ’‚โ€โ™‚.

& ๐Ÿ‘† ๐Ÿ’ช โš™๏ธ & ๐Ÿ› ๏ธ ๐Ÿ”, ๐Ÿฉ ๐Ÿ› ๏ธ, ๐Ÿ’– Oauth2๏ธโƒฃ ๐Ÿ“ถ ๐Ÿ™… ๐ŸŒŒ.

๐Ÿ‘† ๐Ÿ’ช ๐Ÿ’ก ๐ŸŒ… ๐Ÿง ๐Ÿ‘ฉโ€๐Ÿ’ป ๐Ÿฆฎ ๐Ÿ”ƒ โ” โš™๏ธ Oauth2๏ธโƒฃ "โ†”", ๐ŸŒ– ๐Ÿ‘Œ-๐Ÿงฝ โœ” โš™๏ธ, ๐Ÿ“„ ๐Ÿ‘ซ ๐ŸŽ ๐Ÿฉ. Oauth2๏ธโƒฃ โฎ๏ธ โ†” ๐Ÿ› ๏ธ โš™๏ธ ๐Ÿ“š ๐Ÿฆ ๐Ÿค ๐Ÿ•โ€๐Ÿฆบ, ๐Ÿ’– ๐Ÿ‘ฑ๐Ÿ“”, ๐Ÿ‡บ๐Ÿ‡ธ๐Ÿ”, ๐Ÿ“‚, ๐Ÿคธโ€โ™‚, ๐Ÿ‘ฑ๐Ÿ“”, โ™’๏ธ. โœ” ๐Ÿฅ‰ ๐Ÿฅณ ๐Ÿˆธ ๐Ÿ”— โฎ๏ธ ๐Ÿ‘ซ ๐Ÿ”— ๐Ÿ”› ๐Ÿ‘จโ€๐Ÿ’ผ ๐Ÿ‘ซ ๐Ÿ‘ฉโ€๐Ÿ’ป.