File: FrameworkFork\System.ServiceModel\System\ServiceModel\Security\Tokens\SecurityContextSecurityToken.cs
Web Access
Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IdentityModel.Policy;
using System.IdentityModel.Tokens;
using Microsoft.Xml;
 
namespace System.ServiceModel.Security.Tokens
{
    public class SecurityContextSecurityToken : SecurityToken, TimeBoundedCache.IExpirableItem, IDisposable
    {
        private byte[] _cookieBlob;
        private UniqueId _contextId = null;
        private UniqueId _keyGeneration = null;
        private DateTime _keyEffectiveTime;
        private DateTime _keyExpirationTime;
        private DateTime _tokenEffectiveTime;
        private DateTime _tokenExpirationTime;
        private bool _isCookieMode = false;
        private byte[] _key;
        private string _keyString;
        private ReadOnlyCollection<IAuthorizationPolicy> _authorizationPolicies;
        private ReadOnlyCollection<SecurityKey> _securityKeys;
        private string _id;
        private SecurityMessageProperty _bootstrapMessageProperty;
        private bool _disposed = false;
 
        public SecurityContextSecurityToken(UniqueId contextId, byte[] key, DateTime validFrom, DateTime validTo)
            : this(contextId, SecurityUtils.GenerateId(), key, validFrom, validTo)
        { }
 
        public SecurityContextSecurityToken(UniqueId contextId, string id, byte[] key, DateTime validFrom, DateTime validTo)
            : this(contextId, id, key, validFrom, validTo, null)
        { }
 
        public SecurityContextSecurityToken(UniqueId contextId, string id, byte[] key, DateTime validFrom, DateTime validTo, ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies)
            : base()
        {
            _id = id;
            this.Initialize(contextId, key, validFrom, validTo, authorizationPolicies, false, null, validFrom, validTo);
        }
 
        public SecurityContextSecurityToken(UniqueId contextId, string id, byte[] key, DateTime validFrom, DateTime validTo, UniqueId keyGeneration, DateTime keyEffectiveTime, DateTime keyExpirationTime, ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies)
            : base()
        {
            _id = id;
            this.Initialize(contextId, key, validFrom, validTo, authorizationPolicies, false, keyGeneration, keyEffectiveTime, keyExpirationTime);
        }
 
        internal SecurityContextSecurityToken(SecurityContextSecurityToken sourceToken, string id)
            : this(sourceToken, id, sourceToken._key, sourceToken._keyGeneration, sourceToken._keyEffectiveTime, sourceToken._keyExpirationTime, sourceToken.AuthorizationPolicies)
        {
        }
 
        internal SecurityContextSecurityToken(SecurityContextSecurityToken sourceToken, string id, byte[] key, UniqueId keyGeneration, DateTime keyEffectiveTime, DateTime keyExpirationTime, ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies)
            : base()
        {
            _id = id;
            this.Initialize(sourceToken._contextId, key, sourceToken.ValidFrom, sourceToken.ValidTo, authorizationPolicies, sourceToken._isCookieMode, keyGeneration, keyEffectiveTime, keyExpirationTime);
            _cookieBlob = sourceToken._cookieBlob;
            _bootstrapMessageProperty = (sourceToken._bootstrapMessageProperty == null) ? null : (SecurityMessageProperty)sourceToken.BootstrapMessageProperty.CreateCopy();
        }
 
        internal SecurityContextSecurityToken(UniqueId contextId, string id, byte[] key, DateTime validFrom, DateTime validTo, ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies, bool isCookieMode, byte[] cookieBlob)
            : this(contextId, id, key, validFrom, validTo, authorizationPolicies, isCookieMode, cookieBlob, null, validFrom, validTo)
        {
        }
 
        internal SecurityContextSecurityToken(UniqueId contextId, string id, byte[] key, DateTime validFrom, DateTime validTo, ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies, bool isCookieMode, byte[] cookieBlob,
            UniqueId keyGeneration, DateTime keyEffectiveTime, DateTime keyExpirationTime)
            : base()
        {
            _id = id;
            this.Initialize(contextId, key, validFrom, validTo, authorizationPolicies, isCookieMode, keyGeneration, keyEffectiveTime, keyExpirationTime);
            _cookieBlob = cookieBlob;
        }
 
