2012년 6월 27일 수요일

[DevWorks] TAI(Trust Association Interceptor)와 WebSphere Application Server를 사용하여 OAuth 토큰 지원하기


TAI(Trust Association Interceptor)와 WebSphere Application Server를 사용하여 OAuth 토큰 지원하기

소개
OAuth(Open Authorization)는 사용자가 사용자 이름 및 비밀번호와 같은 민감한 계정 정보를 제공하지 않아도 이용자가 사용자 역할을 할 수 있게 하여 데스크탑과 웹 애플리케이션(이용자)에서 안전한 API 인증을 허용하는 오픈 프로토콜이다.
이용자는 모든 고객의 사진을 하나의 웹 페이지에 모으려고 하는 회사이다. 모든 사용자에게 계정을 공유하는 각 사진의 사용자 이름과 비밀번호를 입력하라고 요청하는 대신에 회사가 고객 역할을 할 수 있으며, 웹 사이트를 공유하는 각 사진이 서비스 제공자 역할을 하여 OAuth 토큰을 교환할 수 있다. 이렇게 하면 사용자가 사용자 이름과 비밀번호 정보를 제공하지 않게 되므로 사진을 수집하는 회사는 사용자 계정의 보안을 손상시키지 않으면서 사용자의 사진에 액세스할 수 있게 된다.
개인이나 조직이 OAuth 서비스 제공자가 되려면 OAuth 토큰 요청을 지원하도록 시스템을 구성해야 한다. 이렇게 하는 방식은 여러 가지가 있지만, OAuth를 IBM WebSphere Application Server, LTPA 및 WS-Security가 포함된 특정 애플리케이션 요구사항과 통합하는 가장 좋은 방식을 찾으려고 하는 프로젝트가 오랫동안 진행된 후에야 조사된 모든 가능한 방식 중, TAI를 사용하는 것이 가장 좋다는 사실을 분명하게 확인할 수 있었다.
사용자 정의 TAI(Trust Association Interceptors)를 이용하면 벤더에서 획득한 보안 서비스를 WebSphere Application Server와 통합할 수 있다. 이 경우에는 OAuth가 사용할 보안 서비스에 해당된다. 상위 레벨에서는 TAI가 다음과 같이 작동한다.
  1. WebSphere Application Server로 요청이 들어오면 HttpServletRequest와 HttpServletResponse를 따라서, WebSphere Application Server 보안 설정에 구성된 각 TAI로 요청이 전달된다.
  2. 그러면 각 TAI가 HttpServletRequest 오브젝트에 전달된 매개변수에서, 보안 서비스에서 ID 어설션을 처리하기 위해 갖고 있는 보안(인증 또는 권한) 속성을 검색하여 그 TAI가 의도된 TAI인지 판별한다.
  3. TAI의 다음 단계에서는 요청 과정에서 제공한 데이터를 사용하여 ID를 생성하고 이 ID를 WebSphere Application Server에 확인한다. 그러면 TAI가 구성된 레지스트리에서 사용자를 검색하여 SSO 토큰을 생성한다.
  4. OAuth 사용자 정의 TAI는 필수 OAuth 요청 매개변수를 확인하고 OAuth 액세스 토큰의 유효성을 검증하여 해당 사용자의 인증 여부와 토큰의 유효성을 판별한다.
이와는 대조적으로 표 1에는 다른 솔루션에서 발생한 문제점이 나열되어 있다.

