Django REST Framework/DRF 일반

[DRF] 공식 문서 - Authentication 정리

bluebamus 2024. 1. 19. 18:13

 1. Authentication

   - "인증"은 들어오는 요청을 식별 가능한 자격 증명, 예를 들어 요청을 보낸 사용자 또는 요청이 서명된 토큰과 연결하는 메커니즘이다. 권한 및 쓰로틀링 정책은 이러한 자격 증명을 사용하여 요청을 허용해야 하는지 결정할 수 있다.

      - permission :https://www.django-rest-framework.org/api-guide/permissions/

      - throttling : https://www.django-rest-framework.org/api-guide/throttling/

 

   - REST 프레임워크는 여러 가지 인증 체계를 제공하며, 또한 사용자 정의 체계를 구현할 수 있게 해준다.

   - 인증은 항상 뷰의 맨 시작에서 실행되며, 권한 및 쓰로틀링 검사가 이루어지기 전이며, 다른 어떤 코드도 진행되기 전에 수행된다.

   - request.user 속성은 일반적으로 contrib.auth 패키지의 User 클래스의 인스턴스로 설정된다.

 

   - request.auth 속성은 추가 인증 정보에 사용되며, 예를 들어 요청이 서명된 인증 토큰을 나타내는 데 사용될 수 있다.


   - 참고: 인증 자체는 들어오는 요청을 허용하거나 거부하지 않는다. 인증은 단순히 요청이 어떤 자격 증명으로 이루어졌는지를 식별하는 것이다.

   - API에 대한 권한 정책 설정 방법에 대한 정보는 권한 문서를 참조하시기 바랍니다

      - https://www.django-rest-framework.org/api-guide/permissions/


 

   1) 인증 방식 결정 방법(How authentication is determined)

      - 인증 체계는 항상 클래스의 목록으로 정의된다. REST 프레임워크는 목록에 있는 각 클래스로 인증을 시도하고, 성공적으로 인증한 첫 번째 클래스의 반환 값으로 request.user와 request.auth를 설정한다.

      - 어떤 클래스도 인증에 성공하지 못하면, request.user는 django.contrib.auth.models.AnonymousUser의 인스턴스로, request.auth는 None으로 설정된다.

      - 인증되지 않은 요청에 대한 request.user와 request.auth의 값은 UNAUTHENTICATED_USER 및 UNAUTHENTICATED_TOKEN 설정을 사용하여 수정할 수 있다.

 

   2) 인증 체계 설정(Setting the authentication scheme)

      - 기본 인증 체계는 DEFAULT_AUTHENTICATION_CLASSES 설정을 사용하여 전역적으로 설정할 수 있다. 예를 들면, 다음과 같다.

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ]
}

 

      - APIView 클래스 기반 뷰를 사용하여 뷰별 또는 뷰셋별로 인증 체계를 설정할 수도 있다.

from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

class ExampleView(APIView):
    authentication_classes = [SessionAuthentication, BasicAuthentication]
    permission_classes = [IsAuthenticated]

    def get(self, request, format=None):
        content = {
            'user': str(request.user),  # `django.contrib.auth.User` instance.
            'auth': str(request.auth),  # None
        }
        return Response(content)

 

      - 또는 함수 기반 뷰에서 @api_view 데코레이터를 사용하는 경우에도 가능하다.

