summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2012-02-20 22:18:31 -0800
committerAndrew Arnott <andrewarnott@gmail.com>2012-02-20 22:18:31 -0800
commit335402d6dda7a96acab14e7263ef16e06e637d12 (patch)
tree1f108e239c21dcdc99469d113224afde4ae3cade
parent234cf20e86b0ed1d65bca4a61eabb3277e8562c5 (diff)
downloadDotNetOpenAuth-335402d6dda7a96acab14e7263ef16e06e637d12.zip
DotNetOpenAuth-335402d6dda7a96acab14e7263ef16e06e637d12.tar.gz
DotNetOpenAuth-335402d6dda7a96acab14e7263ef16e06e637d12.tar.bz2
Added scaffolding for OAuth2 unit tests and added the first test for client authorization.
-rw-r--r--src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs13
-rw-r--r--src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs2
-rw-r--r--src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.Designer.cs9
-rw-r--r--src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.resx3
-rw-r--r--src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs6
-rw-r--r--src/DotNetOpenAuth.OAuth2/DotNetOpenAuth.OAuth2.csproj2
-rw-r--r--src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthServerBindingElementBase.cs15
-rw-r--r--src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthorizationCode.cs5
-rw-r--r--src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/IOAuth2ChannelWithAuthorizationServer.cs19
-rw-r--r--src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2AuthorizationServerChannel.cs2
-rw-r--r--src/DotNetOpenAuth.OAuth2/OAuth2/ClientDescription.cs71
-rw-r--r--src/DotNetOpenAuth.OAuth2/OAuth2/IAuthorizationServer.cs2
-rw-r--r--src/DotNetOpenAuth.OAuth2/OAuth2/OAuthStrings.Designer.cs9
-rw-r--r--src/DotNetOpenAuth.OAuth2/OAuth2/OAuthStrings.resx3
-rw-r--r--src/DotNetOpenAuth.OAuth2/OAuth2/OAuthUtilities.cs4
-rw-r--r--src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj6
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/CoordinatingChannel.cs2
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuth2AuthServerChannel.cs28
-rw-r--r--src/DotNetOpenAuth.Test/OAuth2/AuthorizeTests.cs50
-rw-r--r--src/DotNetOpenAuth.Test/OAuth2/OAuth2ChannelTests.cs21
-rw-r--r--src/DotNetOpenAuth.Test/OAuth2/OAuth2Coordinator.cs63
-rw-r--r--src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs18
22 files changed, 298 insertions, 55 deletions
diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs
index 5dee893..5429b60 100644
--- a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs
+++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs
@@ -26,31 +26,24 @@ namespace DotNetOpenAuth.OAuth2 {
/// <param name="authorizationServer">The authorization server.</param>
public AuthorizationServer(IAuthorizationServer authorizationServer) {
Requires.NotNull(authorizationServer, "authorizationServer");
- this.OAuthChannel = new OAuth2AuthorizationServerChannel(authorizationServer);
+ this.Channel = new OAuth2AuthorizationServerChannel(authorizationServer);
}
/// <summary>
/// Gets the channel.
/// </summary>
/// <value>The channel.</value>
- public Channel Channel {
- get { return this.OAuthChannel; }
- }
+ public Channel Channel { get; internal set; }
/// <summary>
/// Gets the authorization server.
/// </summary>
/// <value>The authorization server.</value>
public IAuthorizationServer AuthorizationServerServices {
- get { return this.OAuthChannel.AuthorizationServer; }
+ get { return ((IOAuth2ChannelWithAuthorizationServer)this.Channel).AuthorizationServer; }
}
/// <summary>
- /// Gets the channel.
- /// </summary>
- internal OAuth2AuthorizationServerChannel OAuthChannel { get; private set; }
-
- /// <summary>
/// Reads in a client's request for the Authorization Server to obtain permission from
/// the user to authorize the Client's access of some protected resource(s).
/// </summary>
diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs
index 6911452..8a681be 100644
--- a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs
+++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs
@@ -44,7 +44,7 @@ namespace DotNetOpenAuth.OAuth2 {
/// Gets the OAuth channel.
/// </summary>
/// <value>The channel.</value>
- public Channel Channel { get; private set; }
+ public Channel Channel { get; internal set; }
/// <summary>
/// Gets or sets the identifier by which this client is known to the Authorization Server.
diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.Designer.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.Designer.cs
index 72701d3..d140b7e 100644
--- a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.Designer.cs
+++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.Designer.cs
@@ -86,5 +86,14 @@ namespace DotNetOpenAuth.OAuth2 {
return ResourceManager.GetString("AuthorizationResponseUnexpectedMismatch", resourceCulture);
}
}
+
+ /// <summary>
+ /// Looks up a localized string similar to The property {0} must be set before this operation is allowed..
+ /// </summary>
+ internal static string RequiredPropertyNotYetPreset {
+ get {
+ return ResourceManager.GetString("RequiredPropertyNotYetPreset", resourceCulture);
+ }
+ }
}
}
diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.resx b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.resx
index a78e397..114b3e8 100644
--- a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.resx
+++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.resx
@@ -126,4 +126,7 @@
<data name="AuthorizationResponseUnexpectedMismatch" xml:space="preserve">
<value>Unexpected OAuth authorization response received with callback and client state that does not match an expected value.</value>
</data>
+ <data name="RequiredPropertyNotYetPreset" xml:space="preserve">
+ <value>The property {0} must be set before this operation is allowed.</value>
+ </data>
</root> \ No newline at end of file
diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs
index 09f471c..ffcc1ee 100644
--- a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs
+++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs
@@ -71,7 +71,7 @@ namespace DotNetOpenAuth.OAuth2 {
public OutgoingWebResponse PrepareRequestUserAuthorization(IAuthorizationState authorization, string state = null) {
Requires.NotNull(authorization, "authorization");
Requires.ValidState(authorization.Callback != null || (HttpContext.Current != null && HttpContext.Current.Request != null), MessagingStrings.HttpContextRequired);
- Requires.ValidState(!string.IsNullOrEmpty(this.ClientIdentifier));
+ Requires.ValidState(!string.IsNullOrEmpty(this.ClientIdentifier), OAuth2Strings.RequiredPropertyNotYetPreset, "ClientIdentifier");
Contract.Ensures(Contract.Result<OutgoingWebResponse>() != null);
if (authorization.Callback == null) {
@@ -97,8 +97,8 @@ namespace DotNetOpenAuth.OAuth2 {
/// <param name="request">The incoming HTTP request that may carry an authorization response.</param>
/// <returns>The authorization state that contains the details of the authorization.</returns>
public IAuthorizationState ProcessUserAuthorization(HttpRequestInfo request = null) {
- Requires.ValidState(!string.IsNullOrEmpty(this.ClientIdentifier));
- Requires.ValidState(!string.IsNullOrEmpty(this.ClientSecret));
+ Requires.ValidState(!string.IsNullOrEmpty(this.ClientIdentifier), OAuth2Strings.RequiredPropertyNotYetPreset, "ClientIdentifier");
+ Requires.ValidState(!string.IsNullOrEmpty(this.ClientSecret), OAuth2Strings.RequiredPropertyNotYetPreset, "ClientSecret");
if (request == null) {
request = this.Channel.GetRequestFromContext();
diff --git a/src/DotNetOpenAuth.OAuth2/DotNetOpenAuth.OAuth2.csproj b/src/DotNetOpenAuth.OAuth2/DotNetOpenAuth.OAuth2.csproj
index 094d005..5c934b4 100644
--- a/src/DotNetOpenAuth.OAuth2/DotNetOpenAuth.OAuth2.csproj
+++ b/src/DotNetOpenAuth.OAuth2/DotNetOpenAuth.OAuth2.csproj
@@ -26,6 +26,7 @@
<Compile Include="OAuth2\ChannelElements\AuthServerBindingElementBase.cs" />
<Compile Include="OAuth2\ChannelElements\GrantTypeEncoder.cs" />
<Compile Include="OAuth2\ChannelElements\EndUserAuthorizationResponseTypeEncoder.cs" />
+ <Compile Include="OAuth2\ChannelElements\IOAuth2ChannelWithAuthorizationServer.cs" />
<Compile Include="OAuth2\ChannelElements\OAuth2ChannelBase.cs" />
<Compile Include="OAuth2\ChannelElements\OAuth2ClientChannel.cs" />
<Compile Include="OAuth2\ChannelElements\ScopeEncoder.cs" />
@@ -36,6 +37,7 @@
<Compile Include="OAuth2\ChannelElements\AuthorizationCode.cs" />
<Compile Include="OAuth2\ChannelElements\AuthorizationCodeBindingElement.cs" />
<Compile Include="OAuth2\ChannelElements\AuthServerAllFlowsBindingElement.cs" />
+ <Compile Include="OAuth2\ClientDescription.cs" />
<Compile Include="OAuth2\ClientType.cs" />
<Compile Include="OAuth2\IAccessTokenAnalyzer.cs" />
<Compile Include="OAuth2\IAuthorizationServer.cs" />
diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthServerBindingElementBase.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthServerBindingElementBase.cs
index 6d24d38..49f820d 100644
--- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthServerBindingElementBase.cs
+++ b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthServerBindingElementBase.cs
@@ -18,8 +18,7 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
/// <summary>
/// Initializes a new instance of the <see cref="AuthServerBindingElementBase"/> class.
/// </summary>
- protected AuthServerBindingElementBase()
- {
+ protected AuthServerBindingElementBase() {
}
/// <summary>
@@ -39,21 +38,11 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
public abstract MessageProtections Protection { get; }
/// <summary>
- /// Gets the channel that this binding element belongs to.
- /// </summary>
- /// <remarks>
- /// This property is set by the channel when it is first constructed.
- /// </remarks>
- protected OAuth2AuthorizationServerChannel OAuthChannel {
- get { return (OAuth2AuthorizationServerChannel)this.Channel; }
- }
-
- /// <summary>
/// Gets the authorization server hosting this channel.
/// </summary>
/// <value>The authorization server.</value>
protected IAuthorizationServer AuthorizationServer {
- get { return this.OAuthChannel.AuthorizationServer; }
+ get { return ((IOAuth2ChannelWithAuthorizationServer)this.Channel).AuthorizationServer; }
}
/// <summary>
diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthorizationCode.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthorizationCode.cs
index 6199178..111c007 100644
--- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthorizationCode.cs
+++ b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AuthorizationCode.cs
@@ -61,8 +61,11 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
Requires.NotNull(authorizationServer, "authorizationServer");
Contract.Ensures(Contract.Result<IDataBagFormatter<AuthorizationCode>>() != null);
+ var cryptoStore = authorizationServer.CryptoKeyStore;
+ ErrorUtilities.VerifyHost(cryptoStore != null, OAuthStrings.ResultShouldNotBeNull, authorizationServer.GetType(), "CryptoKeyStore");
+
return new UriStyleMessageFormatter<AuthorizationCode>(
- authorizationServer.CryptoKeyStore,
+ cryptoStore,
AuthorizationCodeKeyBucket,
signed: true,
encrypted: true,
diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/IOAuth2ChannelWithAuthorizationServer.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/IOAuth2ChannelWithAuthorizationServer.cs
new file mode 100644
index 0000000..5fc73ce
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/IOAuth2ChannelWithAuthorizationServer.cs
@@ -0,0 +1,19 @@
+//-----------------------------------------------------------------------
+// <copyright file="IOAuth2ChannelWithAuthorizationServer.cs" company="Outercurve Foundation">
+// Copyright (c) Outercurve Foundation. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuth2.ChannelElements {
+ /// <summary>
+ /// An interface on an OAuth 2 Authorization Server channel
+ /// to expose the host provided authorization server object.
+ /// </summary>
+ internal interface IOAuth2ChannelWithAuthorizationServer {
+ /// <summary>
+ /// Gets the authorization server.
+ /// </summary>
+ /// <value>The authorization server.</value>
+ IAuthorizationServer AuthorizationServer { get; }
+ }
+}
diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2AuthorizationServerChannel.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2AuthorizationServerChannel.cs
index 295ee86..3375328 100644
--- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2AuthorizationServerChannel.cs
+++ b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2AuthorizationServerChannel.cs
@@ -15,7 +15,7 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
/// <summary>
/// The channel for the OAuth protocol.
/// </summary>
- internal class OAuth2AuthorizationServerChannel : OAuth2ChannelBase {
+ internal class OAuth2AuthorizationServerChannel : OAuth2ChannelBase, IOAuth2ChannelWithAuthorizationServer {
/// <summary>
/// Initializes a new instance of the <see cref="OAuth2AuthorizationServerChannel"/> class.
/// </summary>
diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ClientDescription.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ClientDescription.cs
new file mode 100644
index 0000000..76c3ea6
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth2/OAuth2/ClientDescription.cs
@@ -0,0 +1,71 @@
+//-----------------------------------------------------------------------
+// <copyright file="ClientDescription.cs" company="Outercurve Foundation">
+// Copyright (c) Outercurve Foundation. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuth2 {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+
+ /// <summary>
+ /// A default implementation of the <see cref="IClientDescription"/> interface.
+ /// </summary>
+ public class ClientDescription : IClientDescription {
+ /// <summary>
+ /// A delegate that determines whether the callback is allowed.
+ /// </summary>
+ private readonly Func<Uri, bool> isCallbackAllowed;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ClientDescription"/> class.
+ /// </summary>
+ /// <param name="secret">The secret.</param>
+ /// <param name="defaultCallback">The default callback.</param>
+ /// <param name="clientType">Type of the client.</param>
+ /// <param name="isCallbackAllowed">A delegate that determines whether the callback is allowed.</param>
+ public ClientDescription(string secret, Uri defaultCallback, ClientType clientType, Func<Uri, bool> isCallbackAllowed = null) {
+ this.Secret = secret;
+ this.DefaultCallback = defaultCallback;
+ this.ClientType = clientType;
+ this.isCallbackAllowed = isCallbackAllowed;
+ }
+
+ /// <summary>
+ /// Gets the client secret.
+ /// </summary>
+ public string Secret { get; private set; }
+
+ /// <summary>
+ /// Gets the callback to use when an individual authorization request
+ /// does not include an explicit callback URI.
+ /// </summary>
+ /// <value>
+ /// An absolute URL; or <c>null</c> if none is registered.
+ /// </value>
+ public Uri DefaultCallback { get; private set; }
+
+ /// <summary>
+ /// Gets the type of the client.
+ /// </summary>
+ public ClientType ClientType { get; private set; }
+
+ /// <summary>
+ /// Determines whether a callback URI included in a client's authorization request
+ /// is among those allowed callbacks for the registered client.
+ /// </summary>
+ /// <param name="callback">The absolute URI the client has requested the authorization result be received at.</param>
+ /// <returns>
+ /// <c>true</c> if the callback URL is allowable for this client; otherwise, <c>false</c>.
+ /// </returns>
+ public bool IsCallbackAllowed(Uri callback) {
+ if (this.isCallbackAllowed != null) {
+ return this.isCallbackAllowed(callback);
+ }
+
+ return EqualityComparer<Uri>.Default.Equals(this.DefaultCallback, callback);
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/IAuthorizationServer.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/IAuthorizationServer.cs
index 9c2888f..1732003 100644
--- a/src/DotNetOpenAuth.OAuth2/OAuth2/IAuthorizationServer.cs
+++ b/src/DotNetOpenAuth.OAuth2/OAuth2/IAuthorizationServer.cs
@@ -22,7 +22,7 @@ namespace DotNetOpenAuth.OAuth2 {
[ContractClass(typeof(IAuthorizationServerContract))]
public interface IAuthorizationServer {
/// <summary>
- /// Gets the store for storeing crypto keys used to symmetrically encrypt and sign authorization codes and refresh tokens.
+ /// Gets the store for storing crypto keys used to symmetrically encrypt and sign authorization codes and refresh tokens.
/// </summary>
/// <remarks>
/// This store should be kept strictly confidential in the authorization server(s)
diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthStrings.Designer.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthStrings.Designer.cs
index 2167b5f..6ce3b53 100644
--- a/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthStrings.Designer.cs
+++ b/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthStrings.Designer.cs
@@ -169,6 +169,15 @@ namespace DotNetOpenAuth.OAuth2 {
}
/// <summary>
+ /// Looks up a localized string similar to The return value of {0}.{1} should never be null..
+ /// </summary>
+ internal static string ResultShouldNotBeNull {
+ get {
+ return ResourceManager.GetString("ResultShouldNotBeNull", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to Individual scopes may not contain spaces..
/// </summary>
internal static string ScopesMayNotContainSpaces {
diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthStrings.resx b/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthStrings.resx
index 6fad914..af1a955 100644
--- a/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthStrings.resx
+++ b/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthStrings.resx
@@ -153,6 +153,9 @@
<data name="RefreshTokenInappropriateForRequestType" xml:space="preserve">
<value>The request message type {0} should not be responded to with a refresh token.</value>
</data>
+ <data name="ResultShouldNotBeNull" xml:space="preserve">
+ <value>The return value of {0}.{1} should never be null.</value>
+ </data>
<data name="ScopesMayNotContainSpaces" xml:space="preserve">
<value>Individual scopes may not contain spaces.</value>
</data>
diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthUtilities.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthUtilities.cs
index 245779a..68ccc1d 100644
--- a/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthUtilities.cs
+++ b/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthUtilities.cs
@@ -141,7 +141,9 @@ namespace DotNetOpenAuth.OAuth2 {
Contract.Ensures(Contract.Result<IClientDescription>() != null);
try {
- return authorizationServer.GetClient(clientIdentifier);
+ var result = authorizationServer.GetClient(clientIdentifier);
+ ErrorUtilities.VerifyHost(result != null, OAuthStrings.ResultShouldNotBeNull, authorizationServer.GetType().FullName, "GetClient(string)");
+ return result;
} catch (KeyNotFoundException ex) {
throw ErrorUtilities.Wrap(ex, OAuthStrings.ClientOrTokenSecretNotFound);
} catch (ArgumentException ex) {
diff --git a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
index 46556f7..8fc4183 100644
--- a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
+++ b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
@@ -218,6 +218,7 @@
<Compile Include="Mocks\AssociateUnencryptedRequestNoSslCheck.cs" />
<Compile Include="Mocks\CoordinatingChannel.cs" />
<Compile Include="Mocks\CoordinatingHttpRequestInfo.cs" />
+ <Compile Include="Mocks\CoordinatingOAuth2AuthServerChannel.cs" />
<Compile Include="Mocks\CoordinatingOutgoingWebResponse.cs" />
<Compile Include="Mocks\CoordinatingOAuthConsumerChannel.cs" />
<Compile Include="Mocks\InMemoryTokenManager.cs" />
@@ -242,7 +243,8 @@
<Compile Include="Mocks\TestMessage.cs" />
<Compile Include="Mocks\TestMessageFactory.cs" />
<Compile Include="OAuth2\MessageFactoryTests.cs" />
- <Compile Include="OAuth2\OAuth2ChannelTests.cs" />
+ <Compile Include="OAuth2\AuthorizeTests.cs" />
+ <Compile Include="OAuth2\OAuth2Coordinator.cs" />
<Compile Include="OAuth2\OAuth2TestBase.cs" />
<Compile Include="OAuth\ChannelElements\HmacSha1SigningBindingElementTests.cs" />
<Compile Include="OAuth\ChannelElements\OAuthChannelTests.cs" />
@@ -484,4 +486,4 @@
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(ProjectRoot)tools\DotNetOpenAuth.targets" />
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))\EnlistmentInfo.targets" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))' != '' " />
-</Project>
+</Project> \ No newline at end of file
diff --git a/src/DotNetOpenAuth.Test/Mocks/CoordinatingChannel.cs b/src/DotNetOpenAuth.Test/Mocks/CoordinatingChannel.cs
index 054892a..8d5295b 100644
--- a/src/DotNetOpenAuth.Test/Mocks/CoordinatingChannel.cs
+++ b/src/DotNetOpenAuth.Test/Mocks/CoordinatingChannel.cs
@@ -142,7 +142,7 @@ namespace DotNetOpenAuth.Test.Mocks {
ErrorUtilities.VerifyInternal(this.incomingMessage == null, "Oops, a message is already waiting for the remote party!");
this.incomingMessage = this.MessageDescriptions.GetAccessor(message).Serialize();
var directedMessage = message as IDirectedProtocolMessage;
- this.incomingMessageRecipient = directedMessage != null ? new MessageReceivingEndpoint(directedMessage.Recipient, directedMessage.HttpMethods) : null;
+ this.incomingMessageRecipient = (directedMessage != null && directedMessage.Recipient != null) ? new MessageReceivingEndpoint(directedMessage.Recipient, directedMessage.HttpMethods) : null;
this.incomingMessageSignal.Set();
}
diff --git a/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuth2AuthServerChannel.cs b/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuth2AuthServerChannel.cs
new file mode 100644
index 0000000..2b087fd
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuth2AuthServerChannel.cs
@@ -0,0 +1,28 @@
+//-----------------------------------------------------------------------
+// <copyright file="CoordinatingOAuth2AuthServerChannel.cs" company="Outercurve Foundation">
+// Copyright (c) Outercurve Foundation. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.Mocks {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OAuth2;
+ using DotNetOpenAuth.OAuth2.ChannelElements;
+
+ internal class CoordinatingOAuth2AuthServerChannel : CoordinatingChannel, IOAuth2ChannelWithAuthorizationServer {
+ private OAuth2AuthorizationServerChannel wrappedChannel;
+
+ internal CoordinatingOAuth2AuthServerChannel(Channel wrappedChannel, Action<IProtocolMessage> incomingMessageFilter, Action<IProtocolMessage> outgoingMessageFilter)
+ : base(wrappedChannel, incomingMessageFilter, outgoingMessageFilter) {
+ this.wrappedChannel = (OAuth2AuthorizationServerChannel)wrappedChannel;
+ }
+
+ public IAuthorizationServer AuthorizationServer {
+ get { return this.wrappedChannel.AuthorizationServer; }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/OAuth2/AuthorizeTests.cs b/src/DotNetOpenAuth.Test/OAuth2/AuthorizeTests.cs
new file mode 100644
index 0000000..0f0ad8b
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OAuth2/AuthorizeTests.cs
@@ -0,0 +1,50 @@
+//-----------------------------------------------------------------------
+// <copyright file="AuthorizeTests.cs" company="Outercurve Foundation">
+// Copyright (c) Outercurve Foundation. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.OAuth2 {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.Messaging.Bindings;
+ using DotNetOpenAuth.OAuth2;
+ using DotNetOpenAuth.OAuth2.ChannelElements;
+ using DotNetOpenAuth.OAuth2.Messages;
+ using Moq;
+ using NUnit.Framework;
+
+ [TestFixture]
+ public class AuthorizeTests : OAuth2TestBase {
+ [TestCase]
+ public void Test1() {
+ var authHostMock = new Mock<IAuthorizationServer>();
+ var cryptoStore = new MemoryCryptoKeyStore();
+ authHostMock.Setup(m => m.GetClient(ClientId)).Returns(ClientDescription);
+ authHostMock.SetupGet(m => m.CryptoKeyStore).Returns(cryptoStore);
+ authHostMock.Setup(m => m.IsAuthorizationValid(It.Is<IAuthorizationDescription>(d => d.ClientIdentifier == ClientId && d.User == Username))).Returns(true);
+ var coordinator = new OAuth2Coordinator(
+ AuthorizationServerDescription,
+ authHostMock.Object,
+ client => {
+ var authState = new AuthorizationState {
+ Callback = ClientCallback,
+ };
+ client.PrepareRequestUserAuthorization(authState).Respond();
+ var result = client.ProcessUserAuthorization();
+ Assert.IsNotNull(result.AccessToken);
+ },
+ server => {
+ var request = server.ReadAuthorizationRequest();
+ server.ApproveAuthorizationRequest(request, Username);
+ var tokenRequest = server.ReadAccessTokenRequest();
+ var tokenResponse = server.PrepareAccessTokenResponse(tokenRequest);
+ server.Channel.Respond(tokenResponse);
+ });
+ coordinator.Run();
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/OAuth2/OAuth2ChannelTests.cs b/src/DotNetOpenAuth.Test/OAuth2/OAuth2ChannelTests.cs
deleted file mode 100644
index 309dfaf..0000000
--- a/src/DotNetOpenAuth.Test/OAuth2/OAuth2ChannelTests.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-//-----------------------------------------------------------------------
-// <copyright file="OAuth2ChannelTests.cs" company="Outercurve Foundation">
-// Copyright (c) Outercurve Foundation. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.Test.OAuth2 {
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using DotNetOpenAuth.Messaging;
- using DotNetOpenAuth.OAuth2;
- using DotNetOpenAuth.OAuth2.ChannelElements;
- using DotNetOpenAuth.OAuth2.Messages;
- using NUnit.Framework;
-
- [TestFixture]
- public class OAuth2ChannelTests : OAuth2TestBase {
- }
-}
diff --git a/src/DotNetOpenAuth.Test/OAuth2/OAuth2Coordinator.cs b/src/DotNetOpenAuth.Test/OAuth2/OAuth2Coordinator.cs
new file mode 100644
index 0000000..5af7fe8
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OAuth2/OAuth2Coordinator.cs
@@ -0,0 +1,63 @@
+//-----------------------------------------------------------------------
+// <copyright file="OAuth2Coordinator.cs" company="Outercurve Foundation">
+// Copyright (c) Outercurve Foundation. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.OAuth2 {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.OAuth2;
+ using DotNetOpenAuth.Test.Mocks;
+
+ internal class OAuth2Coordinator : CoordinatorBase<WebServerClient, AuthorizationServer> {
+ private readonly AuthorizationServerDescription serverDescription;
+ private readonly IAuthorizationServer authServerHost;
+
+ internal OAuth2Coordinator(AuthorizationServerDescription serverDescription, IAuthorizationServer authServerHost, Action<WebServerClient> clientAction, Action<AuthorizationServer> authServerAction)
+ : base(clientAction, authServerAction) {
+ Requires.NotNull(serverDescription, "serverDescription");
+ Requires.NotNull(authServerHost, "authServerHost");
+ this.serverDescription = serverDescription;
+ this.authServerHost = authServerHost;
+ }
+
+ internal override void Run() {
+ var client = new WebServerClient(this.serverDescription) {
+ ClientIdentifier = OAuth2TestBase.ClientId,
+ ClientSecret = OAuth2TestBase.ClientSecret,
+ };
+ var authServer = new AuthorizationServer(this.authServerHost);
+
+ var rpCoordinatingChannel = new CoordinatingChannel(client.Channel, this.IncomingMessageFilter, this.OutgoingMessageFilter);
+ var opCoordinatingChannel = new CoordinatingOAuth2AuthServerChannel(authServer.Channel, this.IncomingMessageFilter, this.OutgoingMessageFilter);
+ rpCoordinatingChannel.RemoteChannel = opCoordinatingChannel;
+ opCoordinatingChannel.RemoteChannel = rpCoordinatingChannel;
+
+ client.Channel = rpCoordinatingChannel;
+ authServer.Channel = opCoordinatingChannel;
+
+ this.RunCore(client, authServer);
+ }
+
+ private static Action<WebServerClient> WrapAction(Action<WebServerClient> action) {
+ Requires.NotNull(action, "action");
+
+ return client => {
+ action(client);
+ ((CoordinatingChannel)client.Channel).Close();
+ };
+ }
+
+ private static Action<AuthorizationServer> WrapAction(Action<AuthorizationServer> action) {
+ Requires.NotNull(action, "action");
+
+ return authServer => {
+ action(authServer);
+ ((CoordinatingChannel)authServer.Channel).Close();
+ };
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs b/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs
index 49fc40b..32de525 100644
--- a/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs
+++ b/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs
@@ -9,7 +9,25 @@ namespace DotNetOpenAuth.Test.OAuth2 {
using System.Collections.Generic;
using System.Linq;
using System.Text;
+ using DotNetOpenAuth.OAuth2;
public class OAuth2TestBase : TestBase {
+ protected internal const string ClientId = "TestClientId";
+
+ protected internal const string ClientSecret = "TestClientSecret";
+
+ protected const string Username = "TestUser";
+
+ protected static readonly Uri ClientCallback = new Uri("http://client/callback");
+
+ protected static readonly AuthorizationServerDescription AuthorizationServerDescription = new AuthorizationServerDescription {
+ AuthorizationEndpoint = new Uri("https://authserver/authorize"),
+ TokenEndpoint = new Uri("https://authserver/token"),
+ };
+
+ protected static readonly IClientDescription ClientDescription = new ClientDescription(
+ ClientSecret,
+ ClientCallback,
+ ClientType.Confidential);
}
}