1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4 
5 namespace System.IdentityModel.Selectors
6 {
7     using System.Collections.ObjectModel;
8     using System.IdentityModel.Configuration;
9     using System.IdentityModel.Tokens;
10     using System.Xml;
11 
12     public abstract class SecurityTokenResolver : ICustomIdentityConfiguration
13     {
ResolveToken(SecurityKeyIdentifier keyIdentifier)14         public SecurityToken ResolveToken(SecurityKeyIdentifier keyIdentifier)
15         {
16             if (keyIdentifier == null)
17             {
18                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("keyIdentifier");
19             }
20             SecurityToken token;
21             if (!this.TryResolveTokenCore(keyIdentifier, out token))
22             {
23                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.UnableToResolveTokenReference, keyIdentifier)));
24             }
25             return token;
26         }
27 
TryResolveToken(SecurityKeyIdentifier keyIdentifier, out SecurityToken token)28         public bool TryResolveToken(SecurityKeyIdentifier keyIdentifier, out SecurityToken token)
29         {
30             if (keyIdentifier == null)
31             {
32                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("keyIdentifier");
33             }
34             return TryResolveTokenCore(keyIdentifier, out token);
35         }
36 
ResolveToken(SecurityKeyIdentifierClause keyIdentifierClause)37         public SecurityToken ResolveToken(SecurityKeyIdentifierClause keyIdentifierClause)
38         {
39             if (keyIdentifierClause == null)
40             {
41                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("keyIdentifierClause");
42             }
43             SecurityToken token;
44             if (!this.TryResolveTokenCore(keyIdentifierClause, out token))
45             {
46                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.UnableToResolveTokenReference, keyIdentifierClause)));
47             }
48             return token;
49         }
50 
TryResolveToken(SecurityKeyIdentifierClause keyIdentifierClause, out SecurityToken token)51         public bool TryResolveToken(SecurityKeyIdentifierClause keyIdentifierClause, out SecurityToken token)
52         {
53             if (keyIdentifierClause == null)
54             {
55                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("keyIdentifierClause");
56             }
57             return this.TryResolveTokenCore(keyIdentifierClause, out token);
58         }
59 
ResolveSecurityKey(SecurityKeyIdentifierClause keyIdentifierClause)60         public SecurityKey ResolveSecurityKey(SecurityKeyIdentifierClause keyIdentifierClause)
61         {
62             if (keyIdentifierClause == null)
63             {
64                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("keyIdentifierClause");
65             }
66             SecurityKey key;
67             if (!this.TryResolveSecurityKeyCore(keyIdentifierClause, out key))
68             {
69                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.UnableToResolveKeyReference, keyIdentifierClause)));
70             }
71             return key;
72         }
73 
TryResolveSecurityKey(SecurityKeyIdentifierClause keyIdentifierClause, out SecurityKey key)74         public bool TryResolveSecurityKey(SecurityKeyIdentifierClause keyIdentifierClause, out SecurityKey key)
75         {
76             if (keyIdentifierClause == null)
77             {
78                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("keyIdentifierClause");
79             }
80             return this.TryResolveSecurityKeyCore(keyIdentifierClause, out key);
81         }
82 
83         /// <summary>
84         /// Load custom configuration from Xml
85         /// </summary>
86         /// <param name="nodelist">Custom configuration elements</param>
LoadCustomConfiguration(XmlNodeList nodelist)87         public virtual void LoadCustomConfiguration(XmlNodeList nodelist)
88         {
89             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException(SR.GetString(SR.ID0023, this.GetType().AssemblyQualifiedName)));
90         }
91 
92         // protected methods
TryResolveTokenCore(SecurityKeyIdentifier keyIdentifier, out SecurityToken token)93         protected abstract bool TryResolveTokenCore(SecurityKeyIdentifier keyIdentifier, out SecurityToken token);
TryResolveTokenCore(SecurityKeyIdentifierClause keyIdentifierClause, out SecurityToken token)94         protected abstract bool TryResolveTokenCore(SecurityKeyIdentifierClause keyIdentifierClause, out SecurityToken token);
TryResolveSecurityKeyCore(SecurityKeyIdentifierClause keyIdentifierClause, out SecurityKey key)95         protected abstract bool TryResolveSecurityKeyCore(SecurityKeyIdentifierClause keyIdentifierClause, out SecurityKey key);
96 
97 
CreateDefaultSecurityTokenResolver(ReadOnlyCollection<SecurityToken> tokens, bool canMatchLocalId)98         public static SecurityTokenResolver CreateDefaultSecurityTokenResolver(ReadOnlyCollection<SecurityToken> tokens, bool canMatchLocalId)
99         {
100             return new SimpleTokenResolver(tokens, canMatchLocalId);
101         }
102 
103         class SimpleTokenResolver : SecurityTokenResolver
104         {
105             ReadOnlyCollection<SecurityToken> tokens;
106             bool canMatchLocalId;
107 
SimpleTokenResolver(ReadOnlyCollection<SecurityToken> tokens, bool canMatchLocalId)108             public SimpleTokenResolver(ReadOnlyCollection<SecurityToken> tokens, bool canMatchLocalId)
109             {
110                 if (tokens == null)
111                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("tokens");
112 
113                 this.tokens = tokens;
114                 this.canMatchLocalId = canMatchLocalId;
115             }
116 
TryResolveSecurityKeyCore(SecurityKeyIdentifierClause keyIdentifierClause, out SecurityKey key)117             protected override bool TryResolveSecurityKeyCore(SecurityKeyIdentifierClause keyIdentifierClause, out SecurityKey key)
118             {
119                 if (keyIdentifierClause == null)
120                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("keyIdentifierClause");
121 
122                 key = null;
123                 for (int i = 0; i < this.tokens.Count; ++i)
124                 {
125                     SecurityKey securityKey = this.tokens[i].ResolveKeyIdentifierClause(keyIdentifierClause);
126                     if (securityKey != null)
127                     {
128                         key = securityKey;
129                         return true;
130                     }
131                 }
132 
133                 if (keyIdentifierClause is EncryptedKeyIdentifierClause)
134                 {
135                     EncryptedKeyIdentifierClause keyClause = (EncryptedKeyIdentifierClause)keyIdentifierClause;
136                     SecurityKeyIdentifier keyIdentifier = keyClause.EncryptingKeyIdentifier;
137                     if (keyIdentifier != null && keyIdentifier.Count > 0)
138                     {
139                         for (int i = 0; i < keyIdentifier.Count; i++)
140                         {
141                             SecurityKey unwrappingSecurityKey = null;
142                             if (TryResolveSecurityKey(keyIdentifier[i], out unwrappingSecurityKey))
143                             {
144                                 byte[] wrappedKey = keyClause.GetEncryptedKey();
145                                 string wrappingAlgorithm = keyClause.EncryptionMethod;
146                                 byte[] unwrappedKey = unwrappingSecurityKey.DecryptKey(wrappingAlgorithm, wrappedKey);
147                                 key = new InMemorySymmetricSecurityKey(unwrappedKey, false);
148                                 return true;
149                             }
150                         }
151                     }
152                 }
153 
154                 return key != null;
155             }
156 
TryResolveTokenCore(SecurityKeyIdentifier keyIdentifier, out SecurityToken token)157             protected override bool TryResolveTokenCore(SecurityKeyIdentifier keyIdentifier, out SecurityToken token)
158             {
159                 if (keyIdentifier == null)
160                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("keyIdentifier");
161 
162                 token = null;
163                 for (int i = 0; i < keyIdentifier.Count; ++i)
164                 {
165 
166                     SecurityToken securityToken = ResolveSecurityToken(keyIdentifier[i]);
167                     if (securityToken != null)
168                     {
169                         token = securityToken;
170                         break;
171                     }
172                 }
173 
174                 return (token != null);
175             }
176 
TryResolveTokenCore(SecurityKeyIdentifierClause keyIdentifierClause, out SecurityToken token)177             protected override bool TryResolveTokenCore(SecurityKeyIdentifierClause keyIdentifierClause, out SecurityToken token)
178             {
179                 if (keyIdentifierClause == null)
180                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("keyIdentifierClause");
181 
182                 token = null;
183 
184                 SecurityToken securityToken = ResolveSecurityToken(keyIdentifierClause);
185                 if (securityToken != null)
186                     token = securityToken;
187 
188                 return (token != null);
189             }
190 
ResolveSecurityToken(SecurityKeyIdentifierClause keyIdentifierClause)191             SecurityToken ResolveSecurityToken(SecurityKeyIdentifierClause keyIdentifierClause)
192             {
193                 if (keyIdentifierClause == null)
194                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("keyIdentifierClause");
195 
196                 if (!this.canMatchLocalId && keyIdentifierClause is LocalIdKeyIdentifierClause)
197                     return null;
198 
199                 for (int i = 0; i < this.tokens.Count; ++i)
200                 {
201                     if (this.tokens[i].MatchesKeyIdentifierClause(keyIdentifierClause))
202                         return this.tokens[i];
203                 }
204 
205                 return null;
206             }
207 
208         }
209 
210     }
211 }
212