3 분 소요

OAuth2, Bearer란

OAuth2

OAuth 2.0을 사용하면, 계정 정보(특히 비밀번호)를 직접 공유하지 않고도 여러 서비스 간에 안전하게 로그인하고 정보를 공유할 수 있습니다. 이는 인터넷에서 개인정보를 보호하는 중요한 방법 중 하나입니다.

인터넷에서의 “키(토큰)”

우리가 인터넷에서 다양한 서비스(예: 게임, 소셜 미디어, 쇼핑 앱 등)를 사용할 때, 때때로 한 서비스(예: 구글 또는 페이스북)를 사용해서 다른 서비스에 로그인하는 경우가 있습니다. 여기서 OAuth 2.0은 하나의 서비스가 다른 서비스에 ‘키(토큰)’를 안전하게 전달할 수 있게 해주는 역할을 합니다.

“키(토큰)” 전달 과정

  • 권한 요청: 예를 들어, ‘게임 A’에 ‘구글 계정’으로 로그인하고 싶다고 해 봅시다. 여기서 게임 A가 사용자에게 “구글 계정을 사용해서 로그인하도록 권한을 줄래?”라고 묻습니다.
  • 사용자 승인: 사용자가 “네, 괜찮아요”라고 답하면, 구글은 게임 A에 ‘키’( 토큰)를 제공합니다.
  • 키(토큰) 사용: 이제 게임 A는 이 ‘키(토큰)’를 사용하여 사용자의 구글 계정 정보 일부(예: 이메일 주소)에 접근할 수 있게 됩니다. 이 과정에서 사용자의 구글 비밀번호는 게임 A에 알려지지 않습니다.

Bearer

“인터넷에서 특별한 입장권 같은 것”

인터넷에서는 여러 서비스나 웹사이트를 사용할 때 로그인을 해야 하는 경우가 많습니다. 여기서 Bearer 토큰은 마치 놀이공원이나 영화관에 들어갈 때 필요한 입장권과 비슷한 역할을 합니다.

역할

  • 특별한 권한 부여: 사용자가 어떤 서비스(예: 게임, 소셜 미디어)에 로그인하면, 그 서비스는 사용자에게 Bearer 토큰을 줍니다. 이 토큰은 사용자가 그 서비스 내에서 할 수 있는 일들을 증명하는 “입장권”과 같습니다.
  • 서비스 이용: 사용자는 이 토큰을 가지고 다양한 활동을 할 수 있습니다. 예를 들어, 게시글을 쓰거나 친구 목록을 볼 때 이 토큰을 보여주면, 서비스는 “아, 이 사람이 맞구나. 할 수 있어!”라고 인식합니다.
  • 간편하고 안전하게 사용: Bearer 토큰은 비밀번호와 같은 개인정보를 매번 입력하지 않아도 되게 해줍니다. 그래서 사용하기 편리하고, 또 안전하게 서비스를 이용할 수 있습니다.

OAuth2PasswordBearer

출처: https://fastapi.tiangolo.com/tutorial/security/first-steps/
아래의 내용은 공식 사이트의 내용을 제 경험과 생각을 추가하여 다시 정리한 것 입니다.

OAuth2와 Bearer를 FastAPI에서 사용하기 위해 OAuth2PasswordBearer를 사용합니다.

from fastapi import Depends, FastAPI
# OAuth2와 Bearer가 구현 된 OAuth2PasswordBearer import
from fastapi.security import OAuth2PasswordBearer
from typing_extensions import Annotated

app = FastAPI()

# OAuth2PasswordBearer 인스턴스 생성
# tokenUrl은 클라이언트가 토큰을 받기 위해 보내야 하는 URL을 의미
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")


@app.get("/items/")
# Depends(oauth2_scheme): 의존성 주입으로 oauth2_scheme 호출
# -> 각 엔드포인트에서 자동으로 토큰을 추출하고 인증 절차를 수행
async def read_items(token: Annotated[str, Depends(oauth2_scheme)]):
    return {"token": token}