표 1. TAI에 대한 대안
대안 발견된 문제점
JAAS 사용자 정의 로그인 모듈 고객이 제공한 OAuth 토큰을 재생성하려면 HTTP 요청과 응답에 액세스해야 한다. 불행히도 모듈이 WEB_INBOUND JAAS 로그인의 일부인 경우에만 이 토큰을 로그인 모듈과 함께 사용할 수 있다. 이 개념이 작용하지 않는 또 다른 이유는 OAuth 요청 매개변수가 존재하지 않는 경우에만, 기본적인 사용자 이름/비밀번호 인증을 사용하고 싶지만 JAAS 로그인 모듈 방식의 사용을 막을 수 있는 방법이 없기 때문이다. OAuth 요청을 사용하면 액세스 토큰이 사용자 인증을 처리하기 때문에 사용자 이름/비밀번호를 제공하지 않아도 된다.
사용자 정의 토큰 생성기/이용자 사용자 정의 로그인 모듈과 마찬가지로, OAuth 토큰을 재생성하기 위해 요청/응답에 액세스할 수 없었다. 그 결과 방식이 매우 복잡하게 되었다.
필터 이 방식에서는 특정 애플리케이션을 위한 컴포넌트가 필요하다. 다수의 웹 프로젝트에서 자원을 보호하려고 하면, 각 프로젝트에서 필터를 작성해야 한다. 또한, 필터를 사용하려면 업데이트하여 재배치해야 한다.
독자가 OAuth 서비스 제공자가 되려고 하거나 현재 OAuth 서비스 제공자이고 IBM WebSphere Application Server를 사용하여 엔터프라이즈 애플리케이션을 배치한 경우에는 이 기사가 OAuth 서비스 제공자로서 OAuth 액세스 토큰을 처리하도록 사용자 정의 TAI를 설정하는 데 도움이 된다.
가정
이 기사에서는 독자가 WebSphere Application Server 보안과 WebSphere Application Server 관리 콘솔을 기본적으로 이해하고 있다고 가정한다. OAuth 프로토콜을 잘 알고 있으면 도움이 된다.
또한, 이 기사에서는 서비스 제공자 코드가 이미 제대로 작동하고 있으며 OAuth 토큰을 사용하여 WebSphere Application Server 보호 서비스를 인증하려고 한다고 가정한다. OAuth 서비스 제공자 코드의 세부사항은 이 기사에서는 다루지 않는다. OAuth 프로토콜과 TAI에 대한 세부사항은 참고자료를 참조한다.

사용자 정의 TAI(Trust Association Interceptor) 작성
사용자 정의 TAI를 작성하려면 com.ibm.wsspi.security.tai.TrustAssociationInterceptor를 구현하는 클래스를 새로 작성해야한다. 다른 프로젝트와 별도로, JAR 파일로 내보낼 수 있도록 이 클래스를 해당 Java™ 프로젝트에 삽입한다. 이 클래스가 TrustAssociationInterceptor를 구현하면 구현되지 않은 메소드를 추가할 수 있다(참고자료 참조).
이 기사에 있는 샘플 코드는 JAR 파일로 다운로드하여 나중에 참고하거나 자세하게 조사할 수 있다.
고객이 전송한 OAuth 토큰의 유효성을 검증하게 되므로 먼저, 예상되는 필수 OAuth 매개변수가 요청에 포함되어 있는지 확인해야 한다(목록 1). 예상되는 요청 매개변수가 존재하면 true를 리턴하는데, 이는 해당 요청이 OAuth 요청일 가능성이 있다는 점을 TAI에게 알려준다. 이 단계에서는 액세스 토큰의 유효성 검증을 완벽하게 수행하지 않아도 된다. 액세스 토큰의 재생성 및 유효성 검증은 또 다른 메소드가 처리한다(목록 2).

목록 1. isTargetInterceptor() 오버라이드
       
      
@Override
public boolean isTargetInterceptor(HttpServletRequest req)
  throws WebTrustAssociationException {
 
 boolean target = true;
 
 Map<String,String> hdrMap = new HashMap<String,String>();
 for (Enumeration<String> hdrs = req.getHeaderNames(); hdrs.hasMoreElements(); ){
  String hd = hdrs.nextElement();
  hdrMap.put(hd,req.getHeader( hd ));
 }
 target &= params.containsKey("oauth_token");
 target &= params.containsKey("oauth_consumer_key");
 target &= params.containsKey("oauth_signature");
 
 System.out.println("isTargetInterceptor: " + target);
 
 return target;
}

