본문 바로가기

24DAY 백엔드

24DAY 백엔드 - 12DAY 인증

728x90

인증이 필요한 이유

 

클라이언트가 서버에 접속하면 서버는 클라이언트을 식별하기 위해서 인증이 필요합니다.

 

1. Session / Cookie 방식

Cookie 란?

하이퍼 텍스트의 기록서의 일종으로서 인터넷 사용자가 어떠한 웹사이트를 방문할 경우 그 사이트가 사용하고 있는 서버를 통해 인터넷 사용자의 컴퓨터에 설치되는 작은 기록 정보 파일입니다.

 

 

순서도

 

1. 사용자가 로그인을 합니다.

2. 서버에서는 계정정보를 읽어 사용자를 확인한 후, 사용자의 고유한 ID값을 부여하여 세션 저장소에 저장한 후, 이와 연결되는 세션ID를 발행합니다.

3 사용자는 서버에서 해당 세션ID를 받아 쿠키에 저장을 한 후, 인증이 필요한 요청마다 쿠키를 헤더에 실어 보냅니다.

4. 서버에서는 쿠키를 받아 세션 저장소에서 대조를 한 후 대응되는 정보를 가져옵니다.

5. 인증이 완료되고 서버는 사용자에 맞는 데이터를 보내줍니다.

 

 

세션 쿠키 방식의 인증은 기본적으로 세션 저장소를 필요로 합니다. 세션 저장소는 로그인을 했을 때 사용자의 정보를 저장하고 열쇠가 되는 세션ID값을 만듭니다. 그리고 HTTP 헤더에 실어 사용자에게 돌려보냅니다. 그러면 사용자는 쿠키로 보관하고 있다 인증이 필요한 요청에 쿠키(세션ID)를 넣어 보낼 것입니다. 웹 서버에서는 세션 저장소에서 쿠키(세션ID)를 받고 저장되어 있는 정보와 매칭시켜 인증을 완료합니다.

 

(장점)

  1. 세션/쿠키 방식은 기본적으로 쿠키를 매개로 인증을 거칩니다. 여기서 쿠키는 세션 저장소에 담긴 유저 정보를 얻기 위한 열쇠라고 보시면 됩니다. 따라서 쿠키가 담긴 HTTP 요청이 도중에 노출되더라도 쿠키 자체(세션 ID)는 유의미한 값을 갖고있지 않습니다(중요 정보는 서버 세션에) 이는 위의 계정정보를 담아 인증을 거치는 것보단 안전해 보입니다. 
  2.  고유의 ID값을 발급받게 됩니다. 서버에서는 쿠키 값을 받았을 때 일일이 회원정보를 확인할 필요 없이 바로 어떤 회원인지를 확인할 수 있어 서버의 자원에 접근하기 용이할 것입니다. 

 

(단점)

  1. 해커가 HTTP 요청을 통해 쿠키도 충분히 훔칠 수 있습니다.
  2. 서버에서 세션 저장소를 사용한다고 했습니다. 따라서 서버에서 추가적인 저장공간을 필요로 하게되고 자연스럽게 하도 높아질 것입니다.

2. 토큰 기반 인증 방식(JWT)

JWT는 세션/쿠키와 함께 모바일과 웹의 인증을 책임지는 대표주자입니다. JWT는 Json Web Token의 약자로 인증에 필요한 정보들을 암호화시킨 토큰을 뜻합니다. 위의 세션/쿠키 방식과 유사하게 사용자는 Access Token(JWT 토큰)을 HTTP 헤더에 실어 서버로 보내게 됩니다.

 

 

토큰을 만들기 위해서는 크게 3가지, Header,Payload, Verify Signature가 필요합니다. 

 

  • Header : 위 3가지 정보를 암호화할 방식(alg), 타입(type) 등이 들어갑니다.
  • Payload : 서버에서 보낼 데이터가 들어갑니다. 일반적으로 유저의 고유 ID값, 유효기간이 들어갑니다.
  • Verify Signature :  Base64 방식으로 인코딩한 Header,payload 그리고 SECRET KEY를 더한 후 서명됩니다.

