diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2008-09-25 17:08:25 -0700 |
---|---|---|
committer | Andrew <andrewarnott@gmail.com> | 2008-09-25 17:08:25 -0700 |
commit | 49c26eba391f16d197697281d6122b9db42b9e11 (patch) | |
tree | 8ab74995afd1fa08302e34c604a871b9d61d0740 | |
parent | 50e34bfe7224576e901efa6748598d31c36df3a5 (diff) | |
download | DotNetOpenAuth-49c26eba391f16d197697281d6122b9db42b9e11.zip DotNetOpenAuth-49c26eba391f16d197697281d6122b9db42b9e11.tar.gz DotNetOpenAuth-49c26eba391f16d197697281d6122b9db42b9e11.tar.bz2 |
Added check so that unauthorized request tokens cannot be exchanged for access tokens.
-rw-r--r-- | src/DotNetOAuth.Test/Mocks/InMemoryTokenManager.cs | 24 | ||||
-rw-r--r-- | src/DotNetOAuth.Test/Scenarios/AppendixScenarios.cs | 1 | ||||
-rw-r--r-- | src/DotNetOAuth/ChannelElements/ITokenManager.cs | 12 | ||||
-rw-r--r-- | src/DotNetOAuth/ServiceProvider.cs | 9 | ||||
-rw-r--r-- | src/DotNetOAuth/Strings.Designer.cs | 9 | ||||
-rw-r--r-- | src/DotNetOAuth/Strings.resx | 3 |
6 files changed, 58 insertions, 0 deletions
diff --git a/src/DotNetOAuth.Test/Mocks/InMemoryTokenManager.cs b/src/DotNetOAuth.Test/Mocks/InMemoryTokenManager.cs index 0454fb8..622a098 100644 --- a/src/DotNetOAuth.Test/Mocks/InMemoryTokenManager.cs +++ b/src/DotNetOAuth.Test/Mocks/InMemoryTokenManager.cs @@ -14,6 +14,7 @@ namespace DotNetOAuth.Test.Mocks { internal class InMemoryTokenManager : ITokenManager {
private Dictionary<string, string> consumersAndSecrets = new Dictionary<string, string>();
private Dictionary<string, string> tokensAndSecrets = new Dictionary<string, string>();
+ private List<string> authorizedRequestTokens = new List<string>();
#region ITokenManager Members
@@ -29,7 +30,22 @@ namespace DotNetOAuth.Test.Mocks { this.tokensAndSecrets[requestToken] = requestTokenSecret;
}
+ /// <summary>
+ /// Checks whether a given request token has already been authorized
+ /// by some user for use by the Consumer that requested it.
+ /// </summary>
+ /// <param name="requestToken">The Consumer's request token.</param>
+ /// <returns>
+ /// True if the request token has already been fully authorized by the user
+ /// who owns the relevant protected resources. False if the token has not yet
+ /// been authorized, has expired or does not exist.
+ /// </returns>
+ public bool IsRequestTokenAuthorized(string requestToken) {
+ return this.authorizedRequestTokens.Contains(requestToken);
+ }
+
public void ExpireRequestTokenAndStoreNewAccessToken(string consumerKey, string requestToken, string accessToken, string accessTokenSecret) {
+ this.authorizedRequestTokens.Remove(requestToken);
this.tokensAndSecrets.Remove(requestToken);
this.tokensAndSecrets[accessToken] = accessTokenSecret;
}
@@ -39,5 +55,13 @@ namespace DotNetOAuth.Test.Mocks { internal void AddConsumer(string key, string secret) {
this.consumersAndSecrets.Add(key, secret);
}
+
+ internal void AuthorizedRequestToken(string requestToken) {
+ if (requestToken == null) {
+ throw new ArgumentNullException("requestToken");
+ }
+
+ this.authorizedRequestTokens.Add(requestToken);
+ }
}
}
diff --git a/src/DotNetOAuth.Test/Scenarios/AppendixScenarios.cs b/src/DotNetOAuth.Test/Scenarios/AppendixScenarios.cs index aefa0ea..d5e93e9 100644 --- a/src/DotNetOAuth.Test/Scenarios/AppendixScenarios.cs +++ b/src/DotNetOAuth.Test/Scenarios/AppendixScenarios.cs @@ -41,6 +41,7 @@ namespace DotNetOAuth.Test { var requestTokenMessage = sp.ReadTokenRequest();
sp.SendUnauthorizedTokenResponse(requestTokenMessage);
var authRequest = sp.ReadAuthorizationRequest();
+ tokenManager.AuthorizedRequestToken(authRequest.RequestToken);
sp.SendAuthorizationResponse(authRequest);
var accessRequest = sp.ReadAccessTokenRequest();
sp.SendAccessToken(accessRequest);
diff --git a/src/DotNetOAuth/ChannelElements/ITokenManager.cs b/src/DotNetOAuth/ChannelElements/ITokenManager.cs index 9aa9299..0ab108c 100644 --- a/src/DotNetOAuth/ChannelElements/ITokenManager.cs +++ b/src/DotNetOAuth/ChannelElements/ITokenManager.cs @@ -39,6 +39,18 @@ namespace DotNetOAuth.ChannelElements { void StoreNewRequestToken(string consumerKey, string requestToken, string requestTokenSecret, IDictionary<string, string> parameters);
/// <summary>
+ /// Checks whether a given request token has already been authorized
+ /// by some user for use by the Consumer that requested it.
+ /// </summary>
+ /// <param name="requestToken">The Consumer's request token.</param>
+ /// <returns>
+ /// True if the request token has already been fully authorized by the user
+ /// who owns the relevant protected resources. False if the token has not yet
+ /// been authorized, has expired or does not exist.
+ /// </returns>
+ bool IsRequestTokenAuthorized(string requestToken);
+
+ /// <summary>
/// Deletes a request token and its associated secret and stores a new access token and secret.
/// </summary>
/// <param name="consumerKey">The Consumer that is exchanging its request token for an access token.</param>
diff --git a/src/DotNetOAuth/ServiceProvider.cs b/src/DotNetOAuth/ServiceProvider.cs index 6b87079..a6ed9e0 100644 --- a/src/DotNetOAuth/ServiceProvider.cs +++ b/src/DotNetOAuth/ServiceProvider.cs @@ -6,6 +6,7 @@ namespace DotNetOAuth {
using System;
+ using System.Globalization;
using System.Web;
using DotNetOAuth.ChannelElements;
using DotNetOAuth.Messages;
@@ -127,6 +128,14 @@ namespace DotNetOAuth { }
internal void SendAccessToken(RequestAccessTokenMessage request) {
+ if (!this.TokenManager.IsRequestTokenAuthorized(request.RequestToken)) {
+ throw new ProtocolException(
+ string.Format(
+ CultureInfo.CurrentCulture,
+ Strings.AccessTokenNotAuthorized,
+ request.RequestToken));
+ }
+
string accessToken = this.TokenGenerator.GenerateAccessToken(request.ConsumerKey);
string tokenSecret = this.TokenGenerator.GenerateSecret();
this.TokenManager.ExpireRequestTokenAndStoreNewAccessToken(request.ConsumerKey, request.RequestToken, accessToken, tokenSecret);
diff --git a/src/DotNetOAuth/Strings.Designer.cs b/src/DotNetOAuth/Strings.Designer.cs index 47a4c1c..b5ba9c7 100644 --- a/src/DotNetOAuth/Strings.Designer.cs +++ b/src/DotNetOAuth/Strings.Designer.cs @@ -61,6 +61,15 @@ namespace DotNetOAuth { }
/// <summary>
+ /// Looks up a localized string similar to Cannot send access token to Consumer for request token '{0}' before it has been authorized..
+ /// </summary>
+ internal static string AccessTokenNotAuthorized {
+ get {
+ return ResourceManager.GetString("AccessTokenNotAuthorized", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to HttpContext.Current is null. There must be an ASP.NET request in process for this operation to succeed..
/// </summary>
internal static string CurrentHttpContextRequired {
diff --git a/src/DotNetOAuth/Strings.resx b/src/DotNetOAuth/Strings.resx index 0e718d8..ffb73ea 100644 --- a/src/DotNetOAuth/Strings.resx +++ b/src/DotNetOAuth/Strings.resx @@ -117,6 +117,9 @@ <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
+ <data name="AccessTokenNotAuthorized" xml:space="preserve">
+ <value>Cannot send access token to Consumer for request token '{0}' before it has been authorized.</value>
+ </data>
<data name="CurrentHttpContextRequired" xml:space="preserve">
<value>HttpContext.Current is null. There must be an ASP.NET request in process for this operation to succeed.</value>
</data>
|