@api_view(['GET'])
@authentication_classes([SessionAuthentication, BasicAuthentication])
@permission_classes([IsAuthenticated])
def example_view(request, format=None):
    content = {
        'user': str(request.user),  # `django.contrib.auth.User` instance.
        'auth': str(request.auth),  # None
    }
    return Response(content)

 

   3) 인증되지 않은 혹은 금지된 응답(Unauthorized and Forbidden responses)

      - 인증되지 않은 요청이 권한을 거부받을 때, 적절한 두 가지 다른 에러 코드가 있다.

         - HTTP 401 Unauthorized : https://www.rfc-editor.org/rfc/rfc9110.html
         - HTTP 403 Permission Denied : https://www.rfc-editor.org/rfc/rfc9110.html

 

      - HTTP 401 응답은 항상 클라이언트에게 어떻게 인증해야 하는지 지시하는 WWW-Authenticate 헤더를 포함해야 한다. 반면에, HTTP 403 응답은 WWW-Authenticate 헤더를 포함하지 않는다.

      - 어떤 응답이 사용될 것인지는 인증 체계에 따라 달라진다. 여러 인증 체계가 사용되더라도, 응답의 유형을 결정하는 데에는 하나의 체계만 사용될 수 있다. 응답 유형을 결정할 때는 뷰에 설정된 첫 번째 인증 클래스가 사용된다.

 

      - 요청이 성공적으로 인증될 수 있지만, 그래도 요청을 수행하는 것이 허용되지 않는 경우에는, 인증 체계에 관계없이 항상 403 Permission Denied 응답이 사용된다는 것을 참고하자.

 

   4) Apache mod_wsgi 특정 설정(Apache mod_wsgi specific configuration)

      - mod_wsgi를 사용하여 Apache에 배포하는 경우, 기본적으로 인증 헤더가 WSGI 애플리케이션으로 전달되지 않는다는 점을 참고해야 한다. 이는 인증이 Apache에서 처리될 것으로 가정하고 애플리케이션 레벨에서는 처리되지 않을 것으로 생각하기 때문이다.

      - Apache에 배포하고 세션 기반이 아닌 인증을 사용하는 경우, 필요한 헤더를 애플리케이션으로 명시적으로 전달하도록 mod_wsgi를 구성해야 한다. 이는 적절한 컨텍스트에서 WSGIPassAuthorization 지시문을 지정하고 'On'으로 설정함으로써 수행할 수 있다.

# this can go in either server config, virtual host, directory or .htaccess
WSGIPassAuthorization On

 

 2. API Reference

   1) 기본 인증(BasicAuthentication)

      - 이 인증 체계는 사용자의 유저네임과 비밀번호에 대해 서명된 HTTP 기본 인증을 사용한다. 기본 인증은 일반적으로 테스트에만 적합하다.

      - 성공적으로 인증하면 BasicAuthentication는 다음과 같은 자격 증명을 제공한다.

         - request.user는 Django User 인스턴스가 된다.
         - request.auth는 None이 된다.

 

      - 권한이 거부된 인증되지 않은 응답은 적절한 WWW-Authenticate 헤더와 함께 HTTP 401 Unauthorized 응답을 결과로 가져온다. 예를 들면, 다음과 같다.

WWW-Authenticate: Basic realm="api"

      - 참고: 만약 실제 환경에서 BasicAuthentication을 사용한다면, 반드시 API가 https를 통해서만 이용 가능하도록 해야 한다. 또한, API 클라이언트는 항상 로그인 시에 사용자 이름과 비밀번호를 재요청하고, 이러한 정보를 영구 저장소에 저장하지 않도록 해야 한다.


 

   2) 토큰 인증(TokenAuthentication)


      - 참고: Django REST 프레임워크에 의해 제공되는 토큰 인증은 상당히 간단한 구현이다.

      - 사용자 당 여러 개의 토큰을 허용하고, 좀 더 엄격한 보안 구현 세부 사항을 갖추며, 토큰 만료를 지원하는 구현을 원한다면, Django REST Knox라는 서드 파티 패키지를 참고해보시기 바란다.


      - 이 인증 체계는 간단한 토큰 기반 HTTP 인증 체계를 사용한다. 토큰 인증은 기본 데스크톱과 모바일 클라이언트와 같은 클라이언트-서버 설정에 적합하다.

      - TokenAuthentication 체계를 사용하려면 인증 클래스를 구성하여 TokenAuthentication을 포함시키고, 추가로 INSTALLED_APPS 설정에 rest_framework.authtoken을 포함시켜야 한다.

INSTALLED_APPS = [
    ...
    'rest_framework.authtoken'
]

 

      - 설정을 변경한 후에는 반드시 manage.py migrate를 실행해야 한다.
      - rest_framework.authtoken 앱은 Django 데이터베이스 마이그레이션을 제공한다.

      - 또한 사용자들에 대해 토큰을 생성해야 한다.

from rest_framework.authtoken.models import Token