위의 코드를 실행 하고 fastapi의 docs를 확인 합니다.

http://localhost:8000/docs

fastapi docs 화면

위의 화면에서 아래 쪽 /items/를 클릭하고 Try it out을 클릭하면 해당 api를 실행 할 수 있습니다.

fastapi docs 화면

별도의 Parameter가 없으므로 Execute를 클릭하면 아래와 같은 결과를 확인 할 수 있습니다.

fastapi docs 화면

⓵ curl 명령은 http://localhost:8000/users/me 주소의 웹 서버에 HTTP GET 요청을 보내는 명령입니다.
⓶ 인증이 되어 않았으므로 Response body에 {"detail":"Not authenticated"}가 출력됩니다.
⓷ Response headers:

  • content-length: 30: 응답 본문의 길이가 30바이트라는 의미
  • content-type: application/json: 서버가 보낸 데이터의 타입이 JSON 형식이라는 의미
  • date: Fri, 23 Jul 2021 13:00:00 GMT: 서버가 응답을 보낸 시간
  • server: uvicorn: 서버가 사용하는 소프트웨어 이름
  • www-authenticate: Bearer: 서버가 클라이언트에게 Bearer 토큰을 사용하라는 의미. 클라이언트가 유효한 Bearer 토큰(일반적으로 JWT)을 제공해야 서버의 자원에 접근할 수 있음을 의미

fastapi docs 화면

다시 fastapi docs 화면으로 돌아가서 우측 상단의 Authorize를 클릭합니다.
인증 절차를 수행할 수 있습니다. (보통 인터넷상의 로그인 화면을 생각하시면 됩니다)

fastapi docs 화면

현재 코드로는 인증 절차를 수행 하여 토큰을 받을 수 없습니다.
화면 아래의 Authorize를 클릭하면 아래와 같은 화면이 나타납니다.

fastapi docs 화면

지금까지 OAuth2PasswordBearer의 기본 사용법을 알아보았습니다.

현재 유저(user) 가져오기

출처: https://fastapi.tiangolo.com/tutorial/security/get-current-user/
아래의 내용은 공식 사이트의 내용을 제 경험과 생각을 추가하여 다시 정리한 것 입니다.

현재 유저(user)를 가져오는 코드를 추가 합니다.

from typing import Union

from fastapi import Depends, FastAPI
from fastapi.security import OAuth2PasswordBearer
# pydantic의 BaseModel import
from pydantic import BaseModel
from typing_extensions import Annotated

app = FastAPI()

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")


# pydantic's BaseModel을 사용
class User(BaseModel):
    username: str
    email: Union[str, None] = None
    full_name: Union[str, None] = None
    disabled: Union[bool, None] = None


# 토큰을 디코딩하는 함수
def fake_decode_token(token):
    # 이 함수는 실제로 토큰을 디코딩하지 않습니다.
    # test를 위해 임의의 값(User의 인스턴스)을 반환합니다.
    return User(
        username=token + "fakedecoded", email="john@example.com", full_name="John Doe"
    )


# 토큰을 디코딩하는 함수를 의존성 주입으로 사용
async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
    user = fake_decode_token(token)
    return user


@app.get("/users/me")
# get_current_user 함수를 의존성 주입으로 사용
# get_current_user 함수의 반환값이 User 유형으로 current_user에 할당
async def read_users_me(current_user: Annotated[User, Depends(get_current_user)]):
    return current_user

위의 코드를 실행 하고 fastapi의 docs를 확인 합니다.

http://localhost:8000/docs#

/users/me 클릭 -> Try it out 클릭 -> Execute를 클릭 하여 api 실행

fastapi docs 화면

아직 인증 절차를 수행하지 않았으므로 {"detail":"Not authenticated"}가 출력됩니다.

지금까지의 내용으로 OAuth2와 Bearer를 이해하기는 어렵습니다. 앞으로 조금 씩 더 알아보도록 하겠습니다.


해시태그: #fastapi #uvicorn #OAuth2 #Bearer #OAuth2PasswordBearer #get_current_user

댓글남기기