요청이 필수 OAuth 매개변수와 함께 WebSphere Application Server로 들어오면 negotiateValidateandEstablishTrust 메소드가 트리거된다. 이 시점에서 요청 매개변수를 이용하여 OAuth 액세스 토큰의 유효성을 검증할 논리를 배치해야 한다(목록 2 참조). OAuth 서비스 제공자 구현은 다른 사용자 정보를 토큰으로 인코딩하며, 인증이나 권한 부여 의사결정을 하기 위해 해당 코드에서 사용할 토큰에서 이 정보를 추출한다. OAuth 서비스 제공자 논리가, 생성된 accessToken이 유효하지 않다고 판별하면 이 메소드는 인증되지 않은 응답을 리턴한다. 그렇지 않고 OAuth 액세스 토큰이 유효한 경우에는 OAuth 액세스 토큰을 통해 판별된 대로 리턴된 TAIResult에 성공했다는 메시지가 표시된다.

목록 2. negotiateValidateandEstablishTrust() 오버라이드
       
      
@Override
public TAIResult negotiateValidateandEstablishTrust(
  HttpServletRequest req, HttpServletResponse res)
  throws WebTrustAssociationFailedException {

 Map<String,String> hdrMap = new HashMap<String,String>();
 for (Enumeration<String> hdrs = req.getHeaderNames(); hdrs.hasMoreElements(); ){
  String hd = hdrs.nextElement();
  hdrMap.put(hd,req.getHeader( hd ));
 }
 
 Object accessToken = null;
 //Below method is specific to our OAuth SP implementation.  Replace:
 //AccessToken accessToken = OAuthServiceProvider
 //  .GrantResourceAccess(params, request);
 if (accessToken == null) {
  System.out.println("OAuth --- Access token couldn't be created!");
  return TAIResult.create(HttpServletResponse.SC_UNAUTHORIZED);
 }
 
 //Strip out LTPA token from response here (see listing 3)

 String username = accessToken.getUser();
 return TAIResult.create(HttpServletResponse.SC_OK, username);
}


응답에서 LTPA 토큰 제거
이 기술이 SSO(Single-Sign On) 기능을 제공하기 때문에 많은 서비스 제공자 구현에서는 추가 보안에 대한 응답에서 LTPA 토큰을 제거하려고 한다(목록 3 참조). LTPA 토큰이 부여되면 LTPA를 사용하여 보호하는 사이트의 모든 영역을 누구나 LTPA 토큰을 사용하여 액세스할 수 있기 때문에 LTPA 토큰을 제거하지 않으면 코드가 취약해진다. 해당 응답에서 LTPA 토큰을 제거하면 계획대로 OAuth를 액세스할 수 있다.

목록 3. LTPA 토큰 제거(LTPA 버전 1 및 버전 2 쿠키 모두)
       
      
 Cookie[] cookies = request.getCookies();
 if(cookies != null){
  for (int i = 0; i < cookies.length; i++) {
   if (cookies[i].getName().startsWith("LtpaToken")) {
    cookies[i].setMaxAge(0);
    cookies[i].setPath("/");
    response.addCookie(cookies[i]);
   }
  }
 }