token = Token.objects.create(user=...)
print(token.key)

 

      - 클라이언트가 인증을 받으려면, 토큰 키가 Authorization HTTP 헤더에 포함되어야 한다. 키 앞에는 "Token"이라는 문자열 리터럴이 붙고, 두 문자열 사이에는 공백이 있어야 한다.

Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b

 

      - 헤더에 다른 키워드를 사용하려면, 예를 들어 Bearer를 사용하려면, 단순히 TokenAuthentication을 서브클래스로 만들고 키워드 클래스 변수를 설정하면 된다.

      - 성공적으로 인증하면, TokenAuthentication는 다음과 같은 자격 증명을 제공한다.

         - request.user는 Django User 인스턴스가 된다.

         - request.auth는 rest_framework.authtoken.models.Token 인스턴스가 된다.

 

      - 권한이 거부된 인증되지 않은 응답은 적절한 WWW-Authenticate 헤더와 함께 HTTP 401 Unauthorized 응답을 결과로 가져온다

WWW-Authenticate: Token

 

      - curl 명령 줄 도구는 토큰 인증 API를 테스트하는데 유용할 수 있다.

curl -X GET http://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b'

 


      - 참고: 만약 실제 환경에서 TokenAuthentication을 사용한다면, 반드시 API가 https를 통해서만 이용 가능하도록 해야 한다.


      1. 토큰 생성하기(Generating Tokens)

         1. 시그널을 활용하여(By using signals)

      - 모든 사용자가 자동으로 생성된 토큰을 가지길 원한다면, User의 post_save 시그널을 간단히 잡아내면 된다.

from django.conf import settings
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.authtoken.models import Token

@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
    if created:
        Token.objects.create(user=instance)

 

      - 이 코드 스니펫을 설치된 models.py 모듈에 반드시 위치시켜야 한다. 혹은 Django가 시작할 때 불러올 수 있는 다른 위치에도 위치시킬 수도 있다.

 

      - 이미 몇몇 사용자를 생성하였다면, 다음과 같은 방법으로 기존 사용자들에 대해 토큰을 생성할 수 있다.

from django.contrib.auth.models import User
from rest_framework.authtoken.models import Token

for user in User.objects.all():
    Token.objects.get_or_create(user=user)

 

         2. 엔드포인트를 공개함으로써(By exposing an api endpoint)

         - TokenAuthentication을 사용할 때, 사용자명과 비밀번호를 주면 토큰을 얻을 수 있는 메커니즘을 클라이언트에게 제공하고 싶을 수 있다. REST 프레임워크는 이러한 동작을 제공하는 내장 뷰를 제공한다. 이를 사용하려면, URL 설정에 obtain_auth_token 뷰를 추가하면 된다

from rest_framework.authtoken import views
urlpatterns += [
    path('api-token-auth/', views.obtain_auth_token)
]

 

         - 패턴의 URL 부분은 원하는대로 설정할 수 있다는 점을 유의해야 한다.

         - 유효한 사용자명과 비밀번호 필드가 form 데이터나 JSON을 사용하여 뷰에 POST되면, obtain_auth_token 뷰는 JSON 응답을 반환한다.

{ 'token' : '9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b' }

 

         - 기본 obtain_auth_token 뷰는 설정에서 기본 렌더러 및 파서 클래스를 사용하는 대신 명시적으로 JSON 요청 및 응답을 사용한다.

         - 기본적으로 obtain_auth_token 뷰에는 권한이나 쓰로틀링이 적용되지 않는다. 쓰로틀링을 적용하려면 뷰 클래스를 재정의하고 throttle_classes 속성을 사용하여 쓰로틀링을 포함해야 한다.

         - obtain_auth_token 뷰의 사용자 정의 버전이 필요한 경우 ObtainAuthToken 뷰 클래스를 서브클래싱하여 사용하고 URL 구성에서 해당 뷰를 대신 사용할 수 있다.

 

         - 예를 들어, 토큰 값 이상의 추가적인 사용자 정보를 반환할 수 있다.

from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.authtoken.models import Token
from rest_framework.response import Response

class CustomAuthToken(ObtainAuthToken):

    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data,
                                           context={'request': request})
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        token, created = Token.objects.get_or_create(user=user)
        return Response({
            'token': token.key,
            'user_id': user.pk,
            'email': user.email
        })

 

         - 그리고 urls.py 파일에서는 다음과 같이 작성할 수 있다.

