HTTP 기본 인증을 사용해본 적이 없었는데 이번에 SAP 연동을 진행하면서 SAP의 CSRF Token 발행을 위해 HTTP 기본 인증을 처음으로 사용해봤다. (사실 아주 예전에는 사용했을지도 모르겠지만 기억은 못할 것 같다.) 그러면서 몇몇 대표적인 인증 방식에 대한 차이점이 궁금해져서 정리 해본다.
인증(Authentication)과 권한부여(Authorization)
일단 먼저 용어 정리를 하고 지나가자.
보통 Auth라고 쓰는 표현을 많이 접하게 될텐데, 실제 이런 표현을 사용하는 경우에는 인증(Authentication)과 권한부여(Authorization)을 다 포함하는 개념으로 사용한다. 실제 로그인을 통해서 인증을 거치게 되면 인증 이후에 이어서 권한부여까지 이루어지기 때문이다.
2개를 따로 분리해서 짚고 넘어가는 이유는 종종 2가지 표현이 섞여서 사용되는 경우 혼란스럽고 이해가 어려워지기도 하기 때문인데, 어느 정도 개념은 분리해서 알고 있으면 다른 기술 문서를 보기에도 편할 것 같다.
인증(Authentication)
인증은 사용자의 신원을 확인하는 과정이다. 신원을 확인한다는 표현이 좀 거창하긴 하지만 우리가 이메일 주소와 비밀번호를 이용해서 로그인하는 과정을 생각하면 된다. 물론 이메일주소와 비밀번호를 이용해서 인증을 하는 경우 외에도 OTP나 SSO, 혹은 요즘 많이 사용하는 생체인증 같은 것들도 모두 사용자를 확인하는 방법들이며 “누구세요?”라는 질문에 답을 하는 여러 가지 방법이라고 생각한다.
권한부여(Authorization)
사용자의 접근 권한을 확인하는 과정을 말한다. 접근 권한을 확인하기 위해서는 사용자의 신원을 확인하는 과정이 선행되어야 하므로 인증을 거친 이후에 진행된다.해당 사용자가 접근하는 데이터에 대해서 어떤 권한을 가졌는지를, 다시 말해 무엇을 할 수 있는지를 결정하는 과정이다.
HTTP Basic Authentication
이 글을 쓰게 된 이유인 HTTP 기본 인증이다. 쉽게 말하면 username과 password를 http header에 포함시켜서 전송하여 사용자를 증명하는 방식이다. 이때 username과 password를 “:”를 이용해서 붙인 것을 “credential” 라고 하는데 이걸 Base64로 인코딩한 스트링을 http header에 “Authorization”이란 이름으로 넣어서 서버에 전송한다.
Authentication를 하기 위해 헤더에 넣는 이름이 “Authorization”인게 신기한건 나만 그런가? 뭐, 이름을 왜 이렇게 지었는지까지는 모르겠으나 그만큼 인증과 권한부여가 한 사이클에서 이루어지는게 대부분이라 그런게 아닐까 생각해본다.
두번째 의아한 점은 Base64로 인코딩하는 형식이다. 정말 놀랄만큼 순진한 방식 아닌가? 알다시피 base64는 보안적인 측면이 전혀 없고 바이너리 데이터 전송을 위한 방식인데 이렇게 위험하게 보내도 괜찮은 걸까?
이것저것 찾아본 결과로는,
- HTTP 규격에서는 보안적인 측면을 고려하지는 않았다는 점은 확실한 것 같다. 생각해보면 당연하기도 한게 보안 알고리즘은 계속 발전하기도 하고 특정 보안 매커니즘을 HTTP 규격 사양에 적용하는 것이 더 이상하니까. SSL과 같은 다른 기술을 혼합해서 사용하는 것이 맞겠다.
- Base64 인코딩을 사용하는 것은 Base64의 원래 목적처럼 시스템의 ASCII 코드에 대한 처리 방식에 독립적으로 안전하게 처리하기 위한 것이고 우리는 그냥 일반적으로 사용하는 user id와 password만 생각하지만 사실 인증은 사람이 아닌 시스템이나 프로세스등에서도 거쳐야 하는 과정이기 때문에 모든 데이터가 안전하게 문자화 될 수 있는 방법이 필요하다. Base64 인코딩을 암호화 하는 걸로 착각이나 하지 말자. Base64면 아주 최소한의 난독화가 되긴 하겠지만 이건 Base64를 사용하는 이유가 되지 않는다.
결론적으로 HTTP 프로토콜에서 제공하는 인증 자체에 대한 매커니즘이며 암호화나 인증 이후 세션 유지에 대한 고려는 되어 있지 않다. 그러므로 기본적으로는 매 요청 시마다 보내는 것이 원칙이다. 암호화나 세션/쿠키 관리에 대한 고민은 인증 방식과 분리해서 생각하자.
만약 웹 화면에서 인증정보 없이 서버에 요청하면 302 응답과 함께 자세한 인증 방법이 포함된 응답을 받는다. 브라우저는 user id와 password를 요청하는 팝업을 띄워서 입력받아 처리한다. 이런게 표준의 편리함 아닐까? ㅎㅎ
Form Authentication
폼 인증이라는 방식은 사실 HTTP 프로토콜 차원에서 제공하는 HTTP Basic Authentication과 같은 표준 방식은 아니지만 로그인을 통해서 접근하는 사이트와 같이 가장 많이 사용되는 형식이 아닐까 한다. 말 그대로 HTML에서 입력받은 Form의 id, password를 이용해서 서버에 인증을 요청하는 형식으로 아무래도 사용자가 입력하는 Form 데이터를 그대로 사용할 수 가 있어서 웹 사이트와 같은 서비스에서는 가장 많이 사용되는 형식인 것 같다.
이렇게 Form에서 입력받은 데이터를 사용한다는 표현이 있으나 위의 Http 기본 인증과 결정적으로 차이가 있는 것은 인증정보를 어디에 포함시켜서 서버에 전송하느냐의 차이이다. 즉, 여기서 얘기하는 Form은 사용자가 입력하는 화면의 Form이 아니라 Form 데이터로 전송한다는 점에 포커스가 있다. 억지스러울 수 있지만 화면만 Form으로 구성하고 실제 전송은 헤더에 넣어서 전달 할 수도 있는 일이다.
Form 데이터는 http method가 get, post중 어느 것이라고 역시나 보안적인 요소는 고려되어 있지 않다. 주소창에서 보냐 개발자도구로 볼 수 있냐의 차이일뿐… 그러한 이유로 보안적인 측면은 SSL이나 RSA와 같은 기술들을 같이 적용해야 하고 일반적으로는 세션과 쿠키등을 이용해서 인증을 관리한다.
이건 하나의 표준이라기 보다 인증을 구현하는 일종의 패턴으로 분류해야 하는 것은 아닐까 싶다.
OAuth2
개방형 인증 프로토콜(Open Authentication 2.0)이다. HTTP Basic Authentication이 HTTP 프로토콜에서 제공하는 표준 인증 방식이라면 이건 순수하게 인증만을 위해서 구현된 프로토콜이다. 이게 무슨 말이냐하면… 여기에 다 설명을 정리하기에는 내용이 어마무지하다는 것이다. ㅎㅎ
최초 글을 쓰기 시작할때 의도처럼 비교하는 수준에서만 살펴보자. 필요하면 별도의 글로 정리해야 할 듯.
더 쉽게 생각하면 구글, 페이스북, 카카오, 네이버와 같은 곳에서 제공하는 간편로그인이 OAuth 2.0 기반으로 서비스이다.
실제 인증 절차를 구성하는 방식은 좀 더 다양할 수 있지만 기본적으로는 인증서버가 별도로 존재하고 인증과정을 인증서버를 통해서 진행한 이후에 획득한 Access Token을 이용해서 실제 리소스 서버에 요청을 하는 형식이다.
이런 방식의 핵심은 인증을 별도의 인증 서버에 위임한다는 점인데, 사용자 입장에서는 각각 사이트별로 회원가입을 일일이 하지 않아도 되고, 입력하는 아이디와 패스워드를 인증서버에만 전달하지 리소스 서버에 전달하지 않는다는 점이 더 안전하다는 정도가 장점이 될 듯 하다.
게다가 OAuth2가 인증보다는 권한부여에 대해 더 특화된 느낌인데, 이런 점은 리소스 서버별로 어떤 정보까지 접근할 수 있을지 API등을 컨트롤 할 수 있다는 점이 장점이다.
결론
위에서 얘기하는 3가지 인증 방식은 분리된 개념이 아니라는 것이 가장 중요한 점이다. 인증을 하기 위한 여러가지 방법들을 어떤 면에서 보았느냐에 따라서 구분하는 정도이다. OAuth2 기술을 사용하면서 실제 인증서버와 인증과정에서는 Form인증이나 HTTP Basic 인증을 사용할 수 있다는 뜻이다.
웹 애플리케이션을 주로 구축하던 입장에서 모든 기술을 내가 아는 범위에서 이해하려고 하는 경향이 있는데, 실제 우리가 사용하는 기술들은 그것보다 훨씬 다양한 분야에서 사용되는 기술들이고 그런 상황을 감안하여 구성된다. 장단점과 특성을 잘 이해하고 필요한 기술들을 선택하는 것은 점점 어려워지는 것 같다. 현실에서는 뭔가 유행하는 기술을 선택하는 경향이 있는 것 같지만…