WebSphere Application Server로 TAI 구성
TAI가 작성되면 WebSphere Application Server를 사용하여 다음과 같은 단계를 통해 사용자 정의 TAI를 구성할 수 있다. (표시된 화면은 WebSphere Application Server V7.0에서 캡처한 것이지만, V8.0에서도 동일한 프로세스가 적용된다.
  1. TAI 프로젝트를 JAR 파일로 내보낸다.
  2. 이 파일을 {$installroot}/lib/ext 디렉토리에 배치한다. 예를 들면, /opt/IBM/WebSphere/AppServer/lib/ext이다({$installroot}/lib 디렉토리에서 이 파일이 사용 가능한지 확인한다.)
  3. 또한, 참조된 모든 JAR 파일을 동일한 디렉토리에 추가한다. OAuth 서비스 제공자 토큰 생성 논리가 공유 JAR 파일에 저장되어 있는 경우에는 이점이 중요하다.
  4. 관리 콘솔에 로그인한다. Security > Global Security로 이동하여 Web and SIP security를 펼친다. Trust association을 클릭한다(그림 1).

    그림 1. 관리 콘솔
    그림 1. 관리 콘솔
  5. Enable trust association을 선택한다.
  6. Additional Properties 아래에서 Interceptors를 클릭한 후, New 단추를 클릭한다.
  7. 사용자 정의 TAI의 Interceptor class name(패키지 정보 포함)을 입력한다(그림 2). 예를 들면, com.example.CustomTrustAssociationInterceptor이다.

    그림 2. 관리 콘솔의 새 TAI
    그림 2. 관리 콘솔의 새 TAI
  8. OK를 클릭한다.
  9. 마스터 구성의 변경사항을 저장한 후, 서버, 노드 및 dmgr을 다시 시작하여 변경한 사항을 적용한다.

OAuth 테스트
다시 시작이 완료되면 테스트를 수행하여 TAI가 적절하게 구성되었는지 확인할 수 있다. 사용자 정의 OAuth 프로젝트가 설정되면 OAuth를 테스트할 수 있도록 정상 서비스 제공자 URL과 사용자 정의 토큰을 제공한다. 원하면, Firefox와 같은 브라우저를 사용하여 TAI와 OAuth를 테스트할 수도 있다.
  1. Firefox 브라우저를 열고 Tools > RESTClient를 선택한다. (RESTClient가 없는 경우에는 참고자료를 확인하여 RESTClient Firefox 추가 기능을 다운로드한다.)
  2. Enter Login Information 패널(그림 3)에서 Login을 선택한 후, OAuth를 클릭한다.
  3. oAuth를 선택하고 적절한 인증 방법을 선택한다.
  4. 서비스 제공자와 연관된 신임정보와 메타데이터를 입력한 후, OK를 클릭한다.

    그림 3. Firefox RESTClient
    그림 3. Firefox RESTClient
  5. 서비스 제공자가 제공하는 보호 자원의 메소드 및 URL을 입력한 후, Send를 클릭한다. 제대로 된 경우에는 적절한 응답과 OK 상태를 받게 된다(그림 4).

    그림 4. Firefox RESTClient
    그림 4. Firefox RESTClient

다음 단계
이제 WebSphere Application Server TAI가 작동 중이므로 고객은 OAuth를 사용하여 OAuth 서비스 제공자에 성공적으로 연결할 수 있을 뿐만 아니라 보호 자원에도 안전하게 액세스할 수 있다. 서비스 제공자 구현을 면밀하게 조사하여 보호 자원 세트가 의도된 것인지 그리고 다른 보안 문제가 처리되었는지 확인한 다음, 토큰 부여 논리를 적절하게 조정한다. OAuth 프로토콜과 TAI를 자세히 배우려면 참고자료를 참조한다.

결론
이 정보는 OAuth 토큰을 WebSphere Application Server와 함께 사용하는 데 도움이 된다. TAI를 사용하는 것이 구현하기 가장 수월한 솔루션일 뿐만 아니라 프로젝트의 배치 요구에도 가장 논리적이다. 그러나 TAI를 사용할 때는 OAuth 요청으로 인해 고객이 WS-Security 및 LTPA 토큰과 같은 다른 보안 방식에 의해 능동적으로 보호되고 있는 모든 자원에 액세스할 수 있게 될 가능성이 있다는 점을 반드시 염두에 두어야 한다. OAuth 서비스 제공자 코드는 고객이 어떤 특정 자원에 액세스하려고 하는지 판별하여 URL을 기반으로 이 액세스를 제한하는 역할을 한다. 이 논리는 서비스 제공자의 OAuth 토큰 부여 구현과 함께 존재해야 한다. 앞에서 설명했듯이 LTPA 토큰을 제거하여 승인을 받은 요청에만 액세스할 수 있게 제한해야 한다.

댓글 없음:

댓글 쓰기