urlpatterns += [
    path('api-token-auth/', CustomAuthToken.as_view())
]

 

         3. Django admin과 함께 사용하는 경우(With Django admin)

         - 관리자 인터페이스를 통해 수동으로 토큰을 생성하는 것도 가능하다. 사용자 기반이 큰 경우에는 TokenAdmin 클래스를 monkey patch하여 사용자 필드를 raw_field로 선언하여 필요에 맞게 사용자 정의하는 것을 권장한다.

 

         - your_app/admin.py

from rest_framework.authtoken.admin import TokenAdmin

TokenAdmin.raw_id_fields = ['user']

 

         4. Django의 manage.py 명령을 사용하기(Using Django manage.py command)

         - 버전 3.6.4부터는 다음 명령을 사용하여 사용자 토큰을 생성할 수 있습니다

./manage.py drf_create_token <username>

 

         - 해당 명령은 지정된 사용자에 대한 API 토큰을 반환하며, 존재하지 않는 경우에는 생성한다.

Generated token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b for user user1

 

         - 토큰을 재생성하고자 하는 경우 (예: 토큰이 노출되거나 유출된 경우) 추가 매개변수를 전달할 수 있다.

./manage.py drf_create_token -r <username>

 

   3) 세션 인증(SessionAuthentication)

      - 이 인증 체계는 Django의 기본 세션 백엔드를 사용하여 인증한다. 세션 인증은 웹사이트와 동일한 세션 컨텍스트에서 실행되는 AJAX 클라이언트에 적합하다.

 

      - 인증에 성공한 경우, SessionAuthentication은 다음과 같은 자격 증명을 제공한다.
         - request.user는 Django User 인스턴스가 된다.

         - request.auth는 None이 된다.

 

      - 인증되지 않은 요청이 권한이 거부된 경우, HTTP 403 Forbidden 응답이 반환된다.

      - SessionAuthentication을 사용하는 AJAX 스타일의 API를 사용하는 경우, PUT, PATCH, POST 또는 DELETE 요청과 같은 "안전하지 않은" HTTP 메서드 호출에 대해 유효한 CSRF 토큰을 포함해야 한다. 자세한 내용은 Django CSRF 문서를 참조하면 된다.

         - https://docs.djangoproject.com/en/5.0/howto/csrf/#using-csrf-protection-with-ajax

 

      - 경고: 로그인 페이지를 생성할 때는 항상 Django의 표준 로그인 뷰를 사용자. 이렇게 함으로써 로그인 뷰가 올바르게 보호된다.

      - REST framework에서의 CSRF 유효성 검사는 표준 Django와 약간 다르다. 이는 세션 기반 및 비세션 기반 인증을 동일한 뷰에서 지원해야 하기 때문이다. 이는 인증된 요청만 CSRF 토큰을 필요로 하며, 익명 요청은 CSRF 토큰 없이 전송될 수 있다는 의미이다. 이 동작은 로그인 뷰에 적합하지 않으며, 로그인 뷰에는 항상 CSRF 유효성 검사가 적용되어야 한다.

 

   4) 원격 사용자 인증(RemoteUserAuthentication)

      - 이 인증 체계를 사용하면 웹 서버에 인증을 위임할 수 있으며, 웹 서버는 REMOTE_USER 환경 변수를 설정한다.

      - 사용하려면 AUTHENTICATION_BACKENDS 설정에 django.contrib.auth.backends.RemoteUserBackend (또는 이를 상속한 클래스)를 포함해야 한다. 기본적으로 RemoteUserBackend는 이미 존재하지 않는 사용자 이름을 위해 User 객체를 생성한다. 이와 다른 동작을 변경하려면 Django 문서를 참조해야 한다.


      - 인증에 성공한 경우, RemoteUserAuthentication은 다음과 같은 자격 증명을 제공한다.

         - request.user는 Django User 인스턴스가 된다.

         - request.auth는 None이 된다.

 

      - 인증 방법을 구성하는 방법에 대한 정보는 웹 서버의 문서를 참조하세요. 예를 들어:
         - Apache 인증 How-To : https://httpd.apache.org/docs/2.4/howto/auth.html

         - NGINX (접근 제한) : https://docs.nginx.com/nginx/admin-guide/security-controls/configuring-http-basic-authentication/

 

