diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2009-04-09 22:06:03 -0700 |
---|---|---|
committer | Andrew Arnott <andrewarnott@gmail.com> | 2009-04-09 22:06:03 -0700 |
commit | 82781e309db03f8afd09629f2b1bbce10fa355c5 (patch) | |
tree | 78aab6080a65b4740ece9aa1382503a8f718da87 | |
parent | 5d58ebb1186351deba062b3309fcc4a69465b984 (diff) | |
download | DotNetOpenAuth-82781e309db03f8afd09629f2b1bbce10fa355c5.zip DotNetOpenAuth-82781e309db03f8afd09629f2b1bbce10fa355c5.tar.gz DotNetOpenAuth-82781e309db03f8afd09629f2b1bbce10fa355c5.tar.bz2 |
Refactored the programmatic interface of InfoCard token parsing.
-rw-r--r-- | src/DotNetOpenAuth/InfoCard/InfoCardSelector.cs | 10 | ||||
-rw-r--r-- | src/DotNetOpenAuth/InfoCard/ReceivingTokenEventArgs.cs | 42 | ||||
-rw-r--r-- | src/DotNetOpenAuth/InfoCard/Token/Token.cs | 60 | ||||
-rw-r--r-- | src/DotNetOpenAuth/InfoCard/Token/TokenDecryptor.cs | 10 |
4 files changed, 98 insertions, 24 deletions
diff --git a/src/DotNetOpenAuth/InfoCard/InfoCardSelector.cs b/src/DotNetOpenAuth/InfoCard/InfoCardSelector.cs index 48f0100..b787300 100644 --- a/src/DotNetOpenAuth/InfoCard/InfoCardSelector.cs +++ b/src/DotNetOpenAuth/InfoCard/InfoCardSelector.cs @@ -387,12 +387,11 @@ namespace DotNetOpenAuth.InfoCard { if (!string.IsNullOrEmpty(this.TokenXml)) { try { bool encrypted = Token.IsEncrypted(this.TokenXml); - TokenDecryptor decryptor = encrypted ? new TokenDecryptor() : null; - ReceivingTokenEventArgs receivingArgs = this.OnReceivingToken(this.TokenXml, decryptor); + ReceivingTokenEventArgs receivingArgs = this.OnReceivingToken(this.TokenXml); if (!receivingArgs.Cancel) { try { - Token token = new Token(this.TokenXml, this.Audience, decryptor); + Token token = Token.Read(this.TokenXml, this.Audience, receivingArgs.DecryptingTokens); this.OnReceivedToken(token); } catch (InformationCardException ex) { this.OnTokenProcessingError(this.TokenXml, ex); @@ -408,14 +407,13 @@ namespace DotNetOpenAuth.InfoCard { /// Fires the <see cref="ReceivingToken"/> event. /// </summary> /// <param name="tokenXml">The token XML, prior to any processing.</param> - /// <param name="decryptor">The decryptor to use, if the token is encrypted.</param> /// <returns>The event arguments sent to the event handlers.</returns> [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "decryptor", Justification = "By design")] - protected virtual ReceivingTokenEventArgs OnReceivingToken(string tokenXml, TokenDecryptor decryptor) { + protected virtual ReceivingTokenEventArgs OnReceivingToken(string tokenXml) { Contract.Requires(tokenXml != null); ErrorUtilities.VerifyArgumentNotNull(tokenXml, "tokenXml"); - var args = new ReceivingTokenEventArgs(tokenXml, decryptor); + var args = new ReceivingTokenEventArgs(tokenXml); var receivingToken = this.ReceivingToken; if (receivingToken != null) { receivingToken(this, args); diff --git a/src/DotNetOpenAuth/InfoCard/ReceivingTokenEventArgs.cs b/src/DotNetOpenAuth/InfoCard/ReceivingTokenEventArgs.cs index 004d134..f3722d7 100644 --- a/src/DotNetOpenAuth/InfoCard/ReceivingTokenEventArgs.cs +++ b/src/DotNetOpenAuth/InfoCard/ReceivingTokenEventArgs.cs @@ -6,8 +6,11 @@ namespace DotNetOpenAuth.InfoCard { using System; + using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Contracts; + using System.IdentityModel.Tokens; + using System.Security.Cryptography.X509Certificates; /// <summary> /// Arguments for the <see cref="InfoCardSelector.ReceivingToken"/> event. @@ -17,13 +20,12 @@ namespace DotNetOpenAuth.InfoCard { /// Initializes a new instance of the <see cref="ReceivingTokenEventArgs"/> class. /// </summary> /// <param name="tokenXml">The raw token XML, prior to any decryption.</param> - /// <param name="decryptor">The decryptor to use if the token is encrypted.</param> - internal ReceivingTokenEventArgs(string tokenXml, TokenDecryptor decryptor) { + internal ReceivingTokenEventArgs(string tokenXml) { Contract.Requires(tokenXml != null); this.TokenXml = tokenXml; this.IsEncrypted = Token.IsEncrypted(this.TokenXml); - this.Decryptor = decryptor; + this.DecryptingTokens = new List<SecurityToken>(); } /// <summary> @@ -40,13 +42,6 @@ namespace DotNetOpenAuth.InfoCard { public string TokenXml { get; private set; } /// <summary> - /// Gets the object that will perform token decryption, if necessary. - /// </summary> - /// <value>The decryptor to use; or <c>null</c> if the token is not encrypted.</value> - [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Decryptor", Justification = "By design")] - public TokenDecryptor Decryptor { get; private set; } - - /// <summary> /// Gets or sets a value indicating whether processing /// this token should be canceled. /// </summary> @@ -57,6 +52,31 @@ namespace DotNetOpenAuth.InfoCard { /// </remarks> public bool Cancel { get; set; } + /// <summary> + /// Gets a list where security tokens such as X.509 certificates may be + /// added to be used for token decryption. + /// </summary> + internal IList<SecurityToken> DecryptingTokens { get; private set; } + + /// <summary> + /// Adds a security token that may be used to decrypt the incoming token. + /// </summary> + /// <param name="securityToken">The security token.</param> + public void AddDecryptingToken(SecurityToken securityToken) { + Contract.Requires(securityToken != null); + this.DecryptingTokens.Add(securityToken); + } + + /// <summary> + /// Adds an X.509 certificate with a private key that may be used to decrypt the incoming token. + /// </summary> + /// <param name="certificate">The certificate.</param> + public void AddDecryptingToken(X509Certificate2 certificate) { + Contract.Requires(certificate != null); + Contract.Requires(certificate.HasPrivateKey); + this.AddDecryptingToken(new X509SecurityToken(certificate)); + } + #if CONTRACTS_FULL /// <summary> /// Verifies conditions that should be true for any valid state of this object. @@ -65,7 +85,7 @@ namespace DotNetOpenAuth.InfoCard { [ContractInvariantMethod] protected void ObjectInvariant() { Contract.Invariant(this.TokenXml != null); - Contract.Invariant((this.Decryptor != null) == this.IsEncrypted); + Contract.Invariant(this.DecryptingTokens != null); } #endif } diff --git a/src/DotNetOpenAuth/InfoCard/Token/Token.cs b/src/DotNetOpenAuth/InfoCard/Token/Token.cs index d72b47a..f07c555 100644 --- a/src/DotNetOpenAuth/InfoCard/Token/Token.cs +++ b/src/DotNetOpenAuth/InfoCard/Token/Token.cs @@ -11,8 +11,9 @@ namespace DotNetOpenAuth.InfoCard { using System.Diagnostics.Contracts; using System.IdentityModel.Claims; using System.IdentityModel.Policy; + using System.IdentityModel.Tokens; using System.IO; - using System.Security.Cryptography.X509Certificates; + using System.Linq; using System.Text; using System.Xml; using System.Xml.XPath; @@ -40,7 +41,7 @@ namespace DotNetOpenAuth.InfoCard { /// <param name="audience">The audience. May be <c>null</c> to avoid audience checking.</param> /// <param name="decryptor">The decryptor to use to decrypt the token, if necessary..</param> /// <exception cref="InformationCardException">Thrown for any problem decoding or decrypting the token.</exception> - internal Token(string tokenXml, Uri audience, TokenDecryptor decryptor) { + private Token(string tokenXml, Uri audience, TokenDecryptor decryptor) { Contract.Requires(tokenXml != null && tokenXml.Length > 0); Contract.Requires(decryptor != null || !IsEncrypted(tokenXml)); ErrorUtilities.VerifyNonZeroLength(tokenXml, "tokenXml"); @@ -125,6 +126,61 @@ namespace DotNetOpenAuth.InfoCard { } /// <summary> + /// Deserializes an XML document into a token. + /// </summary> + /// <param name="tokenXml">The token XML.</param> + /// <returns>The deserialized token.</returns> + public static Token Read(string tokenXml) { + Contract.Requires(!String.IsNullOrEmpty(tokenXml)); + return Read(tokenXml, (Uri)null); + } + + /// <summary> + /// Deserializes an XML document into a token. + /// </summary> + /// <param name="tokenXml">The token XML.</param> + /// <param name="audience">The URI that this token must have been crafted to be sent to. Use <c>null</c> to accept any intended audience.</param> + /// <returns>The deserialized token.</returns> + public static Token Read(string tokenXml, Uri audience) { + Contract.Requires(!String.IsNullOrEmpty(tokenXml)); + return Read(tokenXml, audience, Enumerable.Empty<SecurityToken>()); + } + + /// <summary> + /// Deserializes an XML document into a token. + /// </summary> + /// <param name="tokenXml">The token XML.</param> + /// <param name="decryptionTokens">Any X.509 certificates that may be used to decrypt the token, if necessary.</param> + /// <returns>The deserialized token.</returns> + public static Token Read(string tokenXml, IEnumerable<SecurityToken> decryptionTokens) { + Contract.Requires(!String.IsNullOrEmpty(tokenXml)); + Contract.Requires(decryptionTokens != null); + return Read(tokenXml, null, decryptionTokens); + } + + /// <summary> + /// Deserializes an XML document into a token. + /// </summary> + /// <param name="tokenXml">The token XML.</param> + /// <param name="audience">The URI that this token must have been crafted to be sent to. Use <c>null</c> to accept any intended audience.</param> + /// <param name="decryptionTokens">Any X.509 certificates that may be used to decrypt the token, if necessary.</param> + /// <returns>The deserialized token.</returns> + public static Token Read(string tokenXml, Uri audience, IEnumerable<SecurityToken> decryptionTokens) { + Contract.Requires(!String.IsNullOrEmpty(tokenXml)); + Contract.Requires(decryptionTokens != null); + Contract.Ensures(Contract.Result<Token>() != null); + + TokenDecryptor decryptor = null; + + if (IsEncrypted(tokenXml)) { + decryptor = new TokenDecryptor(); + decryptor.Tokens.AddRange(decryptionTokens); + } + + return new Token(tokenXml, audience, decryptor); + } + + /// <summary> /// Determines whether the specified token XML is encrypted. /// </summary> /// <param name="tokenXml">The token XML.</param> diff --git a/src/DotNetOpenAuth/InfoCard/Token/TokenDecryptor.cs b/src/DotNetOpenAuth/InfoCard/Token/TokenDecryptor.cs index 5d1be94..1038ad7 100644 --- a/src/DotNetOpenAuth/InfoCard/Token/TokenDecryptor.cs +++ b/src/DotNetOpenAuth/InfoCard/Token/TokenDecryptor.cs @@ -27,7 +27,7 @@ namespace DotNetOpenAuth.InfoCard { /// A utility class for decrypting InfoCard tokens. /// </summary> [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Decryptor", Justification = "By design")] - public class TokenDecryptor { + internal class TokenDecryptor { /// <summary> /// Backing field for the <see cref="Tokens"/> property. /// </summary> @@ -49,7 +49,7 @@ namespace DotNetOpenAuth.InfoCard { /// <remarks> /// Defaults to localmachine:my (same place SSL certs are) /// </remarks> - public IList<SecurityToken> Tokens { + internal List<SecurityToken> Tokens { get { return this.tokens; } } @@ -57,7 +57,7 @@ namespace DotNetOpenAuth.InfoCard { /// Adds a certificate to the list of certificates to decrypt with. /// </summary> /// <param name="certificate">The x509 cert to use for decryption</param> - public void AddDecryptionCertificate(X509Certificate2 certificate) { + internal void AddDecryptionCertificate(X509Certificate2 certificate) { this.Tokens.Add(new X509SecurityToken(certificate)); } @@ -67,7 +67,7 @@ namespace DotNetOpenAuth.InfoCard { /// <param name="storeName">store name of the certificate</param> /// <param name="storeLocation">store location</param> /// <param name="thumbprint">thumbprint of the cert to use</param> - public void AddDecryptionCertificate(StoreName storeName, StoreLocation storeLocation, string thumbprint) { + internal void AddDecryptionCertificate(StoreName storeName, StoreLocation storeLocation, string thumbprint) { this.AddDecryptionCertificates( storeName, storeLocation, @@ -79,7 +79,7 @@ namespace DotNetOpenAuth.InfoCard { /// </summary> /// <param name="storeName">store name of the certificates</param> /// <param name="storeLocation">store location</param> - public void AddDecryptionCertificates(StoreName storeName, StoreLocation storeLocation) { + internal void AddDecryptionCertificates(StoreName storeName, StoreLocation storeLocation) { this.AddDecryptionCertificates(storeName, storeLocation, store => store); } |