최종적인 결과 : Encoded Header + "." + Encoded Payload + "." + Verify Signature

 

Header, Payload는 인코딩될 뿐(16진수로 변경), 따로 암호화되지 않습니다.

따라서 JWT 토큰에서 Header, Payload는 누구나 디코딩하여 확인할 수 있습니다.

여기서 누구나 디코딩할 수 있다는 말은 Payload에는 유저의 중요한 정보(비밀번호)가 들어가면 쉽게 노출될 수 있다는 말이 됩니다. 

 

하지만 Verify Signature는 SECRET KEY를 알지 못하면 복호화할 수 없습니다. 

예로 A 사용자가 토큰을 조작하여 B 사용자의 데이터를 훔쳐보고 싶다고 가정하겠습니다. 그래서 payload에 있던 A의 ID를 B의 ID로 바꿔서 다시 인코딩한 후 토큰을 서버로 보냈습니다. 그러면 서버는 처음에 암호화된 Verify Signature를 검사하게 됩니다. 여기서 Payload는 B사용자의 정보가 들어가 있으나 Verify Signature는 A의 Payload를 기반으로 암호화되었기 때문에 유효하지 않는 토큰으로 간주하게 됩니다. 여기서 A사용자는 SECRET KEY를 알지 못하는 이상 토큰을 조작할 수 없다는 걸 확인할 수 있습니다.

 

 

 

순서도

 

 

1. 사용자가 로그인을 합니다.

2. 서버에서는 계정정보를 읽어 사용자를 확인 후, 사용자의 고유한 ID값을 부여한 후, 기타 정보와 함께 Payload에 넣습니다.

3. JWT 토큰의 유효기간을 설정합니다.

4. 암호화할 SECRET KEY를 이용해 ACCESS TOKEN을 발급합니다.

5. 사용자는 Access Token을 받아 저장한 후, 인증이 필요한 요청마다 토큰을 헤더에 실어 보냅니다.

6. 서버에서는 해당 토큰의 Verify Signature를 SECRET KEY로 복호화한 후, 조작 여부, 유효기간을 확인합니다.

7. 검증이 완료된다면, Payload를 디코딩하여 사용자의 ID에 맞는 데이터를 가져옵니다. 

 

 

세션/쿠키 방식과 가장 큰 차이점은 세션/쿠키는 세션 저장소에 유저의 정보를 넣는 반면, JWT는 토큰 안에 유저의 정보들이 넣는다는 점입니다. 물론 클라이언트 입장에서는 HTTP 헤더에 세션ID나 토큰을 실어서 보내준다는 점에서는 동일하나, 서버 측에서는 인증을 위해 암호화를 하냐, 별도의 저장소를 이용하냐는 차이가 발생합니다.

 

(장점)

 

  1. JWT는 발급한 후 검증만 하면 되기 때문에 추가 저장소가 필요 없습니다. 이는 서버를 확장하거나 유지,보수하는데 유리합니다.
  2. 확장성이 뛰어납니다토큰 기반으로 하는 다른 인증 시스템에 접근이 가능합니다.

(단점)

  1. JWT는 한 번 발급되면 유효기간이 완료될 때 까지는 계속 사용이 가능합니다. 악의적인 사용자는 유효기간이 지나기 전까지 정보들을 유출 가능성이 있습니다.
  2.  Payload 정보가 제한적입니다. 위에서 언급했다시피 Payload는 따로 암호화되지 않기 때문에 디코딩하면 누구나 정보를 확인할 수 있습니다.
  3. 세션/쿠키 방식에 비해 JWT의 길이는 깁니다. 따라서 인증이 필요한 요청이 많아질 수록 서버의 자원낭비가 발생하게 됩니다.

3. OAuth

OAuth?