from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView

class MyView(APIView):
    authentication_classes = [SessionAuthentication]
    permission_classes = [IsAuthenticated]

    def post(self, request):
        # POST 요청 처리 코드 작성
        pass
# settings.py

# Django 기본 설정 내용...

MIDDLEWARE = [
    # 다른 미들웨어들...
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    # 다른 미들웨어들...
]

# Django 기본 설정 내용...
POST /api/my-endpoint/ HTTP/1.1
Host: example.com
Authorization: Session abcdefghijklmnopqrstuvwxyz0123456789
X-CSRFToken: ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
Content-Type: application/json
Content-Length: 27

{"key": "value"}

 

      - 위 코드에서 authentication_classes에 SessionAuthentication을 추가하여 세션 기반 인증을 사용하고, permission_classes에 IsAuthenticated를 추가하여 인증된 사용자만 접근할 수 있도록 설정한다. 이렇게 설정하면 DRF는 요청 헤더에 있는 CSRF 토큰을 자동으로 검증하게 된다.

      - 세션 기반 인증을 사용하려면 Django 설정 파일(settings.py)에서 SessionMiddleware와 AuthenticationMiddleware를 활성화해야 한다. CSRF 토큰은 기본적으로 Django의 CsrfViewMiddleware에서 생성 및 검증된다.

 

3. 사용자 정의 인증(Custom authentication)

   - 사용자 정의 인증 체계를 구현하려면 BaseAuthentication을 상속하고 .authenticate(self, request) 메서드를 재정의해야 한다. 이 메서드는 인증에 성공하면 (user, auth) 형태의 튜플을 반환하고, 그렇지 않은 경우 None을 반환해야 한다.

   - 일부 상황에서는 None을 반환하는 대신 .authenticate() 메서드에서 AuthenticationFailed 예외를 발생시키는 것이 좋을 수 있다.

   - 일반적으로 취해야 할 접근 방식은 다음과 같다.

      - 인증을 시도하지 않은 경우 None을 반환한다. 사용 중인 다른 인증 체계도 여전히 확인된다.
      - 인증을 시도했지만 실패한 경우 AuthenticationFailed 예외를 발생시킨다. 권한 확인과 관계없이 오류 응답이 즉시 반환되며, 다른 인증 체계를 확인하지 않는다.

 

   - .authenticate_header(self, request) 메서드도 재정의할 수 있다. 구현되면 해당 메서드는 HTTP 401 Unauthorized 응답의 WWW-Authenticate 헤더 값으로 사용될 문자열을 반환해야 한다.

   - .authenticate_header() 메서드를 재정의하지 않으면, 인증 체계는 인증되지 않은 요청이 액세스 거부된 경우 HTTP 403 Forbidden 응답을 반환한다.

from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed

