본문 바로가기

Django/Authentication

[Django] DRF의 Token Authentication

 

DRF Authentication

DRF의 인증은 여러가지의 방법이 있다. BasicAuthentication, TokenAuthentication, SessionAuthentication 등등..

  • SessionAuthentication
    • 세션을 통한 인증
    • 웹 프론트엔드와 장고가 같은 호스트를 쓴다면 세션 인증 사용 가능 (ex. nginx)
    • Django의 default이며, 외부 서비스에서는 세션 인증 불가능
  • BasicAuthentication
    • Basic 인증 헤더를 통한 인증
    • Django의 default이며, 외부 서비스에 매번 username과 password를 넘기는 것은 보안상 위험하다.
    • test 에 적합한 인증 방식
  • TokenAuthentication
    • Token 헤더를 통한 인증
    • username과 password로 Token을 발급받고, API 요청에 담아 보내 인증을 처리

 

대부분 인증 방식 중에서 TokenAuthentication 인증 방식을 사용한다. 그 이유는 다른 인증 방식은 위와 같은 문제점이 있기 때문이고 TokenAuthentication 인증 방식이 사용하는 데에 있어서 더 편하다.

 

 

TokenAuthentication

토큰 인증 체계는 간단한 토큰 기반 HTTP 인증 체계를 사용한다. 토큰 인증 방식은 웹 또는 모바일 클라이언트와 서버 사이의 설정에 적합하다.

 

INSTALLED_APPS = [

	...
    
    # Third-Party Apps
    'rest_framework',
    'rest_framework.authtoken',  # <-- Here

    ...
    
]

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',  # <-- And here
    ],
}

DRF에서 지원해주는 authtoken 앱을 설정해준다. 앱의 일종이며 Token 이라는 model을 지원하기 때문에 migrate 과정도 해주어야 한다.

그리고 DEFAULT_AUTHENTICATION_CLASSES에 사용할 TokenAuthentication를 추가해준다.

 

 

Token Model

  • User Model 과 1:1 관계
  • 각 User마다 Token은 수동으로 생성해주어야 한다.
  • Token은 User별로 유일하며, Token만으로 인증을 수행한다.

 

# Token Model

class Token(models.Model):
    key = models.CharField(_("Key"), max_length=40, primary_key=True)
    user = models.OneToOneField(
            settings.AUTH_USER_MODEL, related_name='auth_token',
            on_delete=models.CASCADE, verbose_name=_("User"))
            created = models.DateTimeField(_("Created"), auto_now_add=True)

    class Meta:
        abstract = 'rest_framework.authtoken' not in settings.INSTALLED_APPS

    def save(self, *args, **kwargs):
        if not self.key: # self.key에 값이 없으면, 랜덤 문자열을 지정.
            self.key = self.generate_key()
        return super().save(*args, **kwargs)

    def generate_key(self):
        return binascii.hexlify(os.urandom(20)).decode()

    def __str__(self):
        return self.key

 

 

Token 생성

OptainAuthToken APIVIew 를 이용한 토큰 생성을 볼  것이다.

 rest_framework/authtoken/views.py
class ObtainAuthToken(APIView):
    def post(self, request, *args, **kwargs):  # post 요청일 때
        # ...
        # 토큰, 생성여부(bool 반환)
        token, created = Token.objects.get_or_create(user=user) # 유저가 있으면 가져오고, 없으면 토큰을 생성한다.
        return Response({'token': token.key})

 

Token 획득

obtain_auth_token을 노출한다.

# accounts/urls.py
from rest_framework.authtoken.views import obtain_auth_token

urlpatterns += [
    path('api-token-auth/', obtain_auth_token),
]