인터넷 사용자들이 비밀번호를 제공하지 않고 다른 웹사이트 상의 자신들의 정보에 대해 웹사이트나 애플리케이션(외부서비스)허가(접근 권한)을 부여할 수 있는 공통적인 수단으로서 사용되는, 접근 위임을 위한 개방형 표준입니다.

  • 권한 : OAuth는 인증뿐만 아니라 권한도 관리합니다. 사용자의 권한에 따라 접근할 수 있는 데이터가 다르도록 설정이 가능합니다. 
  • 프로토콜 : 특정한 프로그램을 지칭하는게 아니라 일종의 규격입니다. Facebook, Google, Naver 등은 OAuth라는 규격에 맞춰 인증 및 권한을 대행관리 해줍니다
  • 외부서비스 : 우리가 만들고 있는 서비스를 이야기합니다. 외부 서비스를 위한 서비스인 OAuth는 우리 서비스의 인증 및 권한부여를 관리를 대행해줍니다.

4. OPENid

OpenID는 하나의 ID로 가입 절차 없이도 OpenID를 지원하는 여러 사이트에서 로그인을 할 수 있는 분산형 인증 공개 표준 기술을 말합니다. 

OpenID 는 사용자 중심 identity 를 위한 분산형 공개 표준 기술 입니다.
OpenID 는 웹사이트처럼 하나의 URI (URL 또는 주소)로 누구나 인터넷상에서 자신을 식별하게 해줍니다. URI 는 웹 아키텍쳐의 가장 핵심이기 때문에, 사용자 중심 identity 를 위한 단단한 토대를 제공합니다.

OpenID 기술의 첫번째 부분은 인증(authentication - URI 의 소유자임을 증명하는것) 입니다. 오늘날 웹사이트들은 로그인하기 위해 사용자이름과 암호를 요구하는데, 사실 많은 사람이 같은 암호를 거의 모든곳에 사용하고 있습니다. OpenID 인증(see specs)에서는, 당신의 이름은 당신의 URI 주소이고 당신의 암호(또는 다른 인증서)는 당신의 OpenID 제공서버(당신이 직접 운영하거나 제 3 자가 제공하는) 에만 안전하게 보관됩니다.

당신은 하나의 OpenID 로 OpenID 를 지원하는 모든 웹사이트들에 복잡한 가입 절차 없이 로긴할 수 있습니다.

자세히 설명드리면 회원님이 특정 웹사이트를 이용하기 위해 가입을 하면 그 웹사이트에서만 로그인을 하여 서비스를 이용할 수 있습니다. 요컨데 해당 웹사이트에서의 로그인 인증은 그 웹사이트로 한정됩니다. OpenID는 로그인 인증을 제공하는 서비스를 하나의 웹사이트로 한정하지 않고 OpenID 인증 사이트에만 가입을 하시면 OpenID를 지원하는 다른 사이트에서도 로그인이 가능합니다.

5. SAML

Single Sign On을 지원하기 위한 프로토콜이나 방법은 여러가지가 있다.

그중 대표적인 방법으로 CAS,SAML,OAuth등이 있는데, CAS는 쿠기를 기반으로 하기 때문에 같은 도메인명 (xxx.domain.com yyy.domain.com) 사이에서만 SSO가 가능하다. (그만큼 구현도 쉽다.) OAuth는 현재 B2C쪽에 많이 사용되는 프로토콜이고, 그리고 마지막으로 SAML 있다. cross domain간 SSO 구현이 가능하며, OAuth 만큼이나 많이 사용되고 있다. 

 

SAML는 어떤 구현체가 아니라 SSO을 구현가 위한 XML 스펙입니다.

HTTP GET, POST 또는 SOAP 웹 서비스등 여러가지 방법으로 구현될 수 잇으며, 여기서 HTTP Post를 이용한 SSO 원리와 솔루션 설계시 유의 사항을 설명합니다.

 

