File: SctClaimsHandler.cs

package info (click to toggle)
mono 4.6.2.7%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 778,148 kB
  • ctags: 914,052
  • sloc: cs: 5,779,509; xml: 2,773,713; ansic: 432,645; sh: 14,749; makefile: 12,361; perl: 2,488; python: 1,434; cpp: 849; asm: 531; sql: 95; sed: 16; php: 1
file content (174 lines) | stat: -rw-r--r-- 7,781 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IdentityModel.Policy;
using System.IdentityModel.Tokens;
using System.ServiceModel.Security.Tokens;

using SysClaim = System.IdentityModel.Claims.Claim;
using SystemAuthorizationContext = System.IdentityModel.Policy.AuthorizationContext;

namespace System.ServiceModel.Security
{
    internal class SctClaimsHandler
    {
        SecurityTokenHandlerCollection _securityTokenHandlerCollection;
        string _endpointId;

        /// <summary>
        /// Creates an instance of <see cref="SctClaimsHandler"/>
        /// </summary>
        public SctClaimsHandler(
            SecurityTokenHandlerCollection securityTokenHandlerCollection,
            string endpointId)
        {
            if ( securityTokenHandlerCollection == null )
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "securityTokenHandlerCollection" );
            }

            if ( endpointId == null )
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNullOrEmptyString( "endpointId" );
            }

            _securityTokenHandlerCollection = securityTokenHandlerCollection;
            _endpointId = endpointId;
        }

        /// <summary>
        /// Gets the Endpoint Id to which all <see cref="SecurityContextSecurityToken"/> should be scoped.
        /// </summary>
        public string EndpointId
        {
            get { return _endpointId; }
        }

        /// <summary>
        /// Gets the <see cref="SecurityTokenHandlerCollection" /> used to validate the SCT.
        /// </summary>
        public SecurityTokenHandlerCollection SecurityTokenHandlerCollection
        {
            get { return _securityTokenHandlerCollection; }
        }

        /// <summary>
        /// The the purposes of this method are:
        /// 1. To enable layers above to get to the bootstrap tokens
        /// 2. To ensure an ClaimsPrincipal is inside the SCT authorization policies.  This is needed so that
        ///    a CustomPrincipal will be created and can be set.  This is required as we set the principal permission mode to custom 
        /// 3. To set the IAuthorizationPolicy collection on the SCT to be one of IDFx's Authpolicy.        
        /// This allows SCT cookie and SCT cached to be treated the same, futher up the stack.  
        /// 
        /// This method is call AFTER the final SCT has been created and the bootstrap tokens are around.  Itis not called during the SP/TLS nego bootstrap.
        /// </summary>
        /// <param name="sct"></param>
        internal void SetPrincipalBootstrapTokensAndBindIdfxAuthPolicy( SecurityContextSecurityToken sct )
        {
            if ( sct == null )
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "sct" );
            }

            List<IAuthorizationPolicy> iaps = new List<IAuthorizationPolicy>();

            //
            // The SecurityContextToken is cached first before the OnTokenIssued is called. So in the Session SCT
            // case the AuthorizationPolicies will have already been updated. So check the sct.AuthorizationPolicies
            // policy to see if the first is a AuthorizationPolicy. 
            //
            if ( ( sct.AuthorizationPolicies != null ) &&
                ( sct.AuthorizationPolicies.Count > 0 ) &&
                ( ContainsEndpointAuthPolicy(sct.AuthorizationPolicies) ) )
            {
                // We have already seen this sct and have fixed up the AuthorizationPolicy
                // collection. Just return.
                return;
            }

            //
            // Nego SCT just has a cookie, there are no IAuthorizationPolicy. In this case,
            // we want to add the EndpointAuthorizationPolicy alone to the SCT.
            //
            if ( ( sct.AuthorizationPolicies != null ) &&
                ( sct.AuthorizationPolicies.Count > 0 ) )
            {
                //
                // Create a principal with known policies.
                //
                AuthorizationPolicy sctAp = IdentityModelServiceAuthorizationManager.TransformAuthorizationPolicies( sct.AuthorizationPolicies,
                                                                                                                     _securityTokenHandlerCollection,
                                                                                                                     false );
                // Replace the WCF authorization policies with our IDFx policies.  
                // The principal is needed later on to set the custom principal by WCF runtime.
                iaps.Add( sctAp );

                //
                // Convert the claim from WCF unconditional policy to an SctAuthorizationPolicy. The SctAuthorizationPolicy simply
                // captures the primary identity claim from the WCF unconditional policy which IdFX will eventually throw away. 
                // If we don't capture that claim, then in a token renewal scenario WCF will fail due to identities being different 
                // for the issuedToken and the renewedToken.
                //
                SysClaim claim = GetPrimaryIdentityClaim( SystemAuthorizationContext.CreateDefaultAuthorizationContext( sct.AuthorizationPolicies ) );

                SctAuthorizationPolicy sctAuthPolicy = new SctAuthorizationPolicy( claim );
                iaps.Add( sctAuthPolicy );
            }

            iaps.Add( new EndpointAuthorizationPolicy( _endpointId ) );
            sct.AuthorizationPolicies = iaps.AsReadOnly();
        }

        bool ContainsEndpointAuthPolicy( ReadOnlyCollection<IAuthorizationPolicy> policies )
        {
            if ( policies == null )
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "policies" );
            }

            for ( int i = 0; i < policies.Count; ++i )
            {
                if ( policies[i] is EndpointAuthorizationPolicy )
                {
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// Gets the primary identity claim to create the SCTAuthorizationPolicy
        /// </summary>
        /// <param name="authContext">The authorization context</param>
        /// <returns>The primary identity claim from the authorization context.</returns>
        SysClaim GetPrimaryIdentityClaim( SystemAuthorizationContext authContext )
        {
            if ( authContext != null )
            {
                for ( int i = 0; i < authContext.ClaimSets.Count; ++i )
                {
                    System.IdentityModel.Claims.ClaimSet claimSet = authContext.ClaimSets[i];
                    foreach ( System.IdentityModel.Claims.Claim claim in claimSet.FindClaims( null, System.IdentityModel.Claims.Rights.Identity ) )
                    {
                        return claim;
                    }
                }
            }
            return null;
        }

        public void OnTokenIssued( SecurityToken issuedToken, EndpointAddress tokenRequestor )
        {
            SetPrincipalBootstrapTokensAndBindIdfxAuthPolicy( issuedToken as SecurityContextSecurityToken );
        }

        public void OnTokenRenewed( SecurityToken issuedToken, SecurityToken oldToken )
        {
            SetPrincipalBootstrapTokensAndBindIdfxAuthPolicy( issuedToken as SecurityContextSecurityToken );
        }
    }
}