Security Context Token(SCT) Expired on WCF

Posted in .NET Framework // Posted at 2015. 3. 3. 18:15
728x90

초단위로 반복적으로 WCF를 호출하는 응용프로그램이 있다.

이 WCF 응용프로그램의 바인딩은 wsHttpBinding을 설정하였으며 X.509 인증서기반의 Message 보안모드 상태에서 동작한다. 더불어 클라이언트 인증은 UserName 자격증명을 이용중이다.

 

참고로, WCF는 자체적으로 보안강화를 위해 안전장치를 몇 가지 마련해 두고 있는데, 대표적으로 reply 공격을 방어하기 위해 클라이언트와 서버시간이 일정시간(기본 5분) 이상 차이가 나면 서비스 호출이 불가능하도록 하는 것을 예로 들 수 있다.

 

이런 안전장치들은 WCF 보안 기능을 사용할 경우, 기본적으로 제공되는 것들이다.

따라서 간혹 보안기능에 문제가 발생할때 이런 기본사항을 인지하지 않고 있다면 문제해결이 어려운 경우가 있다. 물론 이러한 기본 보안장치들은 특정 비즈니스 환경에 적합하지 않을 수도 있기에 개발자에 의해 커스터마이징이 가능하다.

 

앞서 초단위로 반복 호출되는 WCF 응용프로그램에서, 어느날 다음과 같은 오류가 발견되었다.

이 오류가 초단위로 지속적으로 나타나고 있었다. 메시지 인증을 지속적으로 시도하여 UserName 자격증명을 처리하는 서비스 오퍼레이션이 불필요하게 많이 호출되는 것이다.

 

메시지 인증을 실행하지 못했습니다.
 서비스: http://mydomain/Service.svc
 동작: http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT/Renew
 ClientIdentity:
 ActivityId: <null>
 SecurityContextTokenValidationException: context-id=urn:uuid:xxxxxxx-xxxx-xxxx-81bb-8218dddd5e8f(key generation-id=)을(를) 가진 SecurityContextSecurityToken이 등록되지 않았습니다. 

 

이 상황에서의, 클라이언트 측 HTTP 응답오류는 다음과 같다. 

HTTP/1.1 500 Internal Server Error
Content-Length: 663
Content-Type: application/soap+xml; charset=utf-8
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Tue, 03 Mar 2015 06:44:16 GMT

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing"><s:Header>
<a:Action s:mustUnderstand="1">http://www.w3.org/2005/08/addressing/soap/fault</a:Action>

<a:RelatesTo>urn:uuid:2def471f-b90d-498b-85b3-edfcaee8dff1</a:RelatesTo></s:Header>
<s:Body><s:Fault><s:Code><s:Value>s:Sender</s:Value><s:Subcode><s:Value xmlns:a="http://schemas.xmlsoap.org/ws/2005/02/sc">a:BadContextToken</s:Value></s:Subcode></s:Code>
<s:Reason><s:Text xml:lang="ko-KR">보안 컨텍스트 토큰이 만료되었거나 잘못되었습니다. 메시지가 처리되지 않았습니다.</s:Text></s:Reason></s:Fault></s:Body></s:Envelope> 

 

WCF Trace Log를 남겨서 조사도해보고, 몇 가지 예상되는 시나리오를 가정하고 테스트를 해 봐도 쉽게 잡히질 않았다. 더욱이 멀티 쓰레드 환경에서 백그라운드로 실행되어, 명시적인 서비스 오퍼레이션 호출에 기인한 메시지 인증의 자동요청이라 패킷검사에서도 서비스 오퍼레이션 이름이 아닌, 인증토큰과 관련된 협상과정만 반복되어 디버깅에 더 애를 먹게 되었다.

 

유독 특정 사용자에게서만 발생하던 오류라 그 사용자의 PC환경과 응용프로그램 사용패턴을 들여다보고, 자료를 좀 찾아보니 예상되는것이 나온다.

 

Idle Session 상태에서 보안토큰의 만료시간으로 인한 토큰 검증에 실패한 것으로 추측된다.

그 사용자는 응용프로그램을 실행한 뒤, 한참을 그냥 두고 PC가 유휴상태에 있다가 다시 활성상태로 돌아와서 다시 사용하는 등 Idle Session 상태를 빈번히 유발하는 것이다.

 

구글링에서 몇 가지 좋은 아이디어를 얻을 수 있었다.

이제 서비스 환경과 정책에 맞도록 idle Session에 대한 보안토큰 만료 완화 혹은 명시적 거부를 구현하기만 하면 될 듯 하다. 이런 오류는 사람을 매우 피곤하게 하지만, 해결이 되면 그마이 기쁜것이 없다.

----------------------------------------------------

http://www.codeproject.com/Articles/156994/WCF-Secure-Channel-cannot-be-opened-Load-Balancing

 

http://stackoverflow.com/questions/912580/invalid-or-expired-security-context-token-in-wcf-web-service

 

http://stackoverflow.com/questions/16575799/invalid-or-expired-security-context-token-when-running-after-a-debugging-resta

 

http://stackoverflow.com/questions/1683724/what-are-the-impacts-of-setting-establishsecuritycontext-false-if-i-use-https

 

https://msdn.microsoft.com/ko-kr/library/ms731814(v=vs.110).aspx

https://msdn.microsoft.com/en-us/library/ms731346(v=vs.110).aspx
https://msdn.microsoft.com/ko-kr/library/ms731346(v=vs.110).aspx


http://forums.asp.net/t/1760793.aspx?establishSecurityContext+false+


https://social.msdn.microsoft.com/Forums/en-US/3faee9bb-e843-42fc-a634-f6feb786c698/expired-security-token?forum=wcf

 

------------------------------------------------------------

 

해당 오류에 대한 클라이언트 측 Exception 은 최초 키 갱신에 대한 오류 이후, MessageSecurityException 즉, 일반적인 메시지보안 오류가 지속된다.

SessionKeyExpiredException 은 private로, 타입비교가 불가능해, 굳이 해당 예외에 맞춤형 처리를 하고자 한다면 문자열로 변환해서 비교하면 될 듯 하다. 

System.ServiceModel.Security.SessionKeyExpiredException: 보안 세션 키를 갱신할 수 없습니다.

Server stack trace:
   위치: System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result)
   위치: System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result)
   위치: System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
   위치: System.ServiceModel.Channels.ServiceChannelProxy.InvokeEndService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   위치: System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

 

 System.ServiceModel.Security.MessageSecurityException: 상대방으로부터 보호되지 않거나 잘못 보호된 오류를 받았습니다. 오류 코드 및 세부 정보는 내부 FaultException을 참조하십시오. ---> System.ServiceModel.FaultException: 보안 컨텍스트 토큰이 만료되었거나 잘못되었습니다. 메시지가 처리되지 않

았습니다.
   --- 내부 예외 스택 추적의 끝 ---

Server stack trace:
   위치: System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result)
   위치: System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result)
   위치: System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
   위치: System.ServiceModel.Channels.ServiceChannelProxy.InvokeEndService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   위치: System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

InnerException Info>>
System.ServiceModel.FaultException: 보안 컨텍스트 토큰이 만료되었거나 잘못되었습니다. 메시지가 처리되지 않았습니다.

 

'.NET Framework' 카테고리의 다른 글

미스터 빈, 너로구나  (0) 2014.07.31
Caching in WCF  (2) 2014.02.21
ASP.NET SignalR  (0) 2013.12.06
maxConcurrentSessions in WCF  (0) 2013.11.21
SQL Double Split  (0) 2013.11.13