diff options
Diffstat (limited to 'src')
7 files changed, 53 insertions, 19 deletions
diff --git a/src/DotNetOpenAuth/OAuthWrap/ChannelElements/OAuthWrapAuthorizationServerChannel.cs b/src/DotNetOpenAuth/OAuthWrap/ChannelElements/OAuthWrapAuthorizationServerChannel.cs index f286e4d..336f582 100644 --- a/src/DotNetOpenAuth/OAuthWrap/ChannelElements/OAuthWrapAuthorizationServerChannel.cs +++ b/src/DotNetOpenAuth/OAuthWrap/ChannelElements/OAuthWrapAuthorizationServerChannel.cs @@ -4,19 +4,20 @@ // </copyright> //----------------------------------------------------------------------- -using DotNetOpenAuth.Messaging.Bindings; -using DotNetOpenAuth.OAuthWrap.Messages; - namespace DotNetOpenAuth.OAuthWrap.ChannelElements { using System; using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Linq; using System.Net; + using System.Net.Mime; using System.Text; using System.Web; + using System.Web.Script.Serialization; using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.Messaging.Bindings; using DotNetOpenAuth.Messaging.Reflection; + using DotNetOpenAuth.OAuthWrap.Messages; /// <summary> /// The channel for the OAuth WRAP protocol. @@ -109,10 +110,11 @@ namespace DotNetOpenAuth.OAuthWrap.ChannelElements { /// <exception cref="ProtocolException">Thrown when the response is not valid.</exception> protected override IDictionary<string, string> ReadFromResponseCore(IncomingWebResponse response) { // The spec says direct responses should be JSON objects, but Facebook uses HttpFormUrlEncoded instead, calling it text/plain + string body = response.GetResponseReader().ReadToEnd(); if (response.ContentType.MediaType == JsonEncoded) { - throw new NotImplementedException(); + var jsonSerializer = new JavaScriptSerializer(); + return jsonSerializer.Deserialize<Dictionary<string, string>>(body); } else if (response.ContentType.MediaType == HttpFormUrlEncoded || response.ContentType.MediaType == PlainTextEncoded) { - string body = response.GetResponseReader().ReadToEnd(); return HttpUtility.ParseQueryString(body).ToDictionary(); } else { throw ErrorUtilities.ThrowProtocol("Unexpected response Content-Type {0}", response.ContentType.MediaType); @@ -131,23 +133,32 @@ namespace DotNetOpenAuth.OAuthWrap.ChannelElements { /// This method implements spec OAuth V1.0 section 5.3. /// </remarks> protected override OutgoingWebResponse PrepareDirectResponse(IProtocolMessage response) { + var webResponse = new OutgoingWebResponse(); + var fields = this.MessageDescriptions.GetAccessor(response); + var directResponse = (IDirectResponseProtocolMessage)response; var formatSpecifyingRequest = directResponse.OriginatingRequest as IOAuthDirectResponseFormat; if (formatSpecifyingRequest != null) { ResponseFormat format = formatSpecifyingRequest.Format; switch (format) { case ResponseFormat.Xml: + // NOTE: the spec is missing details on how to formulate this. throw new NotImplementedException(); case ResponseFormat.Form: - throw new NotImplementedException(); + string form = MessagingUtilities.CreateQueryString(fields); + webResponse.SetResponse(form, HttpFormUrlEncodedContentType); + break; case ResponseFormat.Json: - throw new NotImplementedException(); + var jsonSerializer = new JavaScriptSerializer(); + string json = jsonSerializer.Serialize(fields); + webResponse.SetResponse(json, new ContentType(JsonEncoded)); + break; default: throw ErrorUtilities.ThrowInternal("Unrecognized value of ResponseFormat enum: " + format); } } - throw new NotImplementedException(); + return webResponse; } /// <summary> diff --git a/src/DotNetOpenAuth/OAuthWrap/ChannelElements/TimestampEncoder.cs b/src/DotNetOpenAuth/OAuthWrap/ChannelElements/TimestampEncoder.cs index d4b113a..8edc382 100644 --- a/src/DotNetOpenAuth/OAuthWrap/ChannelElements/TimestampEncoder.cs +++ b/src/DotNetOpenAuth/OAuthWrap/ChannelElements/TimestampEncoder.cs @@ -35,7 +35,7 @@ namespace DotNetOpenAuth.OAuthWrap.ChannelElements { var timestamp = (DateTime)value; TimeSpan secondsSinceEpoch = timestamp - Epoch; - return secondsSinceEpoch.TotalSeconds.ToString(CultureInfo.InvariantCulture); + return ((int)secondsSinceEpoch.TotalSeconds).ToString(CultureInfo.InvariantCulture); } /// <summary> @@ -51,7 +51,7 @@ namespace DotNetOpenAuth.OAuthWrap.ChannelElements { return null; } - var secondsSinceEpoch = Convert.ToInt32(value, CultureInfo.InvariantCulture); + var secondsSinceEpoch = int.Parse(value, CultureInfo.InvariantCulture); return Epoch.AddSeconds(secondsSinceEpoch); } } diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/AccessTokenSuccessResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/AccessTokenSuccessResponse.cs index 2f9b770..b453b07 100644 --- a/src/DotNetOpenAuth/OAuthWrap/Messages/AccessTokenSuccessResponse.cs +++ b/src/DotNetOpenAuth/OAuthWrap/Messages/AccessTokenSuccessResponse.cs @@ -12,8 +12,8 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { using DotNetOpenAuth.Messaging; /// <summary> - /// A response from the Authorization Server to the Consumer containing a delegation code - /// that the Consumer should use to obtain an access token. + /// A response from the Authorization Server to the Client containing a delegation code + /// that the Client should use to obtain an access token. /// </summary> /// <remarks> /// This message type is shared by the Web App, Rich App, and Username/Password profiles. @@ -81,5 +81,12 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { /// </remarks> [MessagePart(Protocol.access_token_secret, IsRequired = false, AllowEmpty = false)] internal string AccessTokenSecret { get; set; } + + /// <summary> + /// Gets or sets the scope of access being requested. + /// </summary> + /// <value>The scope of the access request expressed as a list of space-delimited strings. The value of the scope parameter is defined by the authorization server. If the value contains multiple space-delimited strings, their order does not matter, and each string adds an additional access range to the requested scope.</value> + [MessagePart(Protocol.scope, IsRequired = false, AllowEmpty = true)] + public string Scope { get; set; } } } diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/MessageBase.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/MessageBase.cs index 738846b..1a8094e 100644 --- a/src/DotNetOpenAuth/OAuthWrap/Messages/MessageBase.cs +++ b/src/DotNetOpenAuth/OAuthWrap/Messages/MessageBase.cs @@ -43,6 +43,7 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { Contract.Requires<ArgumentNullException>(version != null); this.messageTransport = MessageTransport.Direct; this.version = version; + this.HttpMethods = HttpDeliveryMethods.GetRequest; } /// <summary> @@ -53,9 +54,10 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { protected MessageBase(IDirectedProtocolMessage request, Uri recipient = null) { Contract.Requires<ArgumentNullException>(request != null); this.originatingRequest = request; - this.messageTransport = MessageTransport.Direct; + this.messageTransport = request.Transport; this.version = request.Version; this.Recipient = recipient; + this.HttpMethods = HttpDeliveryMethods.GetRequest; } /// <summary> diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/WebServer/WebAppAccessTokenRequest.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/WebServer/WebAppAccessTokenRequest.cs index fe6f43a..86404ba 100644 --- a/src/DotNetOpenAuth/OAuthWrap/Messages/WebServer/WebAppAccessTokenRequest.cs +++ b/src/DotNetOpenAuth/OAuthWrap/Messages/WebServer/WebAppAccessTokenRequest.cs @@ -4,13 +4,13 @@ // </copyright> //----------------------------------------------------------------------- -using DotNetOpenAuth.OAuthWrap.Messages.WebServer; - namespace DotNetOpenAuth.OAuthWrap.Messages { using System; using System.Diagnostics.Contracts; - using DotNetOpenAuth.Messaging; - using DotNetOpenAuth.OAuthWrap.ChannelElements; + using ChannelElements; + using Configuration; + using Messaging; + using WebServer; /// <summary> /// A message sent by the Client directly to the Authorization Server to exchange @@ -114,7 +114,9 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { /// <exception cref="ProtocolException">Thrown if the message is invalid.</exception> protected override void EnsureValidMessage() { base.EnsureValidMessage(); - ErrorUtilities.VerifyProtocol(this.Recipient.IsTransportSecure(), OAuthWrapStrings.HttpsRequired); + ErrorUtilities.VerifyProtocol( + DotNetOpenAuthSection.Configuration.Messaging.RelaxSslRequirements || this.Recipient.IsTransportSecure(), + OAuthWrapStrings.HttpsRequired); } } } diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/WebServer/WebAppRequest.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/WebServer/WebAppRequest.cs index 8f94bbb..a5abdb2 100644 --- a/src/DotNetOpenAuth/OAuthWrap/Messages/WebServer/WebAppRequest.cs +++ b/src/DotNetOpenAuth/OAuthWrap/Messages/WebServer/WebAppRequest.cs @@ -57,7 +57,7 @@ namespace DotNetOpenAuth.OAuthWrap.Messages { /// REQUIRED. The client identifier as described in Section 3.4 (Client Credentials). /// </remarks> [MessagePart(Protocol.state, IsRequired = false, AllowEmpty = true)] - string IMessageWithClientState.ClientState { get; set; } + public string ClientState { get; set; } /// <summary> /// Gets or sets the scope of access being requested. diff --git a/src/DotNetOpenAuth/OAuthWrap/WebAppClient.cs b/src/DotNetOpenAuth/OAuthWrap/WebAppClient.cs index 0e26994..1847886 100644 --- a/src/DotNetOpenAuth/OAuthWrap/WebAppClient.cs +++ b/src/DotNetOpenAuth/OAuthWrap/WebAppClient.cs @@ -59,6 +59,7 @@ namespace DotNetOpenAuth.OAuthWrap { var request = new WebAppRequest(this.AuthorizationServer) { ClientIdentifier = this.ClientIdentifier, Callback = authorization.Callback, + Scope = authorization.Scope, }; return request; @@ -67,6 +68,7 @@ namespace DotNetOpenAuth.OAuthWrap { public IAuthorizationState ProcessUserAuthorization(HttpRequestInfo request = null) { Contract.Requires<InvalidOperationException>(!string.IsNullOrEmpty(this.ClientIdentifier)); Contract.Requires<InvalidOperationException>(!string.IsNullOrEmpty(this.ClientSecret)); + Contract.Requires<InvalidOperationException>(this.TokenManager != null); if (request == null) { request = this.Channel.GetRequestFromContext(); @@ -95,6 +97,16 @@ namespace DotNetOpenAuth.OAuthWrap { authorizationState.AccessTokenSecret = accessTokenSuccess.AccessTokenSecret; authorizationState.RefreshToken = accessTokenSuccess.RefreshToken; authorizationState.AccessTokenExpirationUtc = DateTime.UtcNow + accessTokenSuccess.Lifetime; + if (accessTokenSuccess.Scope != null && accessTokenSuccess.Scope != authorizationState.Scope) { + if (authorizationState.Scope != null) { + Logger.Wrap.InfoFormat("Requested scope of \"{0}\" changed to \"{1}\" by authorization server.", + authorizationState.Scope, + accessTokenSuccess.Scope); + } + + authorizationState.Scope = accessTokenSuccess.Scope; + } + authorizationState.SaveChanges(); } else { authorizationState.Delete(); |