        private SecurityContextSecurityToken(SecurityContextSecurityToken from)
        {
            ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies = System.IdentityModel.SecurityUtils.CloneAuthorizationPoliciesIfNecessary(from._authorizationPolicies);
            _id = from._id;
            this.Initialize(from._contextId, from._key, from._tokenEffectiveTime, from._tokenExpirationTime, authorizationPolicies, from._isCookieMode, from._keyGeneration, from._keyEffectiveTime, from._keyExpirationTime);
            _cookieBlob = from._cookieBlob;
            _bootstrapMessageProperty = (from._bootstrapMessageProperty == null) ? null : (SecurityMessageProperty)from.BootstrapMessageProperty.CreateCopy();
        }
 
        /// <summary>
        /// Gets or Sets the SecurityMessageProperty extracted from 
        /// the Bootstrap message. This will contain the original tokens
        /// that the client used to Authenticate with the service. By 
        /// default, this is turned off. To turn this feature on, add a custom 
        /// ServiceCredentialsSecurityTokenManager and override  
        /// CreateSecurityTokenManager. Create the SecurityContextToken Authenticator by calling 
        /// ServiceCredentialsSecurityTokenManager.CreateSecureConversationTokenAuthenticator
        /// with 'preserveBootstrapTokens' parameter to true. 
        /// If there are any UserNameSecurityToken in the bootstrap message, the password in
        /// these tokens will be removed. When 'Cookie' mode SCT is enabled the BootstrapMessageProperty
        /// is not preserved in the Cookie. To preserve the bootstrap tokens in the CookieMode case
        /// write a custom Serializer and serialize the property as part of the cookie.
        /// </summary>
        public SecurityMessageProperty BootstrapMessageProperty
        {
            get
            {
                return _bootstrapMessageProperty;
            }
            set
            {
                _bootstrapMessageProperty = value;
            }
        }
 
        public override string Id
        {
            get { return _id; }
        }
 
        public UniqueId ContextId
        {
            get
            {
                return _contextId;
            }
        }
 
        public UniqueId KeyGeneration
        {
            get
            {
                return _keyGeneration;
            }
        }
 
        public DateTime KeyEffectiveTime
        {
            get
            {
                return _keyEffectiveTime;
            }
        }
 
        public DateTime KeyExpirationTime
        {
            get
            {
                return _keyExpirationTime;
            }
        }
 
        public ReadOnlyCollection<IAuthorizationPolicy> AuthorizationPolicies
        {
            get
            {
                ThrowIfDisposed();
                return _authorizationPolicies;
            }
 
            internal set
            {
                _authorizationPolicies = value;
            }
        }
 
        public override ReadOnlyCollection<SecurityKey> SecurityKeys
        {
            get
            {
                return _securityKeys;
            }
        }
 
        public override DateTime ValidFrom
        {
            get { return _tokenEffectiveTime; }
        }
 
        public override DateTime ValidTo
        {
            get { return _tokenExpirationTime; }
        }
 
        internal byte[] CookieBlob
        {
            get
            {
                return _cookieBlob;
            }
        }
 
        /// <summary>
        /// This is set by the issuer when creating the SCT to be sent in the RSTR
        /// The SecurityContextTokenManager examines this property to determine how to write
        /// out the SCT
        /// This field is set to true when the issuer reads in a cookie mode SCT
        /// </summary>
        public bool IsCookieMode
        {
            get
            {
                return _isCookieMode;
            }
        }
 
        DateTime TimeBoundedCache.IExpirableItem.ExpirationTime
        {
            get
            {
                return this.ValidTo;
            }
        }
 
        internal string GetBase64KeyString()
        {
            if (_keyString == null)
            {
                _keyString = Convert.ToBase64String(_key);
            }
            return _keyString;
        }
 
        internal byte[] GetKeyBytes()
        {
            byte[] retval = new byte[_key.Length];
            Buffer.BlockCopy(_key, 0, retval, 0, _key.Length);
            return retval;
        }
 
