2 // WSSecurityTokenSerializer.cs
5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2006-2007 Novell, Inc. http://www.novell.com
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System
.Collections
.Generic
;
30 using System
.IdentityModel
.Selectors
;
31 using System
.IdentityModel
.Tokens
;
32 using System
.Security
.Cryptography
.X509Certificates
;
33 using System
.Security
.Cryptography
.Xml
;
34 using System
.ServiceModel
.Security
.Tokens
;
38 namespace System
.ServiceModel
.Security
40 public class WSSecurityTokenSerializer
: SecurityTokenSerializer
42 static WSSecurityTokenSerializer default_instance
=
43 new WSSecurityTokenSerializer ();
45 public static WSSecurityTokenSerializer DefaultInstance
{
46 get { return default_instance; }
49 const int defaultOffset
= 64,
50 defaultLabelLength
= 128,
51 defaultNonceLength
= 128;
53 public WSSecurityTokenSerializer ()
58 public WSSecurityTokenSerializer (bool emitBspRequiredAttributes
)
59 : this (SecurityVersion
.WSSecurity11
, emitBspRequiredAttributes
)
63 public WSSecurityTokenSerializer (SecurityVersion securityVersion
)
64 : this (securityVersion
, false)
68 public WSSecurityTokenSerializer (SecurityVersion securityVersion
, bool emitBspRequiredAttributes
)
69 : this (securityVersion
, emitBspRequiredAttributes
, new SamlSerializer ())
73 public WSSecurityTokenSerializer (
74 SecurityVersion securityVersion
,
75 bool emitBspRequiredAttributes
,
76 SamlSerializer samlSerializer
)
77 : this (securityVersion
, emitBspRequiredAttributes
,
78 samlSerializer
, null, null)
82 public WSSecurityTokenSerializer (
83 SecurityVersion securityVersion
,
84 bool emitBspRequiredAttributes
,
85 SamlSerializer samlSerializer
,
86 SecurityStateEncoder securityStateEncoder
,
87 IEnumerable
<Type
> knownTypes
)
88 : this (securityVersion
, emitBspRequiredAttributes
,
89 samlSerializer
, securityStateEncoder
,
90 knownTypes
, defaultOffset
, defaultLabelLength
,
95 public WSSecurityTokenSerializer (
96 SecurityVersion securityVersion
,
97 bool emitBspRequiredAttributes
,
98 SamlSerializer samlSerializer
,
99 SecurityStateEncoder securityStateEncoder
,
100 IEnumerable
<Type
> knownTypes
,
101 int maximumKeyDerivationOffset
,
102 int maximumKeyDerivationLabelLength
,
103 int maximumKeyDerivationNonceLength
)
105 security_version
= securityVersion
;
106 emit_bsp
= emitBspRequiredAttributes
;
107 saml_serializer
= samlSerializer
;
108 encoder
= securityStateEncoder
;
109 known_types
= new List
<Type
> (knownTypes
?? Type
.EmptyTypes
);
110 max_offset
= maximumKeyDerivationOffset
;
111 max_label_length
= maximumKeyDerivationLabelLength
;
112 max_nonce_length
= maximumKeyDerivationNonceLength
;
115 encoder
= new DataProtectionSecurityStateEncoder ();
118 SecurityVersion security_version
;
120 SamlSerializer saml_serializer
;
121 SecurityStateEncoder encoder
;
122 List
<Type
> known_types
;
123 int max_offset
, max_label_length
, max_nonce_length
;
126 get { return SecurityVersion == SecurityVersion.WSSecurity10; }
129 public bool EmitBspRequiredAttributes
{
130 get { return emit_bsp; }
133 public SecurityVersion SecurityVersion
{
134 get { return security_version; }
138 public int MaximumKeyDerivationOffset
{
139 get { return max_offset; }
143 public int MaximumKeyDerivationLabelLength
{
144 get { return max_label_length; }
148 public int MaximumKeyDerivationNonceLength
{
149 get { return max_nonce_length; }
152 protected virtual string GetTokenTypeUri (Type tokenType
)
154 if (tokenType
== typeof (WrappedKeySecurityToken
))
155 return Constants
.WSSEncryptedKeyToken
;
156 if (tokenType
== typeof (X509SecurityToken
))
157 return Constants
.WSSX509Token
;
158 // if (tokenType == typeof (RsaSecurityToken))
160 if (tokenType
== typeof (SamlSecurityToken
))
161 return Constants
.WSSSamlToken
;
162 if (tokenType
== typeof (SecurityContextSecurityToken
))
163 return Constants
.WsscContextToken
;
164 // if (tokenType == typeof (huh))
165 // return ServiceModelSecurityTokenTypes.SecureConversation;
166 // if (tokenType == typeof (hah))
167 // return ServiceModelSecurityTokenTypes.MutualSslnego;
168 // if (tokenType == typeof (whoa))
169 // return ServiceModelSecurityTokenTypes.AnonymousSslnego;
170 if (tokenType
== typeof (UserNameSecurityToken
))
171 return Constants
.WSSUserNameToken
;
172 // if (tokenType == typeof (uhoh))
173 // return ServiceModelSecurityTokenTypes.Spnego;
174 // if (tokenType == typeof (SspiSecurityToken))
175 // return ServiceModelSecurityTokenTypes.SspiCredential;
176 if (tokenType
== typeof (KerberosRequestorSecurityToken
))
177 return Constants
.WSSKerberosToken
;
182 protected override bool CanReadKeyIdentifierClauseCore (XmlReader reader
)
184 reader
.MoveToContent ();
185 switch (reader
.NamespaceURI
) {
186 case EncryptedXml
.XmlEncNamespaceUrl
:
187 switch (reader
.LocalName
) {
192 case Constants
.WssNamespace
:
193 switch (reader
.LocalName
) {
194 case "SecurityTokenReference":
204 protected override bool CanReadKeyIdentifierCore (XmlReader reader
)
206 throw new NotImplementedException ();
210 protected override bool CanReadTokenCore (XmlReader reader
)
212 reader
.MoveToContent ();
214 switch (reader
.NamespaceURI
) {
215 case Constants
.WssNamespace
:
216 switch (reader
.LocalName
) {
217 case "BinarySecurityToken":
219 case "UsernameToken":
223 case Constants
.WsscNamespace
:
224 switch (reader
.LocalName
) {
225 case "DerivedKeyToken":
226 case "SecurityContextToken":
230 case EncryptedXml
.XmlEncNamespaceUrl
:
231 switch (reader
.LocalName
) {
241 public virtual SecurityKeyIdentifierClause
CreateKeyIdentifierClauseFromTokenXml (
242 XmlElement tokenXml
, SecurityTokenReferenceStyle referenceStyle
)
244 throw new NotImplementedException ();
248 protected override SecurityKeyIdentifier
ReadKeyIdentifierCore (
251 throw new NotImplementedException ();
255 protected override SecurityKeyIdentifierClause
ReadKeyIdentifierClauseCore (XmlReader reader
)
257 reader
.MoveToContent ();
258 switch (reader
.NamespaceURI
) {
259 case EncryptedXml
.XmlEncNamespaceUrl
:
260 switch (reader
.LocalName
) {
262 return ReadEncryptedKeyIdentifierClause (reader
);
265 case Constants
.WssNamespace
:
266 switch (reader
.LocalName
) {
267 case "SecurityTokenReference":
268 return ReadSecurityTokenReference (reader
);
273 throw new NotImplementedException (String
.Format ("Security key identifier clause element '{0}' in namespace '{1}' is either not implemented or not supported.", reader
.LocalName
, reader
.NamespaceURI
));
276 SecurityKeyIdentifierClause
ReadSecurityTokenReference (XmlReader reader
)
278 reader
.ReadStartElement ();
279 reader
.MoveToContent ();
280 if (reader
.NamespaceURI
== SignedXml
.XmlDsigNamespaceUrl
) {
281 KeyInfoX509Data x509
= new KeyInfoX509Data ();
282 x509
.LoadXml (new XmlDocument ().ReadNode (reader
) as XmlElement
);
283 if (x509
.IssuerSerials
.Count
== 0)
284 throw new XmlException ("'X509IssuerSerial' element is expected inside 'X509Data' element");
285 X509IssuerSerial s
= (X509IssuerSerial
) x509
.IssuerSerials
[0];
286 reader
.MoveToContent ();
287 reader
.ReadEndElement ();
288 return new X509IssuerSerialKeyIdentifierClause (s
.IssuerName
, s
.SerialNumber
);
290 if (reader
.NamespaceURI
!= Constants
.WssNamespace
)
291 throw new XmlException (String
.Format ("Unexpected SecurityTokenReference content: expected local name 'Reference' and namespace URI '{0}' but found local name '{1}' and namespace '{2}'.", Constants
.WssNamespace
, reader
.LocalName
, reader
.NamespaceURI
));
293 switch (reader
.LocalName
) {
295 Type ownerType
= null;
296 // FIXME: there could be more token types.
297 if (reader
.MoveToAttribute ("ValueType")) {
298 switch (reader
.Value
) {
299 case Constants
.WSSEncryptedKeyToken
:
300 ownerType
= typeof (WrappedKeySecurityToken
);
302 case Constants
.WSSX509Token
:
303 ownerType
= typeof (X509SecurityToken
);
305 case Constants
.WsscContextToken
:
306 ownerType
= typeof (SecurityContextSecurityToken
);
309 throw new XmlException (String
.Format ("Unexpected ValueType in 'Reference' element: '{0}'", reader
.Value
));
312 reader
.MoveToElement ();
313 string uri
= reader
.GetAttribute ("URI");
314 if (String
.IsNullOrEmpty (uri
))
316 SecurityKeyIdentifierClause ic
= null;
317 if (ownerType
== typeof (SecurityContextSecurityToken
) && uri
[0] != '#')
318 // FIXME: Generation?
319 ic
= new SecurityContextKeyIdentifierClause (new UniqueId (uri
));
321 ic
= new LocalIdKeyIdentifierClause (uri
.Substring (1), ownerType
);
323 reader
.MoveToContent ();
324 reader
.ReadEndElement ();
326 case "KeyIdentifier":
327 string valueType
= reader
.GetAttribute ("ValueType");
328 string value = reader
.ReadElementContentAsString ();
329 reader
.MoveToContent ();
330 reader
.ReadEndElement (); // consume </Reference>
332 case Constants
.WssKeyIdentifierX509Thumbptint
:
333 return new X509ThumbprintKeyIdentifierClause (Convert
.FromBase64String (value));
334 case Constants
.WssKeyIdentifierEncryptedKey
:
335 return new InternalEncryptedKeyIdentifierClause (Convert
.FromBase64String (value));
336 case Constants
.WssKeyIdentifierSamlAssertion
:
337 return new SamlAssertionKeyIdentifierClause (value);
339 // It is kinda weird but it throws XmlException here ...
340 throw new XmlException (String
.Format ("KeyIdentifier type '{0}' is not supported in WSSecurityTokenSerializer.", valueType
));
343 throw new XmlException (String
.Format ("Unexpected SecurityTokenReference content: expected local name 'Reference' and namespace URI '{0}' but found local name '{1}' and namespace '{2}'.", Constants
.WssNamespace
, reader
.LocalName
, reader
.NamespaceURI
));
347 EncryptedKeyIdentifierClause
ReadEncryptedKeyIdentifierClause (
350 string encNS
= EncryptedXml
.XmlEncNamespaceUrl
;
352 string id
= reader
.GetAttribute ("Id", Constants
.WsuNamespace
);
354 reader
.MoveToContent ();
355 string encMethod
= reader
.GetAttribute ("Algorithm");
356 bool isEmpty
= reader
.IsEmptyElement
;
357 reader
.ReadStartElement ("EncryptionMethod", encNS
);
358 string digMethod
= null;
360 reader
.MoveToContent ();
361 if (reader
.LocalName
== "DigestMethod" && reader
.NamespaceURI
== SignedXml
.XmlDsigNamespaceUrl
)
362 digMethod
= reader
.GetAttribute ("Algorithm");
363 while (reader
.NodeType
!= XmlNodeType
.EndElement
) {
365 reader
.MoveToContent ();
367 reader
.ReadEndElement ();
369 reader
.MoveToContent ();
370 SecurityKeyIdentifier ki
= null;
371 if (!reader
.IsEmptyElement
) {
372 reader
.ReadStartElement ("KeyInfo", SignedXml
.XmlDsigNamespaceUrl
);
373 reader
.MoveToContent ();
374 SecurityKeyIdentifierClause kic
= ReadKeyIdentifierClauseCore (reader
);
375 ki
= new SecurityKeyIdentifier ();
377 reader
.MoveToContent ();
378 reader
.ReadEndElement (); // </ds:KeyInfo>
379 reader
.MoveToContent ();
381 byte [] keyValue
= null;
382 if (!reader
.IsEmptyElement
) {
383 reader
.ReadStartElement ("CipherData", encNS
);
384 reader
.MoveToContent ();
385 keyValue
= Convert
.FromBase64String (reader
.ReadElementContentAsString ("CipherValue", encNS
));
386 reader
.MoveToContent ();
387 reader
.ReadEndElement (); // CipherData
389 string carriedKeyName
= null;
390 if (!reader
.IsEmptyElement
&& reader
.LocalName
== "CarriedKeyName" && reader
.NamespaceURI
== encNS
) {
391 carriedKeyName
= reader
.ReadElementContentAsString ();
392 reader
.MoveToContent ();
394 // FIXME: handle derived keys??
395 return new EncryptedKeyIdentifierClause (keyValue
, encMethod
, ki
, carriedKeyName
);
399 protected override SecurityToken
ReadTokenCore (
401 SecurityTokenResolver tokenResolver
)
403 if (!CanReadToken (reader
))
404 throw new XmlException (String
.Format ("Cannot read security token from {0} node of name '{1}' and namespace URI '{2}'", reader
.NodeType
, reader
.LocalName
, reader
.NamespaceURI
));
406 switch (reader
.NamespaceURI
) {
407 case Constants
.WssNamespace
:
408 switch (reader
.LocalName
) {
409 case "BinarySecurityToken":
410 return ReadX509TokenCore (reader
, tokenResolver
);
412 return ReadBinarySecretTokenCore (reader
, tokenResolver
);
413 case "UsernameToken":
414 return ReadUserNameTokenCore (reader
, tokenResolver
);
417 case Constants
.WsscNamespace
:
418 if (reader
.LocalName
== "DerivedKeyToken")
419 return ReadDerivedKeyToken (reader
, tokenResolver
);
420 if (reader
.LocalName
== "SecurityContextToken")
421 return ReadSecurityContextToken (reader
, tokenResolver
);
423 case EncryptedXml
.XmlEncNamespaceUrl
:
424 switch (reader
.LocalName
) {
426 return ReadWrappedKeySecurityTokenCore (reader
, tokenResolver
);
431 throw new NotImplementedException ();
434 DerivedKeySecurityToken
ReadDerivedKeyToken (
435 XmlReader reader
, SecurityTokenResolver tokenResolver
)
438 return ReadDerivedKeyTokenCore (reader
, tokenResolver
);
439 } catch (XmlException
) {
441 } catch (Exception ex
) {
442 throw new XmlException ("Cannot read DerivedKeyToken", ex
);
446 DerivedKeySecurityToken
ReadDerivedKeyTokenCore (
447 XmlReader reader
, SecurityTokenResolver tokenResolver
)
449 if (tokenResolver
== null)
450 throw new ArgumentNullException ("tokenResolver");
451 string id
= reader
.GetAttribute ("Id", Constants
.WsuNamespace
);
452 string algorithm
= reader
.MoveToAttribute ("Algorithm") ? reader
.Value
: null;
453 reader
.MoveToElement ();
454 reader
.ReadStartElement ();
455 reader
.MoveToContent ();
456 SecurityKeyIdentifierClause kic
= ReadKeyIdentifierClause (reader
);
457 int? generation
= null, offset
= null, length
= null;
458 byte [] nonce
= null;
459 string name
= null, label
= null;
460 for (reader
.MoveToContent ();
461 reader
.NodeType
!= XmlNodeType
.EndElement
;
462 reader
.MoveToContent ())
463 switch (reader
.LocalName
) {
465 reader
.ReadStartElement ("Properties", Constants
.WsscNamespace
);
466 for (reader
.MoveToContent ();
467 reader
.NodeType
!= XmlNodeType
.EndElement
;
468 reader
.MoveToContent ())
469 switch (reader
.LocalName
) {
471 name
= reader
.ReadElementContentAsString ("Name", Constants
.WsscNamespace
);
474 label
= reader
.ReadElementContentAsString ("Label", Constants
.WsscNamespace
);
477 nonce
= Convert
.FromBase64String (reader
.ReadElementContentAsString ("Nonce", Constants
.WsscNamespace
));
480 reader
.ReadEndElement ();
483 offset
= reader
.ReadElementContentAsInt ("Offset", Constants
.WsscNamespace
);
486 length
= reader
.ReadElementContentAsInt ("Length", Constants
.WsscNamespace
);
489 nonce
= Convert
.FromBase64String (reader
.ReadElementContentAsString ("Nonce", Constants
.WsscNamespace
));
492 label
= reader
.ReadElementContentAsString ("Label", Constants
.WsscNamespace
);
495 reader
.ReadEndElement ();
497 // resolve key reference
498 SymmetricSecurityKey key
= tokenResolver
.ResolveSecurityKey (kic
) as SymmetricSecurityKey
;
500 throw new XmlException ("Cannot resolve the security key referenced by the DerivedKeyToken as a symmetric key");
502 return new DerivedKeySecurityToken (id
, algorithm
, kic
, key
, name
, generation
, offset
, length
, label
, nonce
);
505 // since it cannot consume RequestSecurityTokenResponse,
506 // the token information cannot be complete.
507 SecurityContextSecurityToken
ReadSecurityContextToken (
508 XmlReader reader
, SecurityTokenResolver tokenResolver
)
510 string id
= reader
.GetAttribute ("Id", Constants
.WsuNamespace
);
513 // The input dnse:Cookie value is encrypted by the
514 // server's SecurityStateEncoder
515 // (setting error-raising encoder to ServiceCredentials.
516 // SecureConversationAuthentication.SecurityStateEncoder
519 byte [] cookie
= null;
521 reader
.MoveToContent ();
522 if (reader
.NodeType
!= XmlNodeType
.Element
)
524 switch (reader
.NamespaceURI
) {
525 case Constants
.WsscNamespace
:
526 switch (reader
.LocalName
) {
528 cid
= new UniqueId (reader
.ReadElementContentAsString ());
532 case Constants
.MSTlsnegoTokenContent
:
533 switch (reader
.LocalName
) {
535 cookie
= Convert
.FromBase64String (reader
.ReadElementContentAsString ());
540 throw new XmlException (String
.Format ("Unexpected element {0} in namespace {1}", reader
.LocalName
, reader
.NamespaceURI
));
542 reader
.ReadEndElement ();
544 // LAMESPEC: at client side there is no way to specify
545 // SecurityStateEncoder, so it must be guessed from
546 // its cookie content itself.
547 if (encoder
== null) throw new Exception ();
549 cookie
!= null && cookie
.Length
> 154 ?
550 encoder
.DecodeSecurityState (cookie
) :
552 return SslnegoCookieResolver
.ResolveCookie (decoded
, cookie
);
555 WrappedKeySecurityToken
ReadWrappedKeySecurityTokenCore (
556 XmlReader reader
, SecurityTokenResolver tokenResolver
)
558 if (tokenResolver
== null)
559 throw new ArgumentNullException ("tokenResolver");
560 EncryptedKey ek
= new EncryptedKey ();
561 ek
.LoadXml (new XmlDocument ().ReadNode (reader
) as XmlElement
);
562 SecurityKeyIdentifier ki
= new SecurityKeyIdentifier ();
563 foreach (KeyInfoClause kic
in ek
.KeyInfo
)
564 ki
.Add (ReadKeyIdentifierClause (new XmlNodeReader (kic
.GetXml ())));
565 SecurityToken token
= tokenResolver
.ResolveToken (ki
);
566 string alg
= ek
.EncryptionMethod
.KeyAlgorithm
;
567 foreach (SecurityKey skey
in token
.SecurityKeys
)
568 if (skey
.IsSupportedAlgorithm (alg
)) {
569 byte [] key
= skey
.DecryptKey (alg
, ek
.CipherData
.CipherValue
);
570 WrappedKeySecurityToken wk
=
571 new WrappedKeySecurityToken (ek
.Id
, key
, alg
, token
, ki
);
572 // FIXME: This should not be required.
573 wk
.SetWrappedKey (ek
.CipherData
.CipherValue
);
574 wk
.ReferenceList
= ek
.ReferenceList
;
577 throw new InvalidOperationException (String
.Format ("Cannot resolve security key with the resolved SecurityToken specified by the key identifier in the EncryptedKey XML. The key identifier is: {0}", ki
));
580 X509SecurityToken
ReadX509TokenCore (
581 XmlReader reader
, SecurityTokenResolver resolver
)
583 string id
= reader
.GetAttribute ("Id", Constants
.WsuNamespace
);
584 byte [] raw
= Convert
.FromBase64String (reader
.ReadElementContentAsString ());
585 return new X509SecurityToken (new X509Certificate2 (raw
), id
);
588 UserNameSecurityToken
ReadUserNameTokenCore (
589 XmlReader reader
, SecurityTokenResolver resolver
)
591 string id
= reader
.GetAttribute ("Id", Constants
.WsuNamespace
);
592 if (reader
.IsEmptyElement
)
593 throw new XmlException ("At least UsernameToken must contain Username");
595 reader
.MoveToContent ();
596 string user
= reader
.ReadElementContentAsString ("Username", Constants
.WssNamespace
);
597 reader
.MoveToContent ();
599 if (reader
.LocalName
== "Password" && reader
.NamespaceURI
== Constants
.WssNamespace
) {
600 pass
= reader
.ReadElementContentAsString ("Password", Constants
.WssNamespace
);
601 reader
.MoveToContent ();
603 reader
.ReadEndElement ();
605 new UserNameSecurityToken (user
, pass
, id
) :
606 new UserNameSecurityToken (user
, pass
);
609 BinarySecretSecurityToken
ReadBinarySecretTokenCore (
610 XmlReader reader
, SecurityTokenResolver resolver
)
612 string id
= reader
.GetAttribute ("Id", Constants
.WsuNamespace
);
613 byte [] data
= Convert
.FromBase64String (reader
.ReadElementContentAsString ());
614 return new BinarySecretSecurityToken (id
, data
);
618 protected override bool CanWriteKeyIdentifierCore (
619 SecurityKeyIdentifier keyIdentifier
)
621 throw new NotImplementedException ();
625 protected override bool CanWriteKeyIdentifierClauseCore (
626 SecurityKeyIdentifierClause keyIdentifierClause
)
628 if (keyIdentifierClause
== null)
629 throw new ArgumentNullException ("keyIdentifierClause");
630 if (keyIdentifierClause
is LocalIdKeyIdentifierClause
||
631 keyIdentifierClause
is SecurityContextKeyIdentifierClause
||
632 keyIdentifierClause
is X509IssuerSerialKeyIdentifierClause
||
633 (keyIdentifierClause
is X509ThumbprintKeyIdentifierClause
&& !WSS1_0
) ||
634 keyIdentifierClause
is EncryptedKeyIdentifierClause
||
635 keyIdentifierClause
is BinarySecretKeyIdentifierClause
||
636 keyIdentifierClause
is InternalEncryptedKeyIdentifierClause
||
637 keyIdentifierClause
is SamlAssertionKeyIdentifierClause
)
644 protected override bool CanWriteTokenCore (SecurityToken token
)
646 throw new NotImplementedException ();
650 protected override void WriteKeyIdentifierCore (
652 SecurityKeyIdentifier keyIdentifier
)
654 throw new NotImplementedException ();
658 protected override void WriteKeyIdentifierClauseCore (
660 SecurityKeyIdentifierClause keyIdentifierClause
)
662 string errorReason
= null;
664 if (keyIdentifierClause
== null)
665 throw new ArgumentNullException ("keyIdentifierClause");
666 if (keyIdentifierClause
is LocalIdKeyIdentifierClause
)
667 WriteLocalIdKeyIdentifierClause (writer
, (LocalIdKeyIdentifierClause
) keyIdentifierClause
);
668 else if (keyIdentifierClause
is SecurityContextKeyIdentifierClause
)
669 WriteSecurityContextKeyIdentifierClause (writer
, (SecurityContextKeyIdentifierClause
) keyIdentifierClause
);
670 else if (keyIdentifierClause
is X509IssuerSerialKeyIdentifierClause
)
671 WriteX509IssuerSerialKeyIdentifierClause (writer
, (X509IssuerSerialKeyIdentifierClause
) keyIdentifierClause
);
672 else if (keyIdentifierClause
is X509ThumbprintKeyIdentifierClause
) {
674 errorReason
= String
.Format ("Security key identifier clause '{0}' is not supported in this serializer.", keyIdentifierClause
.GetType ());
676 WriteX509ThumbprintKeyIdentifierClause (writer
, (X509ThumbprintKeyIdentifierClause
) keyIdentifierClause
);
678 else if (keyIdentifierClause
is EncryptedKeyIdentifierClause
)
679 WriteEncryptedKeyIdentifierClause (writer
, (EncryptedKeyIdentifierClause
) keyIdentifierClause
);
680 else if (keyIdentifierClause
is BinarySecretKeyIdentifierClause
)
681 WriteBinarySecretKeyIdentifierClause (writer
, (BinarySecretKeyIdentifierClause
) keyIdentifierClause
);
682 else if (keyIdentifierClause
is InternalEncryptedKeyIdentifierClause
)
683 WriteInternalEncryptedKeyIdentifierClause (writer
, (InternalEncryptedKeyIdentifierClause
) keyIdentifierClause
);
684 else if (keyIdentifierClause
is SamlAssertionKeyIdentifierClause
)
685 WriteSamlAssertionKeyIdentifierClause (writer
, (SamlAssertionKeyIdentifierClause
) keyIdentifierClause
);
687 throw new NotImplementedException (String
.Format ("Security key identifier clause '{0}' is not either implemented or supported.", keyIdentifierClause
.GetType ()));
689 if (errorReason
!= null)
690 throw new InvalidOperationException (errorReason
);
693 void WriteX509IssuerSerialKeyIdentifierClause (
694 XmlWriter w
, X509IssuerSerialKeyIdentifierClause ic
)
696 w
.WriteStartElement ("o", "SecurityTokenReference", Constants
.WssNamespace
);
697 w
.WriteStartElement ("X509Data", Constants
.XmlDsig
);
698 w
.WriteStartElement ("X509IssuerSerial", Constants
.XmlDsig
);
699 w
.WriteStartElement ("X509IssuerName", Constants
.XmlDsig
);
700 w
.WriteString (ic
.IssuerName
);
701 w
.WriteEndElement ();
702 w
.WriteStartElement ("X509SerialNumber", Constants
.XmlDsig
);
703 w
.WriteString (ic
.IssuerSerialNumber
);
704 w
.WriteEndElement ();
705 w
.WriteEndElement ();
706 w
.WriteEndElement ();
707 w
.WriteEndElement ();
710 void WriteX509ThumbprintKeyIdentifierClause (
711 XmlWriter w
, X509ThumbprintKeyIdentifierClause ic
)
713 w
.WriteStartElement ("o", "SecurityTokenReference", Constants
.WssNamespace
);
714 w
.WriteStartElement ("o", "KeyIdentifier", Constants
.WssNamespace
);
715 w
.WriteAttributeString ("ValueType", Constants
.WssKeyIdentifierX509Thumbptint
);
716 if (EmitBspRequiredAttributes
)
717 w
.WriteAttributeString ("EncodingType", Constants
.WssBase64BinaryEncodingType
);
718 w
.WriteString (Convert
.ToBase64String (ic
.GetX509Thumbprint ()));
719 w
.WriteEndElement ();
720 w
.WriteEndElement ();
723 void WriteLocalIdKeyIdentifierClause (
724 XmlWriter w
, LocalIdKeyIdentifierClause ic
)
726 w
.WriteStartElement ("o", "SecurityTokenReference", Constants
.WssNamespace
);
727 w
.WriteStartElement ("o", "Reference", Constants
.WssNamespace
);
728 if (EmitBspRequiredAttributes
&& ic
.OwnerType
!= null) {
729 string vt
= GetTokenTypeUri (ic
.OwnerType
);
731 w
.WriteAttributeString ("ValueType", vt
);
733 w
.WriteAttributeString ("URI", "#" + ic
.LocalId
);
734 w
.WriteEndElement ();
735 w
.WriteEndElement ();
738 void WriteSecurityContextKeyIdentifierClause (
739 XmlWriter w
, SecurityContextKeyIdentifierClause ic
)
741 w
.WriteStartElement ("o", "SecurityTokenReference", Constants
.WssNamespace
);
742 w
.WriteStartElement ("o", "Reference", Constants
.WssNamespace
);
743 w
.WriteAttributeString ("URI", ic
.ContextId
.ToString ());
744 string vt
= GetTokenTypeUri (typeof (SecurityContextSecurityToken
));
745 w
.WriteAttributeString ("ValueType", vt
);
746 w
.WriteEndElement ();
747 w
.WriteEndElement ();
750 void WriteEncryptedKeyIdentifierClause (
751 XmlWriter w
, EncryptedKeyIdentifierClause ic
)
753 w
.WriteStartElement ("e", "EncryptedKey", EncryptedXml
.XmlEncNamespaceUrl
);
754 w
.WriteStartElement ("EncryptionMethod", EncryptedXml
.XmlEncNamespaceUrl
);
755 w
.WriteAttributeString ("Algorithm", ic
.EncryptionMethod
);
756 w
.WriteEndElement ();
757 if (ic
.EncryptingKeyIdentifier
!= null) {
758 w
.WriteStartElement ("KeyInfo", SignedXml
.XmlDsigNamespaceUrl
);
759 foreach (SecurityKeyIdentifierClause ckic
in ic
.EncryptingKeyIdentifier
)
760 WriteKeyIdentifierClause (w
, ckic
);
761 w
.WriteEndElement ();
763 w
.WriteStartElement ("CipherData", EncryptedXml
.XmlEncNamespaceUrl
);
764 w
.WriteStartElement ("CipherValue", EncryptedXml
.XmlEncNamespaceUrl
);
765 w
.WriteString (Convert
.ToBase64String (ic
.GetEncryptedKey ()));
766 w
.WriteEndElement ();
767 w
.WriteEndElement ();
768 if (ic
.CarriedKeyName
!= null)
769 w
.WriteElementString ("CarriedKeyName", EncryptedXml
.XmlEncNamespaceUrl
, ic
.CarriedKeyName
);
770 w
.WriteEndElement ();
773 void WriteBinarySecretKeyIdentifierClause (
774 XmlWriter w
, BinarySecretKeyIdentifierClause ic
)
776 w
.WriteStartElement ("t", "BinarySecret", Constants
.WstNamespace
);
777 w
.WriteString (Convert
.ToBase64String (ic
.GetBuffer ()));
778 w
.WriteEndElement ();
781 void WriteInternalEncryptedKeyIdentifierClause (
782 XmlWriter w
, InternalEncryptedKeyIdentifierClause ic
)
784 w
.WriteStartElement ("o", "SecurityTokenReference", Constants
.WssNamespace
);
785 w
.WriteStartElement ("o", "KeyIdentifier", Constants
.WssNamespace
);
786 w
.WriteAttributeString ("ValueType", Constants
.WssKeyIdentifierEncryptedKey
);
787 w
.WriteString (Convert
.ToBase64String (ic
.GetBuffer ()));
788 w
.WriteEndElement ();
789 w
.WriteEndElement ();
792 void WriteSamlAssertionKeyIdentifierClause (XmlWriter w
, SamlAssertionKeyIdentifierClause ic
)
794 w
.WriteStartElement ("o", "SecurityTokenReference", Constants
.WssNamespace
);
795 w
.WriteStartElement ("o", "KeyIdentifier", Constants
.WssNamespace
);
796 w
.WriteAttributeString ("ValueType", Constants
.WssKeyIdentifierSamlAssertion
);
797 w
.WriteString (ic
.AssertionId
);
798 w
.WriteEndElement ();
799 w
.WriteEndElement ();
803 protected override void WriteTokenCore (
804 XmlWriter writer
, SecurityToken token
)
806 // WSSecurity supports:
807 // - UsernameToken : S.IM.T.UserNameSecurityToken
808 // - X509SecurityToken : S.IM.T.X509SecurityToken
809 // - SAML Assertion : S.IM.T.SamlSecurityToken
810 // - Kerberos : S.IM.T.KerberosRequestorSecurityToken
811 // - Rights Expression Language (REL) : N/A
812 // - SOAP with Attachments : N/A
813 // they are part of standards support:
814 // - WrappedKey (EncryptedKey)
815 // - BinarySecret (WS-Trust)
816 // - SecurityContext (WS-SecureConversation)
817 // additionally there are extra token types in WCF:
821 // not supported in this class:
824 if (token
is UserNameSecurityToken
)
825 WriteUserNameSecurityToken (writer
, ((UserNameSecurityToken
) token
));
826 else if (token
is X509SecurityToken
)
827 WriteX509SecurityToken (writer
, ((X509SecurityToken
) token
));
828 else if (token
is BinarySecretSecurityToken
)
829 WriteBinarySecretSecurityToken (writer
, ((BinarySecretSecurityToken
) token
));
830 else if (token
is SamlSecurityToken
)
831 throw new NotImplementedException ("WriteTokenCore() is not implemented for " + token
);
832 else if (token
is GenericXmlSecurityToken
)
833 ((GenericXmlSecurityToken
) token
).TokenXml
.WriteTo (writer
);
834 else if (token
is WrappedKeySecurityToken
)
835 WriteWrappedKeySecurityToken (writer
, (WrappedKeySecurityToken
) token
);
836 else if (token
is DerivedKeySecurityToken
)
837 WriteDerivedKeySecurityToken (writer
, (DerivedKeySecurityToken
) token
);
838 else if (token
is SecurityContextSecurityToken
)
839 WriteSecurityContextSecurityToken (writer
, (SecurityContextSecurityToken
) token
);
840 else if (token
is SspiSecurityToken
)
841 throw new NotImplementedException ("WriteTokenCore() is not implemented for " + token
);
842 else if (token
is KerberosRequestorSecurityToken
)
843 throw new NotImplementedException ("WriteTokenCore() is not implemented for " + token
);
844 else if (token
is WindowsSecurityToken
)
845 throw new NotImplementedException ("WriteTokenCore() is not implemented for " + token
);
847 throw new InvalidOperationException (String
.Format ("This SecurityTokenSerializer does not support security token '{0}'.", token
));
850 void WriteUserNameSecurityToken (XmlWriter w
, UserNameSecurityToken token
)
852 w
.WriteStartElement ("o", "UsernameToken", Constants
.WssNamespace
);
853 w
.WriteAttributeString ("u", "Id", Constants
.WsuNamespace
, token
.Id
);
854 w
.WriteStartElement ("o", "Username", Constants
.WssNamespace
);
855 w
.WriteString (token
.UserName
);
856 w
.WriteEndElement ();
857 w
.WriteStartElement ("o", "Password", Constants
.WssNamespace
);
858 w
.WriteString (token
.Password
);
859 w
.WriteEndElement ();
860 w
.WriteEndElement ();
863 void WriteX509SecurityToken (XmlWriter w
, X509SecurityToken token
)
865 w
.WriteStartElement ("o", "BinarySecurityToken", Constants
.WssNamespace
);
866 w
.WriteAttributeString ("u", "Id", Constants
.WsuNamespace
, token
.Id
);
867 w
.WriteAttributeString ("ValueType", Constants
.WSSX509Token
);
868 w
.WriteString (Convert
.ToBase64String (token
.Certificate
.RawData
));
869 w
.WriteEndElement ();
872 void WriteBinarySecretSecurityToken (XmlWriter w
, BinarySecretSecurityToken token
)
874 w
.WriteStartElement ("t", "BinarySecret", Constants
.WstNamespace
);
875 w
.WriteAttributeString ("u", "Id", Constants
.WsuNamespace
, token
.Id
);
876 w
.WriteString (Convert
.ToBase64String (token
.GetKeyBytes ()));
877 w
.WriteEndElement ();
880 void WriteDerivedKeySecurityToken (XmlWriter w
, DerivedKeySecurityToken token
)
882 string ns
= Constants
.WsscNamespace
;
883 w
.WriteStartElement ("c", "DerivedKeyToken", ns
);
884 w
.WriteAttributeString ("u", "Id", Constants
.WsuNamespace
, token
.Id
);
885 WriteKeyIdentifierClause (w
, token
.TokenReference
);
886 if (token
.Name
!= null) {
887 w
.WriteStartElement ("Properties", ns
);
888 w
.WriteElementString ("Name", ns
, token
.Name
);
889 w
.WriteEndElement ();
891 if (token
.Offset
!= null)
892 w
.WriteElementString ("Offset", ns
, Convert
.ToString (token
.Offset
));
893 if (token
.Length
!= null)
894 w
.WriteElementString ("Length", ns
, Convert
.ToString (token
.Length
));
895 if (token
.Label
!= null)
896 w
.WriteElementString ("Label", ns
, token
.Label
);
897 w
.WriteElementString ("Nonce", ns
, Convert
.ToBase64String (token
.Nonce
));
898 w
.WriteEndElement ();
901 void WriteWrappedKeySecurityToken (XmlWriter w
, WrappedKeySecurityToken token
)
903 string encNS
= EncryptedXml
.XmlEncNamespaceUrl
;
904 w
.WriteStartElement ("e", "EncryptedKey", encNS
);
905 w
.WriteAttributeString ("Id", token
.Id
);
906 w
.WriteStartElement ("EncryptionMethod", encNS
);
907 w
.WriteAttributeString ("Algorithm", token
.WrappingAlgorithm
);
908 w
.WriteStartElement ("DigestMethod", SignedXml
.XmlDsigNamespaceUrl
);
909 w
.WriteAttributeString ("Algorithm", SignedXml
.XmlDsigSHA1Url
);
910 w
.WriteEndElement ();
911 w
.WriteEndElement ();
913 w
.WriteStartElement ("KeyInfo", SignedXml
.XmlDsigNamespaceUrl
);
914 if (token
.WrappingTokenReference
!= null)
915 foreach (SecurityKeyIdentifierClause kic
in token
.WrappingTokenReference
)
916 WriteKeyIdentifierClause (w
, kic
);
917 w
.WriteEndElement ();
918 w
.WriteStartElement ("CipherData", encNS
);
919 w
.WriteStartElement ("CipherValue", encNS
);
920 w
.WriteString (Convert
.ToBase64String (token
.GetWrappedKey ()));
921 w
.WriteEndElement ();
922 w
.WriteEndElement ();
923 if (token
.ReferenceList
!= null) {
924 w
.WriteStartElement ("e", "ReferenceList", encNS
);
925 foreach (DataReference er
in token
.ReferenceList
) {
926 w
.WriteStartElement ("DataReference", encNS
);
927 w
.WriteAttributeString ("URI", er
.Uri
);
928 w
.WriteEndElement ();
930 w
.WriteEndElement ();
932 w
.WriteEndElement ();
935 void WriteSecurityContextSecurityToken (XmlWriter w
, SecurityContextSecurityToken token
)
937 string ns
= Constants
.WsscNamespace
;
938 w
.WriteStartElement ("c", "SecurityContextToken", ns
);
939 w
.WriteAttributeString ("u", "Id", Constants
.WsuNamespace
, token
.Id
);
940 w
.WriteElementString ("Identifier", ns
, token
.ContextId
.ToString ());
941 // FIXME: add Cookie output (from CreateCookieSecurityContextToken() method)
942 if (token
.Cookie
!= null)
943 w
.WriteElementString ("dnse", "Cookie", Constants
.MSTlsnegoTokenContent
, Convert
.ToBase64String (token
.Cookie
));
944 w
.WriteEndElement ();