summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2010-02-13 06:10:55 -0800
committerAndrew Arnott <andrewarnott@gmail.com>2010-02-13 06:10:55 -0800
commit66e2b799c300cd6af3a42d4c4b297718a9f79f04 (patch)
treeb356864526ae31a54106de161e994dbf6ce9fc4c /src
parent982a8ac73e6fa9f178a0fb15d9e04c91515c3e49 (diff)
parent09398b5febaef7834f2dc822161dc73995439c7e (diff)
downloadDotNetOpenAuth-66e2b799c300cd6af3a42d4c4b297718a9f79f04.zip
DotNetOpenAuth-66e2b799c300cd6af3a42d4c4b297718a9f79f04.tar.gz
DotNetOpenAuth-66e2b799c300cd6af3a42d4c4b297718a9f79f04.tar.bz2
Merge branch 'v3.3' into v3.4
Conflicts: lib/DotNetOpenAuth.BuildTasks.dll lib/DotNetOpenAuth.BuildTasks.pdb
Diffstat (limited to 'src')
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs1
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/OutgoingWebResponseTests.cs4
-rw-r--r--src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd8
-rw-r--r--src/DotNetOpenAuth/Configuration/DotNetOpenAuthSection.cs45
-rw-r--r--src/DotNetOpenAuth/Messaging/Channel.cs16
-rw-r--r--src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs4
-rw-r--r--src/DotNetOpenAuth/Messaging/MessagingUtilities.cs12
-rw-r--r--src/DotNetOpenAuth/Messaging/OutgoingWebResponse.cs17
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs10
-rw-r--r--src/DotNetOpenAuth/OAuth/ConsumerBase.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeRequest.cs1
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeValues.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchRequest.cs6
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchResponse.cs6
-rw-r--r--src/DotNetOpenAuth/OpenId/Identifier.cs7
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/ProviderEndpoint.cs41
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs5
17 files changed, 145 insertions, 42 deletions
diff --git a/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs b/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs
index 8a8ae25..2b0e8f9 100644
--- a/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs
@@ -153,6 +153,7 @@ namespace DotNetOpenAuth.Test.Messaging
Match m = Regex.Match(req.ContentType, "multipart/form-data; boundary=(.+)");
Assert.IsTrue(m.Success, "Content-Type HTTP header not set correctly.");
string boundary = m.Groups[1].Value;
+ boundary = boundary.Substring(0, boundary.IndexOf(';')); // trim off charset
string expectedEntity = "--{0}\r\nContent-Disposition: form-data; name=\"a\"\r\n\r\nb\r\n--{0}--\r\n";
expectedEntity = string.Format(expectedEntity, boundary);
string actualEntity = httpHandler.RequestEntityAsString;
diff --git a/src/DotNetOpenAuth.Test/Messaging/OutgoingWebResponseTests.cs b/src/DotNetOpenAuth.Test/Messaging/OutgoingWebResponseTests.cs
index 16576d6..10045de 100644
--- a/src/DotNetOpenAuth.Test/Messaging/OutgoingWebResponseTests.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/OutgoingWebResponseTests.cs
@@ -6,6 +6,7 @@
namespace DotNetOpenAuth.Test.Messaging {
using System.Net;
+ using System.Net.Mime;
using System.Text;
using DotNetOpenAuth.Messaging;
using NUnit.Framework;
@@ -30,7 +31,8 @@ namespace DotNetOpenAuth.Test.Messaging {
CollectionAssert.AreEqual(expectedBuffer, actualBuffer);
// Verify that the header was set correctly.
- Assert.AreEqual(encoding.HeaderName, response.Headers[HttpResponseHeader.ContentEncoding]);
+ Assert.IsNull(response.Headers[HttpResponseHeader.ContentEncoding]);
+ Assert.AreEqual(encoding.HeaderName, new ContentType(response.Headers[HttpResponseHeader.ContentType]).CharSet);
}
}
}
diff --git a/src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd b/src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd
index 18e1c5c..a9c5965 100644
--- a/src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd
+++ b/src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd
@@ -658,6 +658,14 @@
</xs:documentation>
</xs:annotation>
</xs:attribute>
+ <xs:attribute name="cacheDiscovery" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation>
+ Whether the results of identifier discovery should be cached for a short time to improve performance
+ on subsequent requests, at the potential risk of reading stale data.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="oauth">
diff --git a/src/DotNetOpenAuth/Configuration/DotNetOpenAuthSection.cs b/src/DotNetOpenAuth/Configuration/DotNetOpenAuthSection.cs
index aa956d1..117a542 100644
--- a/src/DotNetOpenAuth/Configuration/DotNetOpenAuthSection.cs
+++ b/src/DotNetOpenAuth/Configuration/DotNetOpenAuthSection.cs
@@ -51,7 +51,10 @@ namespace DotNetOpenAuth.Configuration {
/// Gets the configuration section from the .config file.
/// </summary>
public static DotNetOpenAuthSection Configuration {
- get { return (DotNetOpenAuthSection)ConfigurationManager.GetSection(SectionName) ?? new DotNetOpenAuthSection(); }
+ get {
+ Contract.Ensures(Contract.Result<DotNetOpenAuthSection>() != null);
+ return (DotNetOpenAuthSection)ConfigurationManager.GetSection(SectionName) ?? new DotNetOpenAuthSection();
+ }
}
/// <summary>
@@ -59,8 +62,14 @@ namespace DotNetOpenAuth.Configuration {
/// </summary>
[ConfigurationProperty(MessagingElementName)]
public MessagingElement Messaging {
- get { return (MessagingElement)this[MessagingElementName] ?? new MessagingElement(); }
- set { this[MessagingElementName] = value; }
+ get {
+ Contract.Ensures(Contract.Result<MessagingElement>() != null);
+ return (MessagingElement)this[MessagingElementName] ?? new MessagingElement();
+ }
+
+ set {
+ this[MessagingElementName] = value;
+ }
}
/// <summary>
@@ -68,8 +77,14 @@ namespace DotNetOpenAuth.Configuration {
/// </summary>
[ConfigurationProperty(OpenIdElementName)]
internal OpenIdElement OpenId {
- get { return (OpenIdElement)this[OpenIdElementName] ?? new OpenIdElement(); }
- set { this[OpenIdElementName] = value; }
+ get {
+ Contract.Ensures(Contract.Result<OpenIdElement>() != null);
+ return (OpenIdElement)this[OpenIdElementName] ?? new OpenIdElement();
+ }
+
+ set {
+ this[OpenIdElementName] = value;
+ }
}
/// <summary>
@@ -77,8 +92,14 @@ namespace DotNetOpenAuth.Configuration {
/// </summary>
[ConfigurationProperty(OAuthElementName)]
internal OAuthElement OAuth {
- get { return (OAuthElement)this[OAuthElementName] ?? new OAuthElement(); }
- set { this[OAuthElementName] = value; }
+ get {
+ Contract.Ensures(Contract.Result<OAuthElement>() != null);
+ return (OAuthElement)this[OAuthElementName] ?? new OAuthElement();
+ }
+
+ set {
+ this[OAuthElementName] = value;
+ }
}
/// <summary>
@@ -86,8 +107,14 @@ namespace DotNetOpenAuth.Configuration {
/// </summary>
[ConfigurationProperty(ReportingElementName)]
internal ReportingElement Reporting {
- get { return (ReportingElement)this[ReportingElementName] ?? new ReportingElement(); }
- set { this[ReportingElementName] = value; }
+ get {
+ Contract.Ensures(Contract.Result<ReportingElement>() != null);
+ return (ReportingElement)this[ReportingElementName] ?? new ReportingElement();
+ }
+
+ set {
+ this[ReportingElementName] = value;
+ }
}
}
}
diff --git a/src/DotNetOpenAuth/Messaging/Channel.cs b/src/DotNetOpenAuth/Messaging/Channel.cs
index 1bddf02..7198c78 100644
--- a/src/DotNetOpenAuth/Messaging/Channel.cs
+++ b/src/DotNetOpenAuth/Messaging/Channel.cs
@@ -16,6 +16,7 @@ namespace DotNetOpenAuth.Messaging {
using System.Linq;
using System.Net;
using System.Net.Cache;
+ using System.Net.Mime;
using System.Text;
using System.Threading;
using System.Web;
@@ -39,6 +40,13 @@ namespace DotNetOpenAuth.Messaging {
protected internal const string HttpFormUrlEncoded = "application/x-www-form-urlencoded";
/// <summary>
+ /// The content-type used on HTTP POST requests where the POST entity is a
+ /// URL-encoded series of key=value pairs.
+ /// This includes the <see cref="PostEntityEncoding"/> character encoding.
+ /// </summary>
+ protected internal static readonly ContentType HttpFormUrlEncodedContentType = new ContentType(HttpFormUrlEncoded) { CharSet = PostEntityEncoding.WebName };
+
+ /// <summary>
/// The maximum allowable size for a 301 Redirect response before we send
/// a 200 OK response with a scripted form POST with the parameters instead
/// in order to ensure successfully sending a large payload to another server
@@ -927,15 +935,9 @@ namespace DotNetOpenAuth.Messaging {
Contract.Requires<ArgumentNullException>(httpRequest != null);
Contract.Requires<ArgumentNullException>(fields != null);
- httpRequest.ContentType = HttpFormUrlEncoded;
-
- // Setting the content-encoding to "utf-8" causes Google to reply
- // with a 415 UnsupportedMediaType. But adding it doesn't buy us
- // anything specific, so we disable it until we know how to get it right.
- ////httpRequest.Headers[HttpRequestHeader.ContentEncoding] = PostEntityEncoding.WebName;
-
string requestBody = MessagingUtilities.CreateQueryString(fields);
byte[] requestBytes = PostEntityEncoding.GetBytes(requestBody);
+ httpRequest.ContentType = HttpFormUrlEncodedContentType.ToString();
httpRequest.ContentLength = requestBytes.Length;
Stream requestStream = this.WebRequestHandler.GetRequestStream(httpRequest);
try {
diff --git a/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs b/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs
index 94990c8..6ce87a8 100644
--- a/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs
+++ b/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs
@@ -13,6 +13,7 @@ namespace DotNetOpenAuth.Messaging {
using System.Globalization;
using System.IO;
using System.Net;
+ using System.Net.Mime;
using System.ServiceModel.Channels;
using System.Web;
@@ -233,7 +234,8 @@ namespace DotNetOpenAuth.Messaging {
get {
Contract.Ensures(Contract.Result<NameValueCollection>() != null);
if (this.form == null) {
- if (this.HttpMethod == "POST" && this.Headers[HttpRequestHeader.ContentType] == Channel.HttpFormUrlEncoded) {
+ ContentType contentType = string.IsNullOrEmpty(this.Headers[HttpRequestHeader.ContentType]) ? null : new ContentType(this.Headers[HttpRequestHeader.ContentType]);
+ if (this.HttpMethod == "POST" && contentType != null && string.Equals(contentType.MediaType, Channel.HttpFormUrlEncoded, StringComparison.Ordinal)) {
StreamReader reader = new StreamReader(this.InputStream);
long originalPosition = 0;
if (this.InputStream.CanSeek) {
diff --git a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
index 81b33b0..a52f51b 100644
--- a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
+++ b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
@@ -14,6 +14,7 @@ namespace DotNetOpenAuth.Messaging {
using System.IO;
using System.Linq;
using System.Net;
+ using System.Net.Mime;
using System.Security;
using System.Security.Cryptography;
using System.Text;
@@ -191,20 +192,19 @@ namespace DotNetOpenAuth.Messaging {
string initialPartLeadingBoundary = string.Format(CultureInfo.InvariantCulture, "--{0}\r\n", boundary);
string partLeadingBoundary = string.Format(CultureInfo.InvariantCulture, "\r\n--{0}\r\n", boundary);
string finalTrailingBoundary = string.Format(CultureInfo.InvariantCulture, "\r\n--{0}--\r\n", boundary);
+ var contentType = new ContentType("multipart/form-data") {
+ Boundary = boundary,
+ CharSet = Channel.PostEntityEncoding.WebName,
+ };
request.Method = "POST";
- request.ContentType = "multipart/form-data; boundary=" + boundary;
+ request.ContentType = contentType.ToString();
long contentLength = parts.Sum(p => partLeadingBoundary.Length + p.Length) + finalTrailingBoundary.Length;
if (parts.Any()) {
contentLength -= 2; // the initial part leading boundary has no leading \r\n
}
request.ContentLength = contentLength;
- // Setting the content-encoding to "utf-8" causes Google to reply
- // with a 415 UnsupportedMediaType. But adding it doesn't buy us
- // anything specific, so we disable it until we know how to get it right.
- ////request.Headers[HttpRequestHeader.ContentEncoding] = Channel.PostEntityEncoding.WebName;
-
var requestStream = requestHandler.GetRequestStream(request);
try {
StreamWriter writer = new StreamWriter(requestStream, Channel.PostEntityEncoding);
diff --git a/src/DotNetOpenAuth/Messaging/OutgoingWebResponse.cs b/src/DotNetOpenAuth/Messaging/OutgoingWebResponse.cs
index 52d0e39..cf22bb2 100644
--- a/src/DotNetOpenAuth/Messaging/OutgoingWebResponse.cs
+++ b/src/DotNetOpenAuth/Messaging/OutgoingWebResponse.cs
@@ -10,6 +10,7 @@ namespace DotNetOpenAuth.Messaging {
using System.Diagnostics.Contracts;
using System.IO;
using System.Net;
+ using System.Net.Mime;
using System.Text;
using System.Threading;
using System.Web;
@@ -87,7 +88,7 @@ namespace DotNetOpenAuth.Messaging {
/// </summary>
public string Body {
get { return this.ResponseStream != null ? this.GetResponseReader().ReadToEnd() : null; }
- set { this.SetResponse(value); }
+ set { this.SetResponse(value, null); }
}
/// <summary>
@@ -205,13 +206,23 @@ namespace DotNetOpenAuth.Messaging {
/// Sets the response to some string, encoded as UTF-8.
/// </summary>
/// <param name="body">The string to set the response to.</param>
- internal void SetResponse(string body) {
+ /// <param name="contentType">Type of the content. May be null.</param>
+ internal void SetResponse(string body, ContentType contentType) {
if (body == null) {
this.ResponseStream = null;
return;
}
- this.Headers[HttpResponseHeader.ContentEncoding] = bodyStringEncoder.HeaderName;
+ if (contentType == null) {
+ contentType = new ContentType("text/html");
+ contentType.CharSet = bodyStringEncoder.WebName;
+ } else if (contentType.CharSet != bodyStringEncoder.WebName) {
+ // clone the original so we're not tampering with our inputs if it came as a parameter.
+ contentType = new ContentType(contentType.ToString());
+ contentType.CharSet = bodyStringEncoder.WebName;
+ }
+
+ this.Headers[HttpResponseHeader.ContentType] = contentType.ToString();
this.ResponseStream = new MemoryStream();
StreamWriter writer = new StreamWriter(this.ResponseStream, bodyStringEncoder);
writer.Write(body);
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs
index b0e938f..ed41183 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs
@@ -13,6 +13,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
using System.IO;
using System.Linq;
using System.Net;
+ using System.Net.Mime;
using System.Text;
using System.Web;
using DotNetOpenAuth.Messaging;
@@ -141,9 +142,12 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
}
// Scrape the entity
- if (string.Equals(request.Headers[HttpRequestHeader.ContentType], HttpFormUrlEncoded, StringComparison.Ordinal)) {
- foreach (string key in request.Form) {
- fields.Add(key, request.Form[key]);
+ if (!string.IsNullOrEmpty(request.Headers[HttpRequestHeader.ContentType])) {
+ ContentType contentType = new ContentType(request.Headers[HttpRequestHeader.ContentType]);
+ if (string.Equals(contentType.MediaType, HttpFormUrlEncoded, StringComparison.Ordinal)) {
+ foreach (string key in request.Form) {
+ fields.Add(key, request.Form[key]);
+ }
}
}
diff --git a/src/DotNetOpenAuth/OAuth/ConsumerBase.cs b/src/DotNetOpenAuth/OAuth/ConsumerBase.cs
index 48f54d7..dddbe9e 100644
--- a/src/DotNetOpenAuth/OAuth/ConsumerBase.cs
+++ b/src/DotNetOpenAuth/OAuth/ConsumerBase.cs
@@ -224,7 +224,7 @@ namespace DotNetOpenAuth.OAuth {
// Fine-tune our understanding of the SP's supported OAuth version if it's wrong.
if (this.ServiceProvider.Version != requestTokenResponse.Version) {
- Logger.OAuth.WarnFormat("Expected OAuth service provider at endpoint {0} to use OAuth {1} but {2} was detected. Adjusting service description to new version.", this.ServiceProvider.RequestTokenEndpoint, this.ServiceProvider.Version, requestTokenResponse.Version);
+ Logger.OAuth.WarnFormat("Expected OAuth service provider at endpoint {0} to use OAuth {1} but {2} was detected. Adjusting service description to new version.", this.ServiceProvider.RequestTokenEndpoint.Location, this.ServiceProvider.Version, requestTokenResponse.Version);
this.ServiceProvider.ProtocolVersion = Protocol.Lookup(requestTokenResponse.Version).ProtocolVersion;
}
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeRequest.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeRequest.cs
index 358db9b..2dc9c69 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeRequest.cs
@@ -15,6 +15,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
/// the Attribute Exchange extension.
/// </summary>
[Serializable]
+ [DebuggerDisplay("{TypeUri} (required: {IsRequired}) ({Count})")]
public class AttributeRequest {
/// <summary>
/// Backing field for the <see cref="Count"/> property.
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeValues.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeValues.cs
index 6466cda..b2fc1fe 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeValues.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeValues.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
using System;
using System.Collections.Generic;
+ using System.Diagnostics;
using System.Diagnostics.Contracts;
using DotNetOpenAuth.Messaging;
@@ -16,6 +17,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
/// a fetch request, or by a relying party as part of a store request.
/// </summary>
[Serializable]
+ [DebuggerDisplay("{TypeUri}")]
public class AttributeValues {
/// <summary>
/// Initializes a new instance of the <see cref="AttributeValues"/> class.
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchRequest.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchRequest.cs
index a69e226..124a18c 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchRequest.cs
@@ -8,6 +8,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
+ using System.Diagnostics.Contracts;
using System.Globalization;
using System.Linq;
using DotNetOpenAuth.Messaging;
@@ -67,7 +68,10 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
/// <value>A collection where the keys are the attribute type URIs, and the value
/// is all the attribute request details.</value>
public KeyedCollection<string, AttributeRequest> Attributes {
- get { return this.attributes; }
+ get {
+ Contract.Ensures(Contract.Result<KeyedCollection<string, AttributeRequest>>() != null);
+ return this.attributes;
+ }
}
/// <summary>
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchResponse.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchResponse.cs
index 758b20c..14b1caa 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchResponse.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
using System;
using System.Collections.ObjectModel;
+ using System.Diagnostics.Contracts;
using System.Linq;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.Messages;
@@ -52,7 +53,10 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
/// Gets a sequence of the attributes whose values are provided by the OpenID Provider.
/// </summary>
public KeyedCollection<string, AttributeValues> Attributes {
- get { return this.attributesProvided; }
+ get {
+ Contract.Ensures(Contract.Result<KeyedCollection<string, AttributeValues>>() != null);
+ return this.attributesProvided;
+ }
}
/// <summary>
diff --git a/src/DotNetOpenAuth/OpenId/Identifier.cs b/src/DotNetOpenAuth/OpenId/Identifier.cs
index 548a673..2ab5360 100644
--- a/src/DotNetOpenAuth/OpenId/Identifier.cs
+++ b/src/DotNetOpenAuth/OpenId/Identifier.cs
@@ -68,6 +68,8 @@ namespace DotNetOpenAuth.OpenId {
[DebuggerStepThrough]
public static implicit operator Identifier(string identifier) {
Contract.Requires<ArgumentException>(identifier == null || identifier.Length > 0);
+ Contract.Ensures((identifier == null) == (Contract.Result<Identifier>() == null));
+
if (identifier == null) {
return null;
}
@@ -82,6 +84,7 @@ namespace DotNetOpenAuth.OpenId {
[SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "We have a Parse function.")]
[DebuggerStepThrough]
public static implicit operator Identifier(Uri identifier) {
+ Contract.Ensures((identifier == null) == (Contract.Result<Identifier>() == null));
if (identifier == null) {
return null;
}
@@ -97,7 +100,7 @@ namespace DotNetOpenAuth.OpenId {
[SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "We have a Parse function.")]
[DebuggerStepThrough]
public static implicit operator string(Identifier identifier) {
- Contract.Ensures((identifier == null && Contract.Result<string>() == null) || (identifier != null && Contract.Result<string>() != null));
+ Contract.Ensures((identifier == null) == (Contract.Result<string>() == null));
if (identifier == null) {
return null;
}
@@ -113,6 +116,8 @@ namespace DotNetOpenAuth.OpenId {
[SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "Some of these identifiers are not properly formatted to be Uris at this stage.")]
public static Identifier Parse(string identifier) {
Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(identifier));
+ Contract.Ensures(Contract.Result<Identifier>() != null);
+
if (XriIdentifier.IsValidXri(identifier)) {
return new XriIdentifier(identifier);
} else {
diff --git a/src/DotNetOpenAuth/OpenId/Provider/ProviderEndpoint.cs b/src/DotNetOpenAuth/OpenId/Provider/ProviderEndpoint.cs
index f778b76..445978e 100644
--- a/src/DotNetOpenAuth/OpenId/Provider/ProviderEndpoint.cs
+++ b/src/DotNetOpenAuth/OpenId/Provider/ProviderEndpoint.cs
@@ -43,7 +43,12 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// <summary>
/// Backing field for the <see cref="Provider"/> property.
/// </summary>
- private static OpenIdProvider provider = CreateProvider();
+ private static OpenIdProvider provider;
+
+ /// <summary>
+ /// The lock that must be obtained when initializing the provider field.
+ /// </summary>
+ private static object providerInitializerLock = new object();
/// <summary>
/// Fired when an incoming OpenID request is an authentication challenge
@@ -64,6 +69,15 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// <value>The default value is an <see cref="OpenIdProvider"/> instance initialized according to the web.config file.</value>
public static OpenIdProvider Provider {
get {
+ Contract.Ensures(Contract.Result<OpenIdProvider>() != null);
+ if (provider == null) {
+ lock (providerInitializerLock) {
+ if (provider == null) {
+ provider = CreateProvider();
+ }
+ }
+ }
+
return provider;
}
@@ -83,8 +97,14 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// before responding to the relying party's authentication request.
/// </remarks>
public static IAuthenticationRequest PendingAuthenticationRequest {
- get { return HttpContext.Current.Session[PendingRequestKey] as IAuthenticationRequest; }
- set { HttpContext.Current.Session[PendingRequestKey] = value; }
+ get {
+ Contract.Ensures(Contract.Result<IAuthenticationRequest>() == null || PendingRequest != null);
+ return HttpContext.Current.Session[PendingRequestKey] as IAuthenticationRequest;
+ }
+
+ set {
+ HttpContext.Current.Session[PendingRequestKey] = value;
+ }
}
/// <summary>
@@ -97,8 +117,14 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// before responding to the relying party's request.
/// </remarks>
public static IAnonymousRequest PendingAnonymousRequest {
- get { return HttpContext.Current.Session[PendingRequestKey] as IAnonymousRequest; }
- set { HttpContext.Current.Session[PendingRequestKey] = value; }
+ get {
+ Contract.Ensures(Contract.Result<IAnonymousRequest>() == null || PendingRequest != null);
+ return HttpContext.Current.Session[PendingRequestKey] as IAnonymousRequest;
+ }
+
+ set {
+ HttpContext.Current.Session[PendingRequestKey] = value;
+ }
}
/// <summary>
@@ -159,7 +185,7 @@ namespace DotNetOpenAuth.OpenId.Provider {
// Then try the configuration file specified one. Finally, use the default
// in-memory one that's built into OpenIdProvider.
// determine what incoming message was received
- IRequest request = provider.GetRequest();
+ IRequest request = Provider.GetRequest();
if (request != null) {
PendingRequest = null;
@@ -179,7 +205,7 @@ namespace DotNetOpenAuth.OpenId.Provider {
}
}
if (request.IsResponseReady) {
- provider.SendResponse(request);
+ Provider.SendResponse(request);
Page.Response.End();
PendingAuthenticationRequest = null;
}
@@ -218,6 +244,7 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// </summary>
/// <returns>The new instance of OpenIdProvider.</returns>
private static OpenIdProvider CreateProvider() {
+ Contract.Ensures(Contract.Result<OpenIdProvider>() != null);
return new OpenIdProvider(DotNetOpenAuthSection.Configuration.OpenId.Provider.ApplicationStore.CreateInstance(OpenIdProvider.HttpApplicationStore));
}
}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
index c9106de..a0a0fb9 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
@@ -109,7 +109,10 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
// replay attacks. But only 2.0+ Providers can be expected to provide
// replay protection.
if (nonceStore == null) {
- this.SecuritySettings.MinimumRequiredOpenIdVersion = ProtocolVersion.V20;
+ if (this.SecuritySettings.MinimumRequiredOpenIdVersion < ProtocolVersion.V20) {
+ Logger.OpenId.Warn("Raising minimum OpenID version requirement for Providers to 2.0 to protect this stateless RP from replay attacks.");
+ this.SecuritySettings.MinimumRequiredOpenIdVersion = ProtocolVersion.V20;
+ }
}
this.channel = new OpenIdChannel(associationStore, nonceStore, this.SecuritySettings);