class CustomAuthentication(BaseAuthentication):
    def authenticate(self, request):
        # 가상의 시나리오: 헤더에서 사용자 정보 추출
        auth_header = request.META.get('HTTP_AUTHORIZATION')
        if not auth_header:
            # 인증 헤더가 없는 경우
            raise AuthenticationFailed('Authentication header가 필요합니다.')

        # 가상의 시나리오: 사용자 정보 추출
        # 예시: Basic Auth의 경우 'Basic base64_encoded_credentials' 형식
        auth_type, auth_value = auth_header.split(' ')
        if auth_type.lower() != 'basic':
            # 지원하지 않는 인증 방식인 경우
            raise AuthenticationFailed('지원하지 않는 인증 방식입니다.')

        try:
            # 가상의 시나리오: 사용자 정보 유효성 검사
            username, password = base64.b64decode(auth_value).decode().split(':')
            user = User.objects.get(username=username)
            if not user.check_password(password):
                # 비밀번호가 일치하지 않는 경우
                raise AuthenticationFailed('비밀번호가 일치하지 않습니다.')
        except User.DoesNotExist:
            # 사용자가 존재하지 않는 경우
            raise AuthenticationFailed('사용자가 존재하지 않습니다.')

        return (user, None)  # (인증된 사용자, 인증 정보)

    def authenticate_header(self, request):
        # 가상의 시나리오: 커스텀 인증 헤더 반환
        return 'Bearer realm="api", error="invalid_token", error_description="인증이 필요합니다"'

    def authenticate_request(self, request):
        auth = get_authorization_header(request).split()
        if not auth or auth[0].lower() != b'bearer':
            raise AuthenticationFailed('인증되지 않은 요청입니다.', status.HTTP_403_FORBIDDEN)

        if len(auth) == 1:
            raise AuthenticationFailed('유효하지 않은 토큰입니다.', status.HTTP_403_FORBIDDEN)
        elif len(auth) > 2:
            raise AuthenticationFailed('유효하지 않은 인증 헤더입니다.', status.HTTP_403_FORBIDDEN)

        try:
            token = auth[1].decode()
            # 토큰을 사용하여 사용자 인증 진행
            # ...

        except UnicodeError:
            raise AuthenticationFailed('유효하지 않은 토큰입니다.', status.HTTP_403_FORBIDDEN)

        return (user, token)

      - 참고: custom authenticator가 요청 객체의 .user 또는 .auth 속성에 의해 호출될 때, AttributeError가 WrappedAttributeError로 다시 발생할 수 있다. 이는 원래 예외가 외부 속성 접근에 의해 억제되는 것을 방지하기 위해 필요하다. Python은 AttributeError가 custom authenticator에서 발생한 것임을 인식하지 못하고, 대신 요청 객체에 .user 또는 .auth 속성이 없다고 가정한다. 이러한 오류는 authenticator에서 수정하거나 다른 방식으로 처리되어야 한다.

from rest_framework.exceptions import AuthenticationFailed, WrappedAttributeError

class CustomAuthenticator:
    def authenticate(self, request):
        try:
            # Perform custom authentication logic here
            # If authentication succeeds:
            user = ...  # Retrieve the authenticated user
            auth = ...  # Retrieve additional authentication information
            return user, auth
        except SomeException as e:
            # Handle any specific exceptions that may occur during authentication
            raise AuthenticationFailed("Authentication failed: {}".format(e))
        except AttributeError as e:
            # Wrap the AttributeError to prevent it from being suppressed
            raise WrappedAttributeError(e)

    def authenticate_header(self, request):
        return "Bearer realm='api'"  # Example authentication header

# Example usage in a view
def my_view(request):
    authenticator = CustomAuthenticator()
    try:
        user, auth = authenticator.authenticate(request)
        # Handle authenticated request
    except AuthenticationFailed as e:
        # Handle authentication failure
    except WrappedAttributeError as e:
        # Handle attribute error raised by the authenticator
        # e.original_exception contains the original AttributeError

    # Rest of the view logic

 

   1) Example

      - 다음 예제는 'X-USERNAME'라는 사용자 정의 요청 헤더에 포함된 사용자 이름으로 모든 들어오는 요청을 인증한다.

from django.contrib.auth.models import User
from rest_framework import authentication
from rest_framework import exceptions

class ExampleAuthentication(authentication.BaseAuthentication):
    def authenticate(self, request):
        username = request.META.get('HTTP_X_USERNAME')
        if not username:
            return None

        try:
            user = User.objects.get(username=username)
        except User.DoesNotExist:
            raise exceptions.AuthenticationFailed('No such user')

        return (user, None)

 

 4. Third party packages

   1) django-rest-knox

      - Django-rest-knox 라이브러리는 내장된 TokenAuthentication 체계보다 보안성과 확장성이 더 뛰어난 토큰 기반 인증을 처리하기 위한 모델과 뷰를 제공한다. 특히 Single Page Applications 및 Mobile 클라이언트를 고려하여 개발되었다. 이 라이브러리는 클라이언트별 토큰을 제공하며, 다른 인증 정보 (일반적으로 기본 인증)를 제공하여 토큰을 생성하는 뷰를 제공한다. 또한 토큰을 삭제하여 (서버에서 강제로 로그아웃) 토큰을 삭제하거나 모든 토큰을 삭제하여 사용자가 로그인한 모든 클라이언트를 로그아웃할 수 있는 기능도 제공한다.

         - https://github.com/jazzband/django-rest-knox

 

   2) Django OAuth Toolkit

      - Django OAuth Toolkit 패키지는 OAuth 2.0을 지원하며 Python 3.4+와 호환된다. 이 패키지는 jazzband에 의해 유지되며 우수한 OAuthLib를 사용한다. 해당 패키지는 문서화가 잘 되어 있으며 지원도 잘 되고 있으며 현재 OAuth 2.0을 지원하기 위해 권장되는 패키지이다.

         - https://github.com/jazzband/django-oauth-toolkit

         - https://github.com/jazzband/

         - https://github.com/oauthlib/oauthlib

 

      1. Installation & configuration