        public override string ToString()
        {
            return String.Format(CultureInfo.CurrentCulture, "SecurityContextSecurityToken(Identifier='{0}', KeyGeneration='{1}')", _contextId, _keyGeneration);
        }
 
        private void Initialize(UniqueId contextId, byte[] key, DateTime validFrom, DateTime validTo, ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies, bool isCookieMode,
            UniqueId keyGeneration, DateTime keyEffectiveTime, DateTime keyExpirationTime)
        {
            if (contextId == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contextId");
            }
 
            if (key == null || key.Length == 0)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("key");
            }
 
            DateTime tokenEffectiveTimeUtc = validFrom.ToUniversalTime();
            DateTime tokenExpirationTimeUtc = validTo.ToUniversalTime();
            if (tokenEffectiveTimeUtc > tokenExpirationTimeUtc)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("validFrom", SRServiceModel.EffectiveGreaterThanExpiration);
            }
            _tokenEffectiveTime = tokenEffectiveTimeUtc;
            _tokenExpirationTime = tokenExpirationTimeUtc;
 
            _keyEffectiveTime = keyEffectiveTime.ToUniversalTime();
            _keyExpirationTime = keyExpirationTime.ToUniversalTime();
            if (_keyEffectiveTime > _keyExpirationTime)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("keyEffectiveTime", SRServiceModel.EffectiveGreaterThanExpiration);
            }
            if ((_keyEffectiveTime < tokenEffectiveTimeUtc) || (_keyExpirationTime > tokenExpirationTimeUtc))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SRServiceModel.KeyLifetimeNotWithinTokenLifetime);
            }
 
            _key = new byte[key.Length];
            Buffer.BlockCopy(key, 0, _key, 0, key.Length);
            _contextId = contextId;
            _keyGeneration = keyGeneration;
            _authorizationPolicies = authorizationPolicies ?? EmptyReadOnlyCollection<IAuthorizationPolicy>.Instance;
            List<SecurityKey> temp = new List<SecurityKey>(1);
            temp.Add(new InMemorySymmetricSecurityKey(_key, false));
            _securityKeys = new ReadOnlyCollection<SecurityKey>(temp);
            _isCookieMode = isCookieMode;
        }
 
        public static SecurityContextSecurityToken CreateCookieSecurityContextToken(UniqueId contextId, string id, byte[] key,
            DateTime validFrom, DateTime validTo, ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies, SecurityStateEncoder securityStateEncoder)
        {
            return CreateCookieSecurityContextToken(contextId, id, key, validFrom, validTo, null, validFrom, validTo, authorizationPolicies, securityStateEncoder);
        }
 
 
        public static SecurityContextSecurityToken CreateCookieSecurityContextToken(UniqueId contextId, string id, byte[] key,
            DateTime validFrom, DateTime validTo, UniqueId keyGeneration, DateTime keyEffectiveTime,
            DateTime keyExpirationTime, ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies, SecurityStateEncoder securityStateEncoder)
        {
            SecurityContextCookieSerializer cookieSerializer = new SecurityContextCookieSerializer(securityStateEncoder, null);
            byte[] cookieBlob = cookieSerializer.CreateCookieFromSecurityContext(contextId, id, key, validFrom, validTo, keyGeneration,
                                keyEffectiveTime, keyExpirationTime, authorizationPolicies);
 
            return new SecurityContextSecurityToken(contextId, id, key, validFrom, validTo,
                authorizationPolicies, true, cookieBlob, keyGeneration, keyEffectiveTime, keyExpirationTime);
        }
 
        internal SecurityContextSecurityToken Clone()
        {
            ThrowIfDisposed();
            return new SecurityContextSecurityToken(this);
        }
 
        public void Dispose()
        {
            if (!_disposed)
            {
                _disposed = true;
                System.IdentityModel.SecurityUtils.DisposeAuthorizationPoliciesIfNecessary(_authorizationPolicies);
                if (_bootstrapMessageProperty != null)
                {
                    _bootstrapMessageProperty.Dispose();
                }
            }
        }
 
        private void ThrowIfDisposed()
        {
            if (_disposed)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ObjectDisposedException(this.GetType().FullName));
            }
        }
    }
}