인증을 다루는 방법

18 Mar 2019 - breadkey

서론

1. 인증(Authentication) 기능이란?

한마디로 애플리케이션에 액세스하는 사용자를 특정하는 기능이다.
 
일반적인 방법은 다음과 같다.

  1. 로그인에 필요한 사용자명과 패스워드를 각 애플리케이션이 가진 데이터베이스에 등록해둔다.
  2. 사용자가 애플리케이션에 액세스할 때 사용자명과 패스워드를 직접 입력하게 함으로써 해당 사용자를 특정한다.

2. 인증을 유지하는 방법

처음에는 HTTP의 connectionless(HTTP1.1 부터는 해결), stateless 특성 때문에 인증을 유지할 수 없었다. 인증을 유지하지 않는다면 매번 서비스를 이용할 때마다 다시 인증을 해야하는 번거로움이 있는데, 이를 해결하기 위해 쿠키와 세션을 사용하게 되었다. 로그인을 통해 인증을 하게 되면 서버는 해당 정보를 저장하고 세션 아이디를 쿠키로 넘겨 클라이언트가 서비스를 이용할 때 쿠키와 함꼐 요청하여 인증이 유지되도록 하는 방법이다.

1. Flask-Login

Flask의 사용자 인증과 관련된 세션을 관리한다.

1.1 How to use

1.1.1 LoginManager 클래스를 인스턴스화

login_manager = LoginManager()

1.1.2 사용할 application 등록

login_manager.init_app(app)

1.1.3 user_loader 메서드 정의

@login_manager.user_loader 데코레이터를 붙여 정의한다. 세션에 저장되어있는 user ID로부터 User 오브젝트를 가져오는 메서드이다.

1.1.4 User 클래스에서 정의해야 하는 것들

  • is_authenticated
    사용자가 인증된 상태라면 반드시 True를 반환해야 한다.
  • is_active
    False, 비활성화 상태이면 로그인할 수 없다.
  • is_anonymous
    실제 사용자는 False를 반환한다.
  • get_id()
    user_load 콜백 메서드가 수행될때 사용되기도 하는 메서드로 unicode로 된 id를 반환한다.

1.2 장점

1.2.1 사용이 매우 쉽고 간편하다.

제공하는 login, logout 메서드를 사용하면 되고 인증이 필요한 메소드의 경우 @login_required만 붙여줘도 되니 매우 쉽고 간편하다. 또한, Flask의 세션은 브라우저가 종료되면 바로 삭제되지만 Remember Me 기능으로 인해 브라우저를 실수로 닫아도 다시 접속하면 로그인이 유지되어 있다.

1.2.2 보안성을 제공한다.

쿠키 위조, 훔치기 등을 막을 수 있게 해 준다. 또한 Remeber Me 기능을 가지고 있지만 id와 password에 대해 저장하고 있는게 아니므로 어느정도 안전하다.

1.2.3 원하는 만큼 보안 수준을 설정할 수 있다.

세션 보호 수준, 세션 및 쿠키 사용 여부 및 지속시간 등을 원하는 만큼 설정할 수 있다.

현재 코틀린 클라이언트에서 쿠키를 받고 login_reuiqred 메서드를 요청할 때 쿠키를 Cookie 헤더에 실어서 요청하였는데 401 응답을 받고 있습니다…


2. JSON Web Token

RFC7519 웹 표준으로서 JSON 객체를 사용하여 정보를 전달하는 방식이다.

2.1 다양한 언어에서의 지원

2.2 Self-contained

HMAC 알고리즘을 통해 디지털 서명이 되기 떄문에 정보를 신뢰할 수 있다.

2.3 언제 쓰일까?

2.3.1 인증

유저가 로그인 하면 서버가 유저의 정보에 기반한 토근을 발급하여 유저에게 전달하면 유저가 서버에 요청할 떄 마다 이 토큰을 실어서 보낸다. 서버에서 토큰의 유효성을 검증하고 권한이 있는지를 확인하여 요청을 처리한다.

세션을 유지 할 필요가 없다!! 토큰만 검증하면 되므로 세션 관리에 필요한 서버 자원을 아낄 수 있다.

2.4 How to use?

2.4.1 생김새

xxxxx.yyyyy.zzzzz와 같이 생겼다.
x는 Header, y는 Payload, z는 Signature 영역이다.

2.4.1.1 Header
{
	"alg": "HS256",
	"typ": "JWT"
}

위와 같이 두 부분으로 나뉜다. alg는 서명에 사용될 알고리즘을 정하며 type은 토큰의 타입, 즉 JWT이다.

이후 이 JSON은 Base64Url 방식으로 첫번째 파트(x)에 인코딩 된다.

2.4.1.2 Payload

상태, 데이터 등을 담고 있는 클레임들을 정의한다.

  • Registered claims 이미 JWT에서 정의해 놓은 클레임이다. 보통 iss(발급자), exp(만료시간), sub(제목), aud(수신자)가 대표적으로 많이 쓰인다. 의무적이진 않지만 범용성을 위해 이를 따르는 것이 좋다.
  • Public claims
    충돌 방지된 이름을 가지고 있어야 한다. 충돌 방지를 위해 URI 형식으로 짓는다.
  • Private claims
    정보를 주고받기 위해 username등 클라이언트와 서버간의 협의하에 사용되는 클레임이다.

마찬가지로 payload도 Base64Url로 인코딩 된다.

비밀 정보는 암호화 되지 않은 이상 Header나 Payload에 싣지 않도록 한다.

2.4.1.3 Signature

Base64Url로 인코딩 된 Header와 Payload값을 합친후 Head에 정의한 알고리즘으로 암호화한다.

이 signature는 메세지가 변조되지 않았음을 검증할 때도 사용된다. 또한 보낸이에 대해 검증할 때도 사용된다.

위에서 만들어진 값들을 .으로 연결하면 JWT가 완성된다.

2.4.1.4 How do JWT work?

클라이언트에서 로그인 등 인증할 떄, 인증이 완료되었다면 JWT를 받는다. 이 토큰 자체가 credential이므로 보안상의 문제를 위해 필요 이상으로 오래 가지고 있지 않는 등 주위를 기울여야 한다.

토큰을 Authorization 헤더에 실어 보낸다면 쿠키를 사용하지 않아도 되므로 쿠키로 인해 발생하는 문제가 없다.

2.5 장점

XML을 사용하는 SAML방식보다 JSON 자체가 XML에 비해 가벼우므로 JWT가 더 가볍다. 이는 HTML과 HTTP 환경에서 더 적합하다

여러가지 해싱 알고리즘을 사용할 수 있어 보안성이 높다.

parsing하기 어려운 XML에 비해 JSON은 바로 오브젝트로 매핑되므로 다양한 언어에서 parser를 지원한다.

인터넷 규모에서 사용되므로 굉장히 다양한 플랫폼에서 사용될 수 있다.

tag: android

Related Posts