| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- //------------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------------------------
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.IdentityModel;
- using System.IdentityModel.Selectors;
- using System.IdentityModel.Tokens;
- using System.ServiceModel.Security.Tokens;
- using SystemUniqueId = System.Xml.UniqueId;
- using SR = System.ServiceModel.SR;
- namespace System.ServiceModel.Security
- {
- /// <summary>
- /// The purpose of this class is to provide an ISecurityContextSecurityTokenCache contract over a SecurityTokenCache.
- /// This allows for a consistent interface for the SecurityContextSecurityTokenHandler and a SessionSecurityTokenHandler.
- /// The SecurityTokenCache can be passed to the SecurityContextSecurityTokenHandler and wrapped to expose an ISecurityContextSecurityTokenCache
- /// that can be set to the be the token cache for WCF context tokens
- /// </summary>
- class WrappedTokenCache : SecurityTokenResolver, ISecurityContextSecurityTokenCache
- {
- SessionSecurityTokenCache _tokenCache;
- SctClaimsHandler _claimsHandler;
- public WrappedTokenCache(SessionSecurityTokenCache tokenCache, SctClaimsHandler sctClaimsHandler)
- {
- if (tokenCache == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("tokenCache");
- }
- if (sctClaimsHandler == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("sctClaimsHandler");
- }
- _tokenCache = tokenCache;
- _claimsHandler = sctClaimsHandler;
- }
- #region ISecurityContextSecurityTokenCache Members
- public void AddContext(SecurityContextSecurityToken token)
- {
- //
- // WCF will cache the token first before calling the WrappedSessionSecurityTokenHandler.OnTokenIssued.
- // We need to map the claims here so we will be caching the correct token with Geneva Claims substitued
- // in place of the WCF claims.
- //
- _claimsHandler.SetPrincipalBootstrapTokensAndBindIdfxAuthPolicy(token);
- SessionSecurityTokenCacheKey key = new SessionSecurityTokenCacheKey(_claimsHandler.EndpointId, token.ContextId, token.KeyGeneration);
- SessionSecurityToken sessionToken = SecurityContextSecurityTokenHelper.ConvertSctToSessionToken(token, SecureConversationVersion.Default);
- DateTime expiryTime = DateTimeUtil.Add(sessionToken.ValidTo, _claimsHandler.SecurityTokenHandlerCollection.Configuration.MaxClockSkew);
- _tokenCache.AddOrUpdate(key, sessionToken, expiryTime);
- }
- public void ClearContexts()
- {
- _tokenCache.RemoveAll(_claimsHandler.EndpointId);
- }
- /// <summary>
- /// Called to retrieve all tokens that match a particular contextId. WCF will call this
- /// </summary>
- /// <param name="contextId"></param>
- /// <returns></returns>
- public Collection<SecurityContextSecurityToken> GetAllContexts(System.Xml.UniqueId contextId)
- {
- Collection<SecurityContextSecurityToken> tokens = new Collection<SecurityContextSecurityToken>();
- IEnumerable<SessionSecurityToken> cachedTokens = _tokenCache.GetAll(_claimsHandler.EndpointId, contextId);
- if (cachedTokens != null)
- {
- foreach (SessionSecurityToken sessionSct in cachedTokens)
- {
- if (sessionSct != null && sessionSct.IsSecurityContextSecurityTokenWrapper)
- {
- SecurityContextSecurityToken sctToken = SecurityContextSecurityTokenHelper.ConvertSessionTokenToSecurityContextSecurityToken(sessionSct);
- tokens.Add(sctToken);
- }
- }
- }
- return tokens;
- }
- public SecurityContextSecurityToken GetContext(System.Xml.UniqueId contextId, System.Xml.UniqueId generation)
- {
- SessionSecurityToken token = null;
- SessionSecurityTokenCacheKey key = new SessionSecurityTokenCacheKey(_claimsHandler.EndpointId, contextId, generation);
- token = _tokenCache.Get(key);
- SecurityContextSecurityToken sctToken = null;
- if (token != null && token.IsSecurityContextSecurityTokenWrapper)
- {
- sctToken = SecurityContextSecurityTokenHelper.ConvertSessionTokenToSecurityContextSecurityToken(token);
- }
- return sctToken;
- }
- /// <summary>
- /// Removes all the tokens that match the contextId.
- /// </summary>
- /// <param name="contextId">The context id.</param>
- /// <remarks>
- /// When WCF renews a token, its context id is the same as the issuedToken. The only
- /// difference is in the generationId. When WCF closes the session channel, all the tokens that
- /// were issued need to be removed that match the contextId.
- /// </remarks>
- public void RemoveAllContexts(System.Xml.UniqueId contextId)
- {
- _tokenCache.RemoveAll(_claimsHandler.EndpointId, contextId);
- }
- public void RemoveContext(System.Xml.UniqueId contextId, System.Xml.UniqueId generation)
- {
- SessionSecurityTokenCacheKey key = new SessionSecurityTokenCacheKey(_claimsHandler.EndpointId, contextId, generation);
- _tokenCache.Remove(key);
- }
- public bool TryAddContext(SecurityContextSecurityToken token)
- {
- //
- // WCF will cache the token first before calling the WrappedSessionSecurityTokenHandler.OnTokenIssued.
- // We need to map the claims here so we will be caching the correct token with Geneva Claims substitued
- // in place of the WCF claims.
- //
- _claimsHandler.SetPrincipalBootstrapTokensAndBindIdfxAuthPolicy(token);
- SessionSecurityTokenCacheKey key = new SessionSecurityTokenCacheKey(_claimsHandler.EndpointId, token.ContextId, token.KeyGeneration);
- SessionSecurityToken sessionToken = SecurityContextSecurityTokenHelper.ConvertSctToSessionToken(token, SecureConversationVersion.Default);
- DateTime expiryTime = DateTimeUtil.Add(token.ValidTo, _claimsHandler.SecurityTokenHandlerCollection.Configuration.MaxClockSkew);
- _tokenCache.AddOrUpdate(key, sessionToken, expiryTime);
- return true;
- }
- public void UpdateContextCachingTime(SecurityContextSecurityToken token, DateTime expirationTime)
- {
- if (token.ValidTo <= expirationTime.ToUniversalTime())
- {
- return;
- }
- SessionSecurityTokenCacheKey key = new SessionSecurityTokenCacheKey(_claimsHandler.EndpointId, token.ContextId, token.KeyGeneration);
- SessionSecurityToken sessionToken = SecurityContextSecurityTokenHelper.ConvertSctToSessionToken(token, SecureConversationVersion.Default);
- DateTime expiryTime = DateTimeUtil.Add(sessionToken.ValidTo, _claimsHandler.SecurityTokenHandlerCollection.Configuration.MaxClockSkew);
- if (_tokenCache.Get(key) == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4285, sessionToken.ContextId.ToString()));
- }
- _tokenCache.AddOrUpdate(key, sessionToken, expiryTime);
- }
- #endregion
- // these are not needed as this will never be used as an SecurityTokenResolver.
- protected override bool TryResolveSecurityKeyCore(SecurityKeyIdentifierClause keyIdentifierClause, out SecurityKey key)
- {
- SecurityToken sct;
- if (TryResolveTokenCore(keyIdentifierClause, out sct))
- {
- key = ((SecurityContextSecurityToken)sct).SecurityKeys[0];
- return true;
- }
- else
- {
- key = null;
- return false;
- }
- }
- protected override bool TryResolveTokenCore(SecurityKeyIdentifierClause keyIdentifierClause, out SecurityToken token)
- {
- SecurityContextKeyIdentifierClause sctSkiClause = keyIdentifierClause as SecurityContextKeyIdentifierClause;
- if (sctSkiClause != null)
- {
- token = GetContext(sctSkiClause.ContextId, sctSkiClause.Generation) as SecurityToken;
- }
- else
- {
- token = null;
- }
- return (token != null);
- }
- protected override bool TryResolveTokenCore(SecurityKeyIdentifier keyIdentifier, out SecurityToken token)
- {
- SecurityContextKeyIdentifierClause sctSkiClause;
- if (keyIdentifier.TryFind<SecurityContextKeyIdentifierClause>(out sctSkiClause))
- {
- return TryResolveTokenCore(sctSkiClause, out token);
- }
- else
- {
- token = null;
- return false;
- }
- }
- }
- }
|