pip install django-oauth-toolkit

 

         - "INSTALLED_APPS"에 패키지를 추가하고 REST 프레임워크 설정을 수정한다.

INSTALLED_APPS = [
    ...
    'oauth2_provider',
]

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
    ]
}

 

         - 자세한 내용은 Django REST framework - 시작하기 문서를 참조하면 된다.

            - https://django-oauth-toolkit.readthedocs.io/en/latest/rest-framework/getting_started.html

 

   3) Django REST framework OAuth

      - Django REST framework OAuth 패키지는 REST 프레임워크에 대한 OAuth1과 OAuth2 지원을 제공한다.
      - 이 패키지는 이전에 REST 프레임워크에 직접 포함되었지만, 현재는 제3자 패키지로 지원되고 유지보수되고 있다.

         - https://jpadilla.github.io/django-rest-framework-oauth/

 

      1. Installation & configuration

pip install djangorestframework-oauth

 

         - 인증 및 권한에 대한 자세한 구성 및 사용 방법은 Django REST framework OAuth 문서를 참조하면 된다.

            - authentication : https://jpadilla.github.io/django-rest-framework-oauth/authentication/

            - permissions : https://jpadilla.github.io/django-rest-framework-oauth/permissions/

 

   4) JSON Web Token Authentication

      - permissionsJSON Web Token (JWT)는 토큰 기반 인증에 사용할 수 있는 상당히 새로운 표준이다. 내장된 TokenAuthentication 체계와는 달리, JWT 인증은 토큰을 유효성 검사하기 위해 데이터베이스를 사용할 필요가 없다. JWT 인증을 위한 패키지로는 djangorestframework-simplejwt가 있으며, 이 패키지는 몇 가지 기능과 플러그 가능한 토큰 블랙리스트 앱을 제공한다.

         - djangorestframework-simplejwt :  https://github.com/jazzband/djangorestframework-simplejwt

 

   5) Hawk HTTP Authentication

      - HawkREST 라이브러리는 Mohawk 라이브러리를 기반으로하여 API에서 Hawk 서명된 요청과 응답을 처리할 수 있도록 합니다. Hawk는 공유 키로 서명된 메시지를 사용하여 두 개의 당사자가 안전하게 통신할 수 있게 해줍니다. 이는 HTTP MAC 액세스 인증을 기반으로 하며(이는 OAuth 1.0의 일부를 기반으로 합니다), HawkREST를 사용하여 이러한 기능을 API에서 활용할 수 있습니다.

         - HawkREST : https://hawkrest.readthedocs.io/en/latest/

         - Mohawk : https://mohawk.readthedocs.io/en/latest/

         - Hawk : https://github.com/mozilla/hawk

         - HTTP MAC access authentication : https://datatracker.ietf.org/doc/html/draft-hammer-oauth-v2-mac-token-05

         - OAuth 1.0 : https://oauth.net/core/1.0a/

 

   6) HTTP Signature Authentication

      - HTTP Signature는 HTTP 메시지의 출처 인증과 메시지 무결성을 달성하기 위한 방법을 제공한다. 이는 많은 서비스에서 사용하는 Amazon의 HTTP Signature 체계와 유사하며, 상태를 유지하지 않고 요청별 인증을 허용한다. djangorestframework-httpsignature (오래된 버전) 패키지는 Elvio Toccalino에 의해 유지되며, 사용하기 쉬운 HTTP Signature 인증 메커니즘을 제공한다. drf-httpsig는 djangorestframework-httpsignature의 업데이트된 포크 버전을 사용할 수 있다.

         - IETF draft : https://datatracker.ietf.org/doc/draft-cavage-http-signatures/

         - Amazon's HTTP Signature scheme :  https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-signing.html

         - Elvio Toccalino : https://github.com/etoccalino/

         - djangorestframework-httpsignature : https://github.com/etoccalino/django-rest-framework-httpsignature

         - drf-httpsig : https://github.com/ahknight/drf-httpsig

 

   7) Djoser

      - Djoser 라이브러리는 등록, 로그인, 로그아웃, 비밀번호 재설정 및 계정 활성화와 같은 기본 작업을 처리하기 위한 일련의 뷰를 제공한다. 이 패키지는 사용자 정의 사용자 모델과 토큰 기반 인증을 사용한다. 이는 Django 인증 시스템의 REST 구현체로서 즉시 사용할 수 있는 기능을 제공한다.

         - https://github.com/sunscrapers/djoser

 

   8) django-rest-auth / dj-rest-auth

      - 이 라이브러리는 등록, 인증(소셜 미디어 인증 포함), 비밀번호 재설정, 사용자 세부 정보 검색 및 업데이트 등을 위한 REST API 엔드포인트 세트를 제공한다. 이러한 API 엔드포인트를 통해 AngularJS, iOS, Android 등의 클라이언트 앱은 REST API를 통해 Django 백엔드 사이트와 독립적으로 사용자 관리를 할 수 있다.

      - 현재 이 프로젝트에는 두 개의 포크가 있다.

      - Django-rest-auth는 원래 프로젝트이지만 현재 업데이트를 받지 않고 있다.

         - https://github.com/Tivix/django-rest-auth
      - Dj-rest-auth는 이 프로젝트의 최신 포크이다.

         - https://github.com/iMerica/dj-rest-auth

 

   9) drf-social-oauth2

      - Drf-social-oauth2는 Facebook, Google, Twitter, Orcid 등과 같은 주요 소셜 OAuth2 공급자로 인증하는 데 도움이 되는 프레임워크이다. 간편한 설정으로 JWT 형식의 토큰을 생성한다.

         - https://github.com/wagnerdelima/drf-social-oauth2

 

   10) drfpasswordless

      - drfpasswordless는 Django REST Framework의 TokenAuthentication 체계에 (Medium, Square Cash에서 영감을 받은) 비밀번호 없는 인증을 추가한다. 사용자는 이메일 주소나 휴대폰 번호와 같은 연락처로 전송된 토큰을 사용하여 로그인하고 가입할 수 있다.

         - https://github.com/aaronn/django-rest-framework-passwordless

 

   11) django-rest-authemail

      - django-rest-authemail은 사용자 등록 및 인증을 위한 RESTful API 인터페이스를 제공한다. 사용자 이름 대신 이메일 주소를 인증에 사용한다. 가입, 가입 이메일 확인, 로그인, 로그아웃, 비밀번호 재설정, 비밀번호 재설정 확인, 이메일 변경, 이메일 변경 확인, 비밀번호 변경 및 사용자 세부 정보를 위한 API 엔드포인트가 제공된다. 완전히 기능이 구현된 예제 프로젝트와 상세한 지침이 포함되어 있다.

         - https://github.com/celiao/django-rest-authemail

 

   12) Django-Rest-Durin

      - Django-Rest-Durin은 여러 웹/CLI/모바일 API 클라이언트를 한 인터페이스를 통해 토큰 인증을 처리하되, API를 사용하는 각 API 클라이언트마다 다른 토큰 구성이 가능하도록하는 아이디어로 개발된 라이브러리이다. 이는 Django-Rest-Framework와 함께 작동하는 사용자 지정 모델, 뷰, 권한을 통해 사용자 당 여러 토큰을 지원한다. 토큰 만료 시간은 API 클라이언트마다 다를 수 있으며, Django Admin 인터페이스를 통해 사용자 정의할 수 있다.

         - https://github.com/eshaan7/django-rest-durin

 

 - 공식 사이트 문서 : https://www.django-rest-framework.org/api-guide/authentication/

 

Authentication - Django REST framework

 

www.django-rest-framework.org