Oauth를 사용해보는 실습을 해 보면서, Oauth는 Bearer authentication을 사용한다고 하였음.
HTTP authentiacation header는 뭐지?
응답 Http 메시지에만 있는건가?
그럼 평소에 사용하던 Form-based 인증을 위한 인증방법도있는가?? 라는 궁금증으로 찾아보았다.
일반적인 HTTP 인증 프레임워크
HTTP에서는 확장가능한 " 일련의 "인증요구-응답"( challenge - response 인증 전략 )들을 통해 접근 제어와 인증에 관련된 일반적인 프레임워크를 제공하고 있다.
서버에서는 클라이언트 요청에게 어떤 것을 요구(challenge) 하고, 클라이언트에서는, 인증 정보를 제공하는데에 "이런 인증 전략(스킴)" 들을 사용하고 있다.
보안 프로토콜에서 "challenge"
- 매 번 서로다른 응답을 생성하기 위해, 서버에서 클라이언트로 몇 가지 데이터를 전송하는 것
challenge -response 인증
- 한 파티가 challnege 하면 -> 상대방에서는 인증되기 위해 유효한 응답을 줘야만 한다.
-- 가장 간단한 예시 : 비밀번호 인증
Basic" Authentication 전략
RFC 7617에 명시되어있음
challenge -response flow는 다음과 같다
- Server에서는 401상태코드(Unauthorized)로 응답하면서 사용자 요청을 반려한다., WWW- Authenticate 응답헤더에 권한을 부여하는 방법에 대한 정보를 제공한다.
- 401 상태코드와 함께, " 적어도 하나의 challenge(일종의 요구임.. 인증정보가 필요하다고 클라이언트에게 사용자이름-비밀번호 같은 일정 정보를 요구하게 되는 것) 를 담고 있는 [WWW-Authenticate] response header로 , 권한을 부여하는 방법에 대한 정보를 제공한다.
- 위의 그림에서도 : WWW-Authenticate : Basic realm ="Access to the staging site" 라고 하고 있음
- 웹 서버는 "기밀문서를 보안 영역(realm) 그룹" 으로 나눈다. 보안 영역은 저마다 다른 사용자 권한을 요구한다.
- realm 은 위의 "Access to the staging site" 와 같이 "해설 형식"으로 되어 있어, 사용자 이름,비밀번호를 가지고 있는 사용자가 "권한의 범위를 이해(하고, 어떤 비밀번호를 사용해야하는지 아는데에) 하는데 도움"이 되어야 한다.
- 401 상태코드와 함께, " 적어도 하나의 challenge(일종의 요구임.. 인증정보가 필요하다고 클라이언트에게 사용자이름-비밀번호 같은 일정 정보를 요구하게 되는 것) 를 담고 있는 [WWW-Authenticate] response header로 , 권한을 부여하는 방법에 대한 정보를 제공한다.
- Client에서는 "인증 알고리즘과 , Authorization request header에 credentials(사용자 이름과 비밀번호를 기술한 ) 를 포함한 request "를 전송 한다.
- Server에서는 Credentials를 확인한다. 그리고는 200 또는 401 상태코드(ex.비밀번호가 틀렸다던가, 유효하지않은 username이라던가.. )를 포함한 response를 전송하겠다.
- 대부분의 authentication 전략에 대한 일반적인 message flow는 위와 같다. 헤더 내부의 정보나, encoded된 방식정도가 바뀔 것 이다.
현재는, HTTP의 challenge(인증요구)/ 응답 프로토콜을 사용하는 인증 프로토콜로 " OAuth"가 있고 매우 자주 쓰인다.
OAuth는 모바일 기기 같은 다양한 app에서 API 인증을 위해 사용한다.
- 기본 인증에서 서버는 클라이언트의 요청을 거부 && 유효한 사용자 이름,비밀번호 요구를 할 수 있다.
- 기본 인증에서 서버는 401 상태코드와 함께, "클라이언트가 접근하려 했던 보안영역을 WWW-Authenticate에 기술해 응답" 하여 "인증 요구를 시작"한다.
- 브라우저는 사용자가 입력한 이름,pwd를 Authorization 요청헤더 에 인코딩하여 서버로 다시 보낸다.
프록시 인증
중개 프록시 서버를 통해 인증 할 수도 있다.
- 프락시 서버에서 접근 정책을 "중앙 관리" 할 수 있기에, 회사 리소스 전체에 대해 "통합적인 접근 제어"를 하기 위해 사용하면 좋다.
- 여기서도 "프록시 인증"으로 "사용자 식별"과정이 필요하다.
--- 프록시 인증은, "웹서버 인증과 동일한 인증요구-응답 절차를 가졌다.
--- 다만, header ("Proxy-Authenticate" 라는 response header ,"Proxy-Authorization" request header) , 상태코드(407)가 다를 뿐이다.
Access forbidden
- 만약 (proxy) server가 " 유효하지 않은 credentials"를 받는다면, 401 또는 407로 응답한다. 그러면 사용자는 " 새 요청을 보내거나", " Authorization header field를 교체한 요청"을 보낼 것 이다.
- 만약 (proxy) server가 유요한 credential을 받았으나, 요청한 resource에 접근하기에는 부적절하다면, server는 403 상태 코드로 응답해야 한다.
- 401,407과는 달리, 이 user의 authentication이 불가능한 것이기 때문에 , 브라우저는 다시 시도하려고 하지 않을 것이다.
- 근데 대부분의 경우, server에서는 404 (Not Found) 코드를 보내는 경우가 많을 거임.
- 왜냐하면, 적절한 권한이 없거나, 인증되지 않은 사용자에게 page의 존재에 대해 숨기기 위함.
WWW-Authenticate와 Proxy-Authenticate headers ( 응답 헤더 )
- 둘 다 resource에 대한 access를 획득하기 위해 사용되어야 하는 authentication method를 정의한다.
- 어떤 authentication 전략이 사용되었는지 명시해야만, 인증하고자 하는 client가 어떤 crendential을 제공할지를 알 수 있다.
이런 syntax
WWW-Authenticate: <type> realm=<realm>
Proxy-Authenticate: <type> realm=<realm>
- 여기서 < type > 이 authentication전략이다.
- "Basic"이 가장 흔한 전략임.
- realm : scope of protection을 나타낸다 . 웹 서버는 "기밀문서를 보안영역(realm) 그룹"으로 나눈다.
- 보안 영역은 저마다 다른 사용자 권한을 요구한다.
- 사용자가 접근하려고 하는 space가 무엇인지 알게끔 해 준다.
Authorization과 Proxy-Authorization headers ( 요청 헤더 )
- 이 request header들은, user agent를 (proxy) server에게 authenticate하기 위한 credentials를 담고 있다.
- 여기서, credentials 앞에는 <type> 이 또 필요하다.
- 사용하는 authentication 전략에 따라서, <type> 은 encoded되어있거나 encrypted되어있을 수 있다.
보안적 결함
- 위 "Basic" Authentication ( 기본 인증 )→ encoded는 되었지만 encrypt는 되지 않은 credential(사용자이름-비밀번호) 을 전송했다.
- HTTP Basic Authentication : 사용자이름과 비밀번호를 콜론으로 합치고 ( 사용자이름: 비밀번호), base-64인코딩을 한다.
- base-64 인코딩은 암호화된 것이 아니다. 그저 "여러 타입의 문자열"을 "전송가능한 문자인 알파벳으로 변환"하기 위해 발명된 것이다. 전송중 원본 문자열이 변질될 걱정을 없애주는 용도.
- 따라서, 보안상 매우 취약( 디코딩 하기에 매우 쉬움 )하다.→ secure connection(HTTPS/TLS) 을 통한 전송이 이루어져야 할 것
- 이 사이트에는 사용자 로그인 정보가 털려도 중요하지 않다 하더라도, 문제는 일반적인 사용자들의 행태( 여러 곳에서 같은 비번 사용) 상, 이것이 보안상 매우 위험해지는 것.
- 좀 더 복잡하게 암호화되었다고 하더라도, 여전히 네트워크상에서, 제3자가 패킷을 가로채, 이를 원 서버로 보내 인증에 성공 && 서버 접근을 할 수 있다.
Authentication 전략
위에서 본, 일반적인 HTTP 인증 프레임워크가 다양한 인증 전략에 대한 기초가 된다. ( 그리고 우리가 본 인증 자체가 Basic 인증 전략(scheme)임 )
다양한 인증전략
Basic, Bearer, Digest, HOBA, Mutual, Negotiate/NTLM , VAPID, SCRAM, ...
- 참고로 OAuth2에서는 "Bearer" 을 사용한다.
- 전략에 따라, 보안의 강력함 정도가 다르다.
- 예상가능하나, Basic이 가장 최악의 보안 제공.하지만 세팅하기에 제일 쉬움.
위에서 봤지만 기본 인증전략부터 다시 간단히보자면
Basic Authentciation 전략
RFC 7617에 명시되어있음.
- username:password 와 같은 credentials를 request header에 넣어서 전송한다.
- 이런 credentials는 base64로 인코딩되어있다.
- base64 : 64개의 chracter로 변환
- 이 방식은, cookies도, session IDs 도, login 페이지도 필요로 하지 않는다. 그냥 HTTP header 자체를 사용하기 때문임..
Security
-- 사용자 ID와 password가, "clear text(base64로 인코딩 되어있긴 하지만, base64는 reversible encoding임..) 형태로" 네트워크 너머로 전송된다.
-- 그니까 안전하지가 않다.
-- HTTPS/TLS 가 같이 사용되어야만 한다!!
추가적으로 보안을 강화할만한 것 없이는, 민감정보,중요정보에 대해서는 basic authentication을 사용해서는 안된다.
Bearer Authentication
token authentication이라고도 불린다.
bearer tokens이라고 불리는 security tokens을 포함하는 방식이다.
- bearer token을 통해, 특정 리소스 또는 URL에 대한 접근이 허용된다.
- bearer token은 주로 login 요청에 대해 서버에서 생성한 cryptic string( 암호화된 문자열) 이다.
- client에서는 보호되는 리소스에 대한 요청을 보낼 때, Authorization header에 이 token을 같이 전송해야 한다.
- Basic authentication과 마찬가지로, Bearer authentication도 오직 HTTPS( SSL) 을 통해서만 사용해야 한다. ( 토큰 서명만으론 안전하지 않음 )
- 구글 정책이 바뀌어서, Oauth2를 사용하는 경우, AWS에서도 HTTPS를 사용해야한다고 한다.
Form - based 인증은? Basic Authentication과 차이가 뭘까?
Oauth 와 같은 것을 사용하기 이전까지 나는 계속해서 HTTP form + POST 방식을 사용하여 사용자 인증정보를 날리곤 했다.
즉, form-based authentication을 해왔었다.
이것과 Basic authentication의 차이는 뭘까?
@@ Basic Authentication
RFC7617 에 공식적으로 정의가 되어있다. 즉, 공식 문서에서, 해당 인증 솔루션이 어떻게 동작하는지에 설명해주고 있음.
Basic Auth에서는,클라이언트에서 서버에게 요청을 보낼 때 사용자이름,비밀번호를 제공하기위해 HTTP header 를 사용한다. 위에서 봤듯이 이때 사용되는 헤더는 이런형태를 띈다.
Authorization: Basic Base64-encoded(형태는 username:password) <-- username 뒤에 콜론(:) + password
-- 즉, credentials가 username과 password를 ":" 으로 붙인 것의 base64 인코딩된 형태다.
👏 Form- Based 인증과 달리, Basic 인증에서는 쿠키를 사용하지 않는다!!!! 따라서, session이라던가, 로그아웃이라는 개념이 없음. 따라서 각각의 request는 인증을 위해 매번 위의 header 정보를 가져야하는 거임.
@@ Form-Based 인증
Form-based 인증방식은 RFC에 의해 공식화 된 방법이 아니다. 그저 인증을 위한 프로그래밍적 방법으로, Basic Auth에서 매 request마다 인증을 해야하던 것을 조금 더 쉽게(?mitigate?)하기 위해 사용된다.
대부분의 Form-based 인증에서는 POST request 를 통하여 표준 HTML form field를 사용하여 username과 pwd를 값을 서버로 넘기게 된다
->server에서는, 해당 credentials를 검증하고는 , 쿠키에 저장되는 "unique token"에 대한 세션을 생성한다.
-> 서버에서는 해당 쿠키를 client에게로 전달
-> 클라이언트에서는 매 번 해당 cookie를 포함한 http 요청을 한다.
-> 만약 해당 쿠키가 invalid하거나 로그아웃한 사용자라면, 서버에서는 로그인 페이지로 redirect 시키면된다.
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
위의 Basic 인증에서는 매 요청 header에 Authorization 정보를 가졌다면, 이제는 매번 Cookie를 갖고 가야하는게 된 거 아닌가??
ㅇㅇ
그런데 Authorization 헤더에는 실제 credentials 정보가 있었다는 것이 주요한 차이로 보인다.
그리고 jwt 와 같은 토큰을 사용할 때에는(매 번 헤더에 토큰 정보를 contain해서 요청을 보내게됨 ), 토큰의 claim ? payload? 부분에 민감정보는 넣지 않게 되어있다. (그럼 뭘 넣는냐 ? -> User의 id값 같은 거.. User의 id값 자체로는 민감정보가 아니니까 )
참조
HTTP authentication - HTTP | MDN
'네트워크_aws_등등' 카테고리의 다른 글
HTTPS와 SSH ( 개요 정도의 수준 글 ) (0) | 2022.02.20 |
---|