1. Site SP A로 초기 로그인

 

  1. Browser에서 사이트 SPA로 접속합니다.
  2. 사이트 SpA에는 로그인 되어 있지 않기 때문에(세션이 없어서), SpA에서는 SAML request를 만들어서, Browser에게로redirect URL를 보냅니다.
  3. Browser는 redirect URL에 따라 IdP에 접속하고, Idp에서 login form을 넣고 log in을 합니다. 이때 IdP와 Browser 사이에 HttpSession 또는 Cookie로  Login에 대한 정보를 기록합니다.
  4. Browser는 SAML Reponse를 가지고 SpA로 접속하면, SPA에는 인증된 정보를 가지고 로그인 처리를 합니다.( 이과정에서 미리 정의한 SpA의 SAML response 처리 URL로 갔다가 SAML response를 처리가 끝나면 인증 처리를 한후,
  5. 사용자 페이지으로 다시 redirect 합니다.

2.  Site Sp A로  로그인된 상태에서 Site Sp B로 로그인

  1. 사이트 spA에서 로그인된상태에서 spB에 접속합니다.
  2. 사이트 SpB는 로그인이 되어 있지 않기 때문에, SAML 메시지를 만들어서 IdP의 login from으로 redirect URL을 보냅니다.
  3. 브라우져는 redirect URL을 따라서 IdP에 접속을 합니다. IdP에 접속을 하면 앞의 과정에서 이미 Session 또는 Cookie가 만들어져 있기 때문에 별도의 로그인 폼을 띄위지 않고, SAML response message와 함계, spB로 의 redirect URL을 전송합니다.

발생할 수 있는 문제점

 

1. Idp에는 대규모 사용자를 지원할 경우, Session 정보를 어떻게 분산 저장할것인가입니다.

WSO2 Identity server의 경우네는 각 instance의 memory에 이 session 정보를 저장하고, 자체 clusterting feature를

이용하여 이 session을 상호 복제합니다. Oracle WebLogic이나 Apache Tomcat cluster의 Http session clustering과 같은 원리입니다. 이 경우에 각 instance의 메모리 size에 따라 저장할 수 있는 session의 수의 한계를 가지게 되고, instance간 session 복제로 인하여, 장애 전파 등의 가능성을 가지게 됩니다. 그래서 Shibboleth의 경우에는 이 Session 정보를 별도의 terracotta와 같은 data grid에 저장하도록 하여, 확장성을 보장할 수 있습니다 

 

2. 로그 아웃에 대한 문제입니다. Sp A나 Sp B에 SAML을 이용한 초기 인증이성공한 경우, 제 로그인(인증)을 막기 위해서 자체적으로 HttpSession등 사용하여, 별도의 log in session을 유지해야 하는데, 이 경우 Sp a, Sp B의 Session Time out 시간이 다를 수 있기 때문에, 한 사이트에서 log 9out이 된 경우 전체 사이트에 걸쳐서 log out이 안될 수 있는 incosistency 문제가 발생합니다. 그래서 WSO2 identity server이 경우에는 별도의 logout URL을 정의하여, IdP에서 log out을 한 경우에 전체 사이트에서 loig out을 시키는 global log lout 기능을 제공합니다.

 

SAML 기반의 SSO 솔루션은 대표적으로 

 

simplePHPSAML - 가장 널리 쓰이고, 사용이 쉽다.

Shibboleth - java stack으로 구현이 되어 있으며, terracotta를 이용하여 session을 저장하기 때문에 상대적으로 확장성이 높다.

WSO2 identity server - 앞에서도 언급하였듯이, 확장성에 문제가 있는 것으로 보이며, 자체 OSGi 컨테이너인 carbon 엔진 위에서 동작한다. SAML 뿐만 아니라 OAuth,STS 서비스를 추가 지원하며, Provisioning protocol인 SCIM도 함께 지원한다. 오픈 소스이지만, 제품 완성도가 매우 높고, 사용이 매우 쉽다. (모니터링,관리 기능등이 강점)

Open AM - Sun IDM을 모태로 하여, 현재 오픈소스화 되었다. 아무래도 enterprise 제품을 기반으로 하다 보니 복잡도가 상대적으로 높다.

CAS - TBD