WrappedSessionSecurityTokenAuthenticator.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Collections.ObjectModel;
  7. using System.Globalization;
  8. using System.IdentityModel.Policy;
  9. using System.IdentityModel.Selectors;
  10. using System.IdentityModel.Tokens;
  11. using System.Reflection;
  12. using System.ServiceModel;
  13. using System.ServiceModel.Security.Tokens;
  14. using SysClaim = System.IdentityModel.Claims.Claim;
  15. using SystemAuthorizationContext = System.IdentityModel.Policy.AuthorizationContext;
  16. using System.Security.Claims;
  17. namespace System.ServiceModel.Security
  18. {
  19. /// <summary>
  20. /// Wraps a SessionSecurityTokenHandler. Delegates the token authentication call to
  21. /// this wrapped tokenAuthenticator. Wraps the returned ClaimsIdentities into
  22. /// an IAuthorizationPolicy. This class is wired into WCF and actually receives
  23. /// SecurityContextSecurityTokens which are then wrapped into SessionSecurityTokens for
  24. /// validation.
  25. /// </summary>
  26. internal class WrappedSessionSecurityTokenAuthenticator : SecurityTokenAuthenticator, IIssuanceSecurityTokenAuthenticator, ICommunicationObject
  27. {
  28. SessionSecurityTokenHandler _sessionTokenHandler;
  29. IIssuanceSecurityTokenAuthenticator _issuanceSecurityTokenAuthenticator;
  30. ICommunicationObject _communicationObject;
  31. SctClaimsHandler _sctClaimsHandler;
  32. ExceptionMapper _exceptionMapper;
  33. /// <summary>
  34. /// Initializes an instance of <see cref="WrappedRsaSecurityTokenAuthenticator"/>
  35. /// </summary>
  36. /// <param name="sessionTokenHandler">The sessionTokenHandler to wrap</param>
  37. /// <param name="wcfSessionAuthenticator">The wcf SessionTokenAuthenticator.</param>
  38. /// <param name="sctClaimsHandler">Handler that converts WCF generated IAuthorizationPolicy to <see cref="AuthorizationPolicy"/></param>
  39. /// <param name="exceptionMapper">Converts token validation exception to SOAP faults.</param>
  40. public WrappedSessionSecurityTokenAuthenticator( SessionSecurityTokenHandler sessionTokenHandler,
  41. SecurityTokenAuthenticator wcfSessionAuthenticator,
  42. SctClaimsHandler sctClaimsHandler,
  43. ExceptionMapper exceptionMapper )
  44. : base()
  45. {
  46. if ( sessionTokenHandler == null )
  47. {
  48. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "sessionTokenHandler" );
  49. }
  50. if ( wcfSessionAuthenticator == null )
  51. {
  52. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "wcfSessionAuthenticator" );
  53. }
  54. if ( sctClaimsHandler == null )
  55. {
  56. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "sctClaimsHandler" );
  57. }
  58. if ( exceptionMapper == null )
  59. {
  60. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "exceptionMapper" );
  61. }
  62. _issuanceSecurityTokenAuthenticator = wcfSessionAuthenticator as IIssuanceSecurityTokenAuthenticator;
  63. if ( _issuanceSecurityTokenAuthenticator == null )
  64. {
  65. throw DiagnosticUtility.ExceptionUtility.ThrowHelperInvalidOperation( SR.GetString( SR.ID4244 ) );
  66. }
  67. _communicationObject = wcfSessionAuthenticator as ICommunicationObject;
  68. if ( _communicationObject == null )
  69. {
  70. throw DiagnosticUtility.ExceptionUtility.ThrowHelperInvalidOperation( SR.GetString( SR.ID4245 ) );
  71. }
  72. _sessionTokenHandler = sessionTokenHandler;
  73. _sctClaimsHandler = sctClaimsHandler;
  74. _exceptionMapper = exceptionMapper;
  75. }
  76. /// <summary>
  77. /// Validates the token using the wrapped token handler and generates IAuthorizationPolicy
  78. /// wrapping the returned ClaimsIdentities.
  79. /// </summary>
  80. /// <param name="token">Token to be validated. This is always a SecurityContextSecurityToken.</param>
  81. /// <returns>Read-only collection of IAuthorizationPolicy</returns>
  82. protected override ReadOnlyCollection<IAuthorizationPolicy> ValidateTokenCore( SecurityToken token )
  83. {
  84. SecurityContextSecurityToken sct = token as SecurityContextSecurityToken;
  85. SessionSecurityToken sessionToken = SecurityContextSecurityTokenHelper.ConvertSctToSessionToken( sct );
  86. IEnumerable<ClaimsIdentity> identities = null;
  87. try
  88. {
  89. identities = _sessionTokenHandler.ValidateToken(sessionToken, _sctClaimsHandler.EndpointId);
  90. }
  91. catch (Exception ex)
  92. {
  93. if (!_exceptionMapper.HandleSecurityTokenProcessingException(ex))
  94. {
  95. throw;
  96. }
  97. }
  98. return new List<IAuthorizationPolicy>(new AuthorizationPolicy[] { new AuthorizationPolicy(identities) }).AsReadOnly();
  99. }
  100. protected override bool CanValidateTokenCore( SecurityToken token )
  101. {
  102. return ( token is SecurityContextSecurityToken );
  103. }
  104. #region IIssuanceSecurityTokenAuthenticator Members
  105. public IssuedSecurityTokenHandler IssuedSecurityTokenHandler
  106. {
  107. get
  108. {
  109. return _issuanceSecurityTokenAuthenticator.IssuedSecurityTokenHandler;
  110. }
  111. set
  112. {
  113. _issuanceSecurityTokenAuthenticator.IssuedSecurityTokenHandler = value;
  114. }
  115. }
  116. public RenewedSecurityTokenHandler RenewedSecurityTokenHandler
  117. {
  118. get
  119. {
  120. return _issuanceSecurityTokenAuthenticator.RenewedSecurityTokenHandler;
  121. }
  122. set
  123. {
  124. _issuanceSecurityTokenAuthenticator.RenewedSecurityTokenHandler = value;
  125. }
  126. }
  127. #endregion
  128. #region ICommunicationObject Members
  129. // all these methods are passthroughs
  130. public void Abort()
  131. {
  132. _communicationObject.Abort();
  133. }
  134. public System.IAsyncResult BeginClose( System.TimeSpan timeout, System.AsyncCallback callback, object state )
  135. {
  136. return _communicationObject.BeginClose( timeout, callback, state );
  137. }
  138. public System.IAsyncResult BeginClose( System.AsyncCallback callback, object state )
  139. {
  140. return _communicationObject.BeginClose( callback, state );
  141. }
  142. public System.IAsyncResult BeginOpen( System.TimeSpan timeout, System.AsyncCallback callback, object state )
  143. {
  144. return _communicationObject.BeginOpen( timeout, callback, state );
  145. }
  146. public System.IAsyncResult BeginOpen( System.AsyncCallback callback, object state )
  147. {
  148. return _communicationObject.BeginOpen( callback, state );
  149. }
  150. public void Close( System.TimeSpan timeout )
  151. {
  152. _communicationObject.Close( timeout );
  153. }
  154. public void Close()
  155. {
  156. _communicationObject.Close();
  157. }
  158. public event System.EventHandler Closed
  159. {
  160. add { _communicationObject.Closed += value; }
  161. remove { _communicationObject.Closed -= value; }
  162. }
  163. public event System.EventHandler Closing
  164. {
  165. add { _communicationObject.Closing += value; }
  166. remove { _communicationObject.Closing -= value; }
  167. }
  168. public void EndClose( System.IAsyncResult result )
  169. {
  170. _communicationObject.EndClose( result );
  171. }
  172. public void EndOpen( System.IAsyncResult result )
  173. {
  174. _communicationObject.EndOpen( result );
  175. }
  176. public event System.EventHandler Faulted
  177. {
  178. add { _communicationObject.Faulted += value; }
  179. remove { _communicationObject.Faulted -= value; }
  180. }
  181. public void Open( System.TimeSpan timeout )
  182. {
  183. _communicationObject.Open( timeout );
  184. }
  185. public void Open()
  186. {
  187. _communicationObject.Open();
  188. }
  189. public event System.EventHandler Opened
  190. {
  191. add { _communicationObject.Opened += value; }
  192. remove { _communicationObject.Opened -= value; }
  193. }
  194. public event System.EventHandler Opening
  195. {
  196. add { _communicationObject.Opening += value; }
  197. remove { _communicationObject.Opening -= value; }
  198. }
  199. public CommunicationState State
  200. {
  201. get { return _communicationObject.State; }
  202. }
  203. #endregion
  204. }
  205. /// <summary>
  206. /// Defines a SecurityStateEncoder whose Encode and Decode operations are
  207. /// a no-op. This class is used to null WCF SecurityContextToken creation
  208. /// code to skip any encryption and decryption cost. When SessionSecurityTokenHandler
  209. /// is being used we will use our own EncryptionTransform and ignore the WCF
  210. /// generated cookie.
  211. /// </summary>
  212. internal class NoOpSecurityStateEncoder : SecurityStateEncoder
  213. {
  214. protected internal override byte[] EncodeSecurityState( byte[] data )
  215. {
  216. return data;
  217. }
  218. protected internal override byte[] DecodeSecurityState( byte[] data )
  219. {
  220. return data;
  221. }
  222. }
  223. }