diff options
19 files changed, 164 insertions, 61 deletions
diff --git a/projecttemplates/RelyingPartyLogic/Model.Client.cs b/projecttemplates/RelyingPartyLogic/Model.Client.cs index 9426408..3b3bce5 100644 --- a/projecttemplates/RelyingPartyLogic/Model.Client.cs +++ b/projecttemplates/RelyingPartyLogic/Model.Client.cs @@ -6,13 +6,30 @@ namespace RelyingPartyLogic { using System; + using System.Collections.Generic; using DotNetOpenAuth.OAuth2; public partial class Client : IConsumerDescription { - public Uri Callback { - get { return this.CallbackAsString != null ? new Uri(this.CallbackAsString) : null; } - set { this.CallbackAsString = value != null ? value.AbsoluteUri : null; } + /// <summary> + /// Gets the allowed callback URIs that this client has pre-registered with the service provider, if any. + /// </summary> + /// <value> + /// The URIs that user authorization responses may be directed to; must not be <c>null</c>, but may be empty. + /// </value> + /// <remarks> + /// The first element in this list (if any) will be used as the default client redirect URL if the client sends an authorization request without a redirect URL. + /// If the list is empty, any callback is allowed for this client. + /// </remarks> + public List<Uri> AllowedCallbacks { + get { + var result = new List<Uri>(); + if (this.CallbackAsString != null) { + result.Add(new Uri(this.CallbackAsString)); + } + + return result; + } } #region IConsumerDescription Members diff --git a/samples/OAuthConsumer/SampleWcf2.aspx.cs b/samples/OAuthConsumer/SampleWcf2.aspx.cs index 55154bc..68965be 100644 --- a/samples/OAuthConsumer/SampleWcf2.aspx.cs +++ b/samples/OAuthConsumer/SampleWcf2.aspx.cs @@ -21,6 +21,21 @@ private static readonly WebServerClient Client; /// <summary> + /// The details about the sample OAuth-enabled WCF service that this sample client calls into. + /// </summary> + private static AuthorizationServerDescription authServerDescription = new AuthorizationServerDescription { + TokenEndpoint = new Uri("http://localhost:65169/OAuth.ashx"), + AuthorizationEndpoint = new Uri("http://localhost:65169/Members/Authorize.aspx"), + }; + + /// <summary> + /// Initializes static members of the <see cref="SampleWcf2"/> class. + /// </summary> + static SampleWcf2() { + Client = new WebServerClient(authServerDescription, "sampleconsumer", "samplesecret"); + } + + /// <summary> /// Gets or sets the authorization details for the logged in user. /// </summary> /// <value>The authorization details.</value> @@ -33,21 +48,6 @@ set { HttpContext.Current.Session["Authorization"] = value; } } - /// <summary> - /// Initializes static members of the <see cref="SampleWcf2"/> class. - /// </summary> - static SampleWcf2() { - Client = new WebServerClient(AuthServerDescription, "sampleconsumer", "samplesecret"); - } - - /// <summary> - /// The details about the sample OAuth-enabled WCF service that this sample client calls into. - /// </summary> - private static AuthorizationServerDescription AuthServerDescription = new AuthorizationServerDescription { - TokenEndpoint = new Uri("http://localhost:65169/OAuth.ashx"), - AuthorizationEndpoint = new Uri("http://localhost:65169/Members/Authorize.aspx"), - }; - protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // Check to see if we're receiving a end user authorization response. diff --git a/samples/OAuthConsumerWpf/Authorize2.xaml.cs b/samples/OAuthConsumerWpf/Authorize2.xaml.cs index d303145..1480cd4 100644 --- a/samples/OAuthConsumerWpf/Authorize2.xaml.cs +++ b/samples/OAuthConsumerWpf/Authorize2.xaml.cs @@ -26,7 +26,7 @@ Contract.Requires(client != null, "client"); Contract.Requires(authorizationState != null, "authorizationState"); - InitializeComponent(); + this.InitializeComponent(); this.client = client; this.Authorization = authorizationState; @@ -47,11 +47,11 @@ } private void locationChanged(Uri location) { - //if (location.Scheme == "res") { - // this.DialogResult = false; - // this.Close(); - // MessageBox.Show("An error occurred during authorization."); - //} + ////if (location.Scheme == "res") { + //// this.DialogResult = false; + //// this.Close(); + //// MessageBox.Show("An error occurred during authorization."); + ////} if (SignificantlyEqual(location, this.Authorization.Callback, UriComponents.SchemeAndServer | UriComponents.Path)) { try { @@ -70,7 +70,7 @@ } private void webBrowser_LocationChanged(object sender, EventArgs e) { - this.locationChanged(webBrowser.Url); + this.locationChanged(this.webBrowser.Url); } } }
\ No newline at end of file diff --git a/samples/OAuthConsumerWpf/MainWindow.xaml.cs b/samples/OAuthConsumerWpf/MainWindow.xaml.cs index b194777..7a1f703 100644 --- a/samples/OAuthConsumerWpf/MainWindow.xaml.cs +++ b/samples/OAuthConsumerWpf/MainWindow.xaml.cs @@ -196,34 +196,34 @@ private void oauth2BeginButton_Click(object sender, RoutedEventArgs e) { var authServer = new DotNetOpenAuth.OAuth2.AuthorizationServerDescription { - AuthorizationEndpoint = new Uri(oauth2AuthorizationUrlBox.Text), + AuthorizationEndpoint = new Uri(this.oauth2AuthorizationUrlBox.Text), }; - if (oauth2TokenEndpointBox.Text.Length > 0) { - authServer.TokenEndpoint = new Uri(oauth2TokenEndpointBox.Text); + if (this.oauth2TokenEndpointBox.Text.Length > 0) { + authServer.TokenEndpoint = new Uri(this.oauth2TokenEndpointBox.Text); } try { - var client = new OAuth2.UserAgentClient(authServer, oauth2ClientIdentifierBox.Text, oauth2ClientSecretBox.Text); + var client = new OAuth2.UserAgentClient(authServer, this.oauth2ClientIdentifierBox.Text, this.oauth2ClientSecretBox.Text); - var authorization = new AuthorizationState(OAuthUtilities.SplitScopes(oauth2ScopeBox.Text)); + var authorization = new AuthorizationState(OAuthUtilities.SplitScopes(this.oauth2ScopeBox.Text)); var authorizePopup = new Authorize2(client, authorization); authorizePopup.Owner = this; bool? result = authorizePopup.ShowDialog(); if (result.HasValue && result.Value) { - var requestUri = new UriBuilder(oauth2ResourceUrlBox.Text); - if (oauth2ResourceHttpMethodList.SelectedIndex > 0) { + var requestUri = new UriBuilder(this.oauth2ResourceUrlBox.Text); + if (this.oauth2ResourceHttpMethodList.SelectedIndex > 0) { requestUri.AppendQueryArgument("access_token", authorization.AccessToken); } var request = (HttpWebRequest)WebRequest.Create(requestUri.Uri); - request.Method = oauth2ResourceHttpMethodList.SelectedIndex < 2 ? "GET" : "POST"; - if (oauth2ResourceHttpMethodList.SelectedIndex == 0) { + request.Method = this.oauth2ResourceHttpMethodList.SelectedIndex < 2 ? "GET" : "POST"; + if (this.oauth2ResourceHttpMethodList.SelectedIndex == 0) { client.AuthorizeRequest(request, authorization); } using (var resourceResponse = request.GetResponse()) { using (var responseStream = new StreamReader(resourceResponse.GetResponseStream())) { - oauth2ResultsBox.Text = responseStream.ReadToEnd(); + this.oauth2ResultsBox.Text = responseStream.ReadToEnd(); } } } else { diff --git a/samples/OAuthServiceProvider/Code/Client.cs b/samples/OAuthServiceProvider/Code/Client.cs index 43e282d..bb4007e 100644 --- a/samples/OAuthServiceProvider/Code/Client.cs +++ b/samples/OAuthServiceProvider/Code/Client.cs @@ -14,12 +14,25 @@ namespace OAuthServiceProvider.Code { public partial class Client : IConsumerDescription { #region IConsumerDescription Members + /// <summary> + /// Gets the client secret. + /// </summary> string IConsumerDescription.Secret { get { return this.ClientSecret; } } - Uri IConsumerDescription.Callback { - get { return string.IsNullOrEmpty(this.Callback) ? null : new Uri(this.Callback); } + /// <summary> + /// Gets the allowed callback URIs that this client has pre-registered with the service provider, if any. + /// </summary> + /// <value> + /// The URIs that user authorization responses may be directed to; must not be <c>null</c>, but may be empty. + /// </value> + /// <remarks> + /// The first element in this list (if any) will be used as the default client redirect URL if the client sends an authorization request without a redirect URL. + /// If the list is empty, any callback is allowed for this client. + /// </remarks> + List<Uri> IConsumerDescription.AllowedCallbacks { + get { return string.IsNullOrEmpty(this.Callback) ? new List<Uri>() : new List<Uri>(new Uri[] { new Uri(this.Callback) }); } } #endregion diff --git a/samples/OAuthServiceProvider/Members/Authorize.aspx.cs b/samples/OAuthServiceProvider/Members/Authorize.aspx.cs index 48a7897..4cb266f 100644 --- a/samples/OAuthServiceProvider/Members/Authorize.aspx.cs +++ b/samples/OAuthServiceProvider/Members/Authorize.aspx.cs @@ -16,15 +16,15 @@ public partial class Authorize2 : System.Web.UI.Page { private static readonly RandomNumberGenerator CryptoRandomDataGenerator = new RNGCryptoServiceProvider(); + private EndUserAuthorizationRequest pendingRequest; + + private Client client; + private string AuthorizationSecret { get { return Session["OAuthAuthorizationSecret"] as string; } set { Session["OAuthAuthorizationSecret"] = value; } } - private EndUserAuthorizationRequest pendingRequest; - - private Client client; - protected void Page_Load(object sender, EventArgs e) { var getRequest = new HttpRequestInfo("GET", this.Request.Url, this.Request.RawUrl, new WebHeaderCollection(), null); this.pendingRequest = Global.AuthorizationServer.ReadAuthorizationRequest(getRequest); diff --git a/src/DotNetOpenAuth.Test/OAuth2/MessageFactoryTests.cs b/src/DotNetOpenAuth.Test/OAuth2/MessageFactoryTests.cs index 2514f68..0e82154 100644 --- a/src/DotNetOpenAuth.Test/OAuth2/MessageFactoryTests.cs +++ b/src/DotNetOpenAuth.Test/OAuth2/MessageFactoryTests.cs @@ -105,7 +105,7 @@ namespace DotNetOpenAuth.Test.OAuth2 { { Protocol.client_secret, "abc" }, { Protocol.grant_type, "basic-credentials" }, { Protocol.username, "abc" }, - { Protocol.password , "abc" }, + { Protocol.password, "abc" }, }; IDirectedProtocolMessage request = this.messageFactory.GetNewRequestMessage(this.recipient, fields); Assert.IsInstanceOf(typeof(AccessTokenResourceOwnerPasswordCredentialsRequest), request); diff --git a/src/DotNetOpenAuth.Test/OAuth2/OAuth2ChannelTests.cs b/src/DotNetOpenAuth.Test/OAuth2/OAuth2ChannelTests.cs index 51d0656..c263eb6 100644 --- a/src/DotNetOpenAuth.Test/OAuth2/OAuth2ChannelTests.cs +++ b/src/DotNetOpenAuth.Test/OAuth2/OAuth2ChannelTests.cs @@ -1,5 +1,5 @@ //----------------------------------------------------------------------- -// <copyright file="OAuthWrapChannelTests.cs" company="Andrew Arnott"> +// <copyright file="OAuth2ChannelTests.cs" company="Andrew Arnott"> // Copyright (c) Andrew Arnott. All rights reserved. // </copyright> //----------------------------------------------------------------------- diff --git a/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs b/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs index fa1ed40..6c13c5e 100644 --- a/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs +++ b/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs @@ -1,5 +1,5 @@ //----------------------------------------------------------------------- -// <copyright file="OAuthWrapTestBase.cs" company="Andrew Arnott"> +// <copyright file="OAuth2TestBase.cs" company="Andrew Arnott"> // Copyright (c) Andrew Arnott. All rights reserved. // </copyright> //----------------------------------------------------------------------- diff --git a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs index 9dbd1b9..08c536a 100644 --- a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs +++ b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs @@ -935,7 +935,6 @@ namespace DotNetOpenAuth.Messaging { /// Tests whether two arrays are equal in contents and ordering, /// guaranteeing roughly equivalent execution time regardless of where a signature mismatch may exist. /// </summary> - /// <typeparam name="T">The type of elements in the arrays.</typeparam> /// <param name="first">The first array in the comparison. May not be null.</param> /// <param name="second">The second array in the comparison. May not be null.</param> /// <returns>True if the arrays equal; false otherwise.</returns> diff --git a/src/DotNetOpenAuth/OAuth2/AuthorizationServer.cs b/src/DotNetOpenAuth/OAuth2/AuthorizationServer.cs index 9eefb9d..f98dc79 100644 --- a/src/DotNetOpenAuth/OAuth2/AuthorizationServer.cs +++ b/src/DotNetOpenAuth/OAuth2/AuthorizationServer.cs @@ -66,6 +66,13 @@ namespace DotNetOpenAuth.OAuth2 { return message; } + /// <summary> + /// Approves an authorization request and sends an HTTP response to the user agent to redirect the user back to the Client. + /// </summary> + /// <param name="authorizationRequest">The authorization request to approve.</param> + /// <param name="username">The username of the account that approved the request (or whose data will be accessed by the client).</param> + /// <param name="scopes">The scope of access the client should be granted. If <c>null</c>, all scopes in the original request will be granted.</param> + /// <param name="callback">The Client callback URL to use when formulating the redirect to send the user agent back to the Client.</param> public void ApproveAuthorizationRequest(EndUserAuthorizationRequest authorizationRequest, string username, IEnumerable<string> scopes = null, Uri callback = null) { Contract.Requires<ArgumentNullException>(authorizationRequest != null, "authorizationRequest"); @@ -74,6 +81,11 @@ namespace DotNetOpenAuth.OAuth2 { this.Channel.Send(response); } + /// <summary> + /// Rejects an authorization request and sends an HTTP response to the user agent to redirect the user back to the Client. + /// </summary> + /// <param name="authorizationRequest">The authorization request to disapprove.</param> + /// <param name="callback">The Client callback URL to use when formulating the redirect to send the user agent back to the Client.</param> public void RejectAuthorizationRequest(EndUserAuthorizationRequest authorizationRequest, Uri callback = null) { Contract.Requires<ArgumentNullException>(authorizationRequest != null, "authorizationRequest"); @@ -123,6 +135,14 @@ namespace DotNetOpenAuth.OAuth2 { return response; } + /// <summary> + /// Approves an authorization request. + /// </summary> + /// <param name="authorizationRequest">The authorization request to approve.</param> + /// <param name="username">The username of the account that approved the request (or whose data will be accessed by the client).</param> + /// <param name="scopes">The scope of access the client should be granted. If <c>null</c>, all scopes in the original request will be granted.</param> + /// <param name="callback">The Client callback URL to use when formulating the redirect to send the user agent back to the Client.</param> + /// <returns>The authorization response message to send to the Client.</returns> public EndUserAuthorizationSuccessResponseBase PrepareApproveAuthorizationRequest(EndUserAuthorizationRequest authorizationRequest, string username, IEnumerable<string> scopes = null, Uri callback = null) { Contract.Requires<ArgumentNullException>(authorizationRequest != null, "authorizationRequest"); Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(username)); @@ -196,8 +216,8 @@ namespace DotNetOpenAuth.OAuth2 { } var client = this.AuthorizationServerServices.GetClient(authorizationRequest.ClientIdentifier); - if (client.Callback != null) { - return client.Callback; + if (client.AllowedCallbacks.Any()) { + return client.AllowedCallbacks.First(); } throw ErrorUtilities.ThrowProtocol(OAuthStrings.NoCallback); diff --git a/src/DotNetOpenAuth/OAuth2/ChannelElements/AuthServerAllFlowsBindingElement.cs b/src/DotNetOpenAuth/OAuth2/ChannelElements/AuthServerAllFlowsBindingElement.cs index 1bf8c79..7e69ae1 100644 --- a/src/DotNetOpenAuth/OAuth2/ChannelElements/AuthServerAllFlowsBindingElement.cs +++ b/src/DotNetOpenAuth/OAuth2/ChannelElements/AuthServerAllFlowsBindingElement.cs @@ -71,8 +71,12 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { var authorizationRequest = message as EndUserAuthorizationRequest; if (authorizationRequest != null) { var client = this.AuthorizationServer.GetClientOrThrow(authorizationRequest.ClientIdentifier); - ErrorUtilities.VerifyProtocol(client.Callback == null || client.Callback == authorizationRequest.Callback, OAuthStrings.CallbackMismatch, client.Callback, authorizationRequest.Callback); - ErrorUtilities.VerifyProtocol(client.Callback != null || authorizationRequest.Callback != null, OAuthStrings.NoCallback); + ErrorUtilities.VerifyProtocol( + !client.AllowedCallbacks.Any() || client.AllowedCallbacks.Contains(authorizationRequest.Callback), + OAuthStrings.CallbackMismatch, + String.Join(" ", client.AllowedCallbacks.Select(v => v.AbsoluteUri).ToArray()), + authorizationRequest.Callback); + ErrorUtilities.VerifyProtocol(client.AllowedCallbacks.Any() || authorizationRequest.Callback != null, OAuthStrings.NoCallback); return MessageProtections.None; } diff --git a/src/DotNetOpenAuth/OAuth2/IConsumerDescription.cs b/src/DotNetOpenAuth/OAuth2/IConsumerDescription.cs index 4e2bc4f..f37bc9f 100644 --- a/src/DotNetOpenAuth/OAuth2/IConsumerDescription.cs +++ b/src/DotNetOpenAuth/OAuth2/IConsumerDescription.cs @@ -6,10 +6,13 @@ namespace DotNetOpenAuth.OAuth2 { using System; + using System.Collections.Generic; + using System.Diagnostics.Contracts; /// <summary> /// A description of a client from an Authorization Server's point of view. /// </summary> + [ContractClass(typeof(IConsumerDescriptionContract))] public interface IConsumerDescription { /// <summary> /// Gets the client secret. @@ -17,9 +20,49 @@ namespace DotNetOpenAuth.OAuth2 { string Secret { get; } /// <summary> - /// Gets the callback URI that this client has pre-registered with the service provider, if any. + /// Gets the allowed callback URIs that this client has pre-registered with the service provider, if any. /// </summary> - /// <value>A URI that user authorization responses should be directed to; or <c>null</c> if no preregistered callback was arranged.</value> - Uri Callback { get; } + /// <value>The URIs that user authorization responses may be directed to; must not be <c>null</c>, but may be empty.</value> + /// <remarks> + /// The first element in this list (if any) will be used as the default client redirect URL if the client sends an authorization request without a redirect URL. + /// If the list is empty, any callback is allowed for this client. + /// </remarks> + List<Uri> AllowedCallbacks { get; } + } + + /// <summary> + /// Contract class for the <see cref="IConsumerDescription"/> interface. + /// </summary> + [ContractClassFor(typeof(IConsumerDescription))] + internal abstract class IConsumerDescriptionContract : IConsumerDescription { + #region IConsumerDescription Members + + /// <summary> + /// Gets the client secret. + /// </summary> + /// <value></value> + string IConsumerDescription.Secret { + get { throw new NotImplementedException(); } + } + + /// <summary> + /// Gets the allowed callback URIs that this client has pre-registered with the service provider, if any. + /// </summary> + /// <value> + /// The URIs that user authorization responses may be directed to; must not be <c>null</c>, but may be empty. + /// </value> + /// <remarks> + /// The first element in this list (if any) will be used as the default client redirect URL if the client sends an authorization request without a redirect URL. + /// If the list is empty, any callback is allowed for this client. + /// </remarks> + List<Uri> IConsumerDescription.AllowedCallbacks { + get { + Contract.Ensures(Contract.Result<List<Uri>>() != null); + Contract.Ensures(Contract.Result<List<Uri>>().TrueForAll(v => v != null && v.IsAbsoluteUri)); + throw new NotImplementedException(); + } + } + + #endregion } } diff --git a/src/DotNetOpenAuth/OAuth2/Messages/AccessTokenRefreshRequest.cs b/src/DotNetOpenAuth/OAuth2/Messages/AccessTokenRefreshRequest.cs index f15f190..e325dd7 100644 --- a/src/DotNetOpenAuth/OAuth2/Messages/AccessTokenRefreshRequest.cs +++ b/src/DotNetOpenAuth/OAuth2/Messages/AccessTokenRefreshRequest.cs @@ -39,7 +39,6 @@ namespace DotNetOpenAuth.OAuth2.Messages { get { return CodeOrTokenType.RefreshToken; } } - /// <summary> /// Gets or sets the verification code or refresh/access token. /// </summary> diff --git a/src/DotNetOpenAuth/OAuth2/Messages/EndUserAuthorizationFailedResponse.cs b/src/DotNetOpenAuth/OAuth2/Messages/EndUserAuthorizationFailedResponse.cs index b125c67..14677f3 100644 --- a/src/DotNetOpenAuth/OAuth2/Messages/EndUserAuthorizationFailedResponse.cs +++ b/src/DotNetOpenAuth/OAuth2/Messages/EndUserAuthorizationFailedResponse.cs @@ -13,9 +13,12 @@ namespace DotNetOpenAuth.OAuth2.Messages { using System.Text; using DotNetOpenAuth.Messaging; + /// <summary> + /// The message that an Authorization Server responds to a Client with when the user denies a user authorization request. + /// </summary> public class EndUserAuthorizationFailedResponse : MessageBase, IMessageWithClientState { /// <summary> - /// Initializes a new instance of the <see cref="EndUserAuthorizationSuccessResponseBase"/> class. + /// Initializes a new instance of the <see cref="EndUserAuthorizationFailedResponse"/> class. /// </summary> /// <param name="clientCallback">The URL to redirect to so the client receives the message. This may not be built into the request message if the client pre-registered the URL with the authorization server.</param> /// <param name="version">The protocol version.</param> diff --git a/src/DotNetOpenAuth/OAuth2/OAuthStrings.Designer.cs b/src/DotNetOpenAuth/OAuth2/OAuthStrings.Designer.cs index f4a74cc..7b2c3c2 100644 --- a/src/DotNetOpenAuth/OAuth2/OAuthStrings.Designer.cs +++ b/src/DotNetOpenAuth/OAuth2/OAuthStrings.Designer.cs @@ -70,7 +70,7 @@ namespace DotNetOpenAuth.OAuth2 { } /// <summary> - /// Looks up a localized string similar to Client's pre-registered callback URL ({0}) does not match the one found in the authorization request ({1}).. + /// Looks up a localized string similar to None of the client's pre-registered callback URLs ({0}) match the one found in the authorization request ({1}).. /// </summary> internal static string CallbackMismatch { get { diff --git a/src/DotNetOpenAuth/OAuth2/OAuthStrings.resx b/src/DotNetOpenAuth/OAuth2/OAuthStrings.resx index dacd9fc..c5b2cdc 100644 --- a/src/DotNetOpenAuth/OAuth2/OAuthStrings.resx +++ b/src/DotNetOpenAuth/OAuth2/OAuthStrings.resx @@ -121,7 +121,7 @@ <value>The requested access scope ("{0}") exceeds the grant scope ("{1}").</value> </data> <data name="CallbackMismatch" xml:space="preserve"> - <value>Client's pre-registered callback URL ({0}) does not match the one found in the authorization request ({1}).</value> + <value>None of the client's pre-registered callback URLs ({0}) match the one found in the authorization request ({1}).</value> </data> <data name="CannotObtainAccessTokenWithReason" xml:space="preserve"> <value>Failed to obtain access token. Authorization Server reports reason: {0}</value> diff --git a/src/DotNetOpenAuth/OAuth2/OAuthUtilities.cs b/src/DotNetOpenAuth/OAuth2/OAuthUtilities.cs index 79ef278..64a6d0c 100644 --- a/src/DotNetOpenAuth/OAuth2/OAuthUtilities.cs +++ b/src/DotNetOpenAuth/OAuth2/OAuthUtilities.cs @@ -18,6 +18,9 @@ namespace DotNetOpenAuth.OAuth2 { /// Some common utility methods for OAuth 2.0. /// </summary> public static class OAuthUtilities { + /// <summary> + /// The <see cref="StringComparer"/> instance to use when comparing scope equivalence. + /// </summary> public static readonly StringComparer ScopeStringComparer = StringComparer.Ordinal; /// <summary> @@ -62,10 +65,8 @@ namespace DotNetOpenAuth.OAuth2 { /// <summary> /// Identifies individual scope elements /// </summary> - /// <param name="scope">The scope.</param> - /// <param name="scopeComparer">The scope comparer, allowing scopes to be case sensitive or insensitive. - /// Usually <see cref="StringComparer.Ordinal"/> or <see cref="StringComparer.OrdinalIgnoreCase"/>.</param> - /// <returns></returns> + /// <param name="scope">The space-delimited list of scopes.</param> + /// <returns>A set of individual scopes, with any duplicates removed.</returns> public static HashSet<string> SplitScopes(string scope) { if (string.IsNullOrEmpty(scope)) { return new HashSet<string>(); @@ -74,6 +75,11 @@ namespace DotNetOpenAuth.OAuth2 { return new HashSet<string>(scope.Split(scopeDelimiter, StringSplitOptions.RemoveEmptyEntries), ScopeStringComparer); } + /// <summary> + /// Serializes a set of scopes as a space-delimited list. + /// </summary> + /// <param name="scopes">The scopes to serialize.</param> + /// <returns>A space-delimited list.</returns> public static string JoinScopes(HashSet<string> scopes) { Contract.Requires<ArgumentNullException>(scopes != null, "scopes"); return string.Join(" ", scopes.ToArray()); diff --git a/src/DotNetOpenAuth/OAuth2/WebServerClient.cs b/src/DotNetOpenAuth/OAuth2/WebServerClient.cs index 0998619..d50ab8f 100644 --- a/src/DotNetOpenAuth/OAuth2/WebServerClient.cs +++ b/src/DotNetOpenAuth/OAuth2/WebServerClient.cs @@ -40,7 +40,6 @@ namespace DotNetOpenAuth.OAuth2 { /// </summary> /// <param name="scope">The scope of authorized access requested.</param> /// <param name="state">The state of the client that should be sent back with the authorization response.</param> - /// <returns>The authorization request as an HTTP response that causes a redirect.</returns> public void RequestUserAuthorization(IEnumerable<string> scope = null, string state = null) { this.PrepareRequestUserAuthorization(scope, state).Send(); } |