summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2009-06-23 18:02:45 -0700
committerAndrew Arnott <andrewarnott@gmail.com>2009-06-23 18:02:45 -0700
commit73bdb918f37382a8985f597416746b4c55283dca (patch)
tree678165d15a154fa9cf49cf3bc1c30465445ea5bd
parent7b6219a7c1b2b076ad2f08f60a6c9e6dbab7e8e9 (diff)
downloadDotNetOpenAuth-73bdb918f37382a8985f597416746b4c55283dca.zip
DotNetOpenAuth-73bdb918f37382a8985f597416746b4c55283dca.tar.gz
DotNetOpenAuth-73bdb918f37382a8985f597416746b4c55283dca.tar.bz2
Added IServiceProviderAccessToken and added a method to get it on the IServiceProviderTokenManager interface.
-rw-r--r--samples/OAuthServiceProvider/App_Code/DatabaseTokenManager.cs10
-rw-r--r--samples/OAuthServiceProvider/App_Code/OAuthToken.cs22
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/InMemoryTokenManager.cs12
-rw-r--r--src/DotNetOpenAuth/DotNetOpenAuth.csproj1
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/IServiceProviderAccessToken.cs45
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/IServiceProviderTokenManager.cs20
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/TokenHandlingBindingElement.cs29
7 files changed, 135 insertions, 4 deletions
diff --git a/samples/OAuthServiceProvider/App_Code/DatabaseTokenManager.cs b/samples/OAuthServiceProvider/App_Code/DatabaseTokenManager.cs
index 8ca4539..710508d 100644
--- a/samples/OAuthServiceProvider/App_Code/DatabaseTokenManager.cs
+++ b/samples/OAuthServiceProvider/App_Code/DatabaseTokenManager.cs
@@ -26,7 +26,15 @@ public class DatabaseTokenManager : IServiceProviderTokenManager {
public IServiceProviderRequestToken GetRequestToken(string token) {
try {
- return Global.DataContext.OAuthTokens.First(t => t.Token == token);
+ return Global.DataContext.OAuthTokens.First(t => t.Token == token && t.State != TokenAuthorizationState.AccessToken);
+ } catch (InvalidOperationException ex) {
+ throw new KeyNotFoundException("Unrecognized token", ex);
+ }
+ }
+
+ public IServiceProviderAccessToken GetAccessToken(string token) {
+ try {
+ return Global.DataContext.OAuthTokens.First(t => t.Token == token && t.State == TokenAuthorizationState.AccessToken);
} catch (InvalidOperationException ex) {
throw new KeyNotFoundException("Unrecognized token", ex);
}
diff --git a/samples/OAuthServiceProvider/App_Code/OAuthToken.cs b/samples/OAuthServiceProvider/App_Code/OAuthToken.cs
index ec9b31e..fc1d6c5 100644
--- a/samples/OAuthServiceProvider/App_Code/OAuthToken.cs
+++ b/samples/OAuthServiceProvider/App_Code/OAuthToken.cs
@@ -10,7 +10,7 @@ using System.Linq;
using System.Web;
using DotNetOpenAuth.OAuth.ChannelElements;
-public partial class OAuthToken : IServiceProviderRequestToken {
+public partial class OAuthToken : IServiceProviderRequestToken, IServiceProviderAccessToken {
#region IServiceProviderRequestToken Members
string IServiceProviderRequestToken.Token {
@@ -41,4 +41,24 @@ public partial class OAuthToken : IServiceProviderRequestToken {
}
#endregion
+
+ #region IServiceProviderAccessToken Members
+
+ string IServiceProviderAccessToken.Token {
+ get { return this.Token; }
+ }
+
+ DateTime? IServiceProviderAccessToken.ExpirationDate {
+ get { return null; }
+ }
+
+ string IServiceProviderAccessToken.Username {
+ get { return this.User.OpenIDClaimedIdentifier; }
+ }
+
+ string[] IServiceProviderAccessToken.Roles {
+ get { return this.Scope.Split('|'); }
+ }
+
+ #endregion
}
diff --git a/src/DotNetOpenAuth.Test/Mocks/InMemoryTokenManager.cs b/src/DotNetOpenAuth.Test/Mocks/InMemoryTokenManager.cs
index 6980761..48547b7 100644
--- a/src/DotNetOpenAuth.Test/Mocks/InMemoryTokenManager.cs
+++ b/src/DotNetOpenAuth.Test/Mocks/InMemoryTokenManager.cs
@@ -102,6 +102,10 @@ namespace DotNetOpenAuth.Test.Mocks {
return this.tokens[token];
}
+ public IServiceProviderAccessToken GetAccessToken(string token) {
+ return this.tokens[token];
+ }
+
#endregion
/// <summary>
@@ -125,7 +129,7 @@ namespace DotNetOpenAuth.Test.Mocks {
this.requestTokens[requestToken] = true;
}
- private class TokenInfo : IServiceProviderRequestToken {
+ private class TokenInfo : IServiceProviderRequestToken, IServiceProviderAccessToken {
internal TokenInfo() {
this.CreatedOn = DateTime.Now;
}
@@ -142,6 +146,12 @@ namespace DotNetOpenAuth.Test.Mocks {
public Version ConsumerVersion { get; set; }
+ public string Username { get; set; }
+
+ public string[] Roles { get; set; }
+
+ public DateTime? ExpirationDate { get; set; }
+
internal string Secret { get; set; }
}
diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
index d3eb5e2..20e2869 100644
--- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj
+++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
@@ -243,6 +243,7 @@
<Compile Include="OAuth\ChannelElements\IConsumerDescription.cs" />
<Compile Include="OAuth\ChannelElements\IConsumerTokenManager.cs" />
<Compile Include="OAuth\ChannelElements\IOpenIdOAuthTokenManager.cs" />
+ <Compile Include="OAuth\ChannelElements\IServiceProviderAccessToken.cs" />
<Compile Include="OAuth\ChannelElements\IServiceProviderTokenManager.cs" />
<Compile Include="OAuth\ChannelElements\OAuthConsumerMessageFactory.cs" />
<Compile Include="OAuth\ChannelElements\ITokenGenerator.cs" />
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/IServiceProviderAccessToken.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/IServiceProviderAccessToken.cs
new file mode 100644
index 0000000..329ac4d
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/IServiceProviderAccessToken.cs
@@ -0,0 +1,45 @@
+//-----------------------------------------------------------------------
+// <copyright file="IServiceProviderAccessToken.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuth.ChannelElements {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+
+ /// <summary>
+ /// A description of an access token and its metadata as required by a Service Provider.
+ /// </summary>
+ public interface IServiceProviderAccessToken {
+ /// <summary>
+ /// Gets the token itself.
+ /// </summary>
+ string Token { get; }
+
+ /// <summary>
+ /// Gets the expiration date (local time) for the access token.
+ /// </summary>
+ /// <value>The expiration date, or <c>null</c> if there is no expiration date.</value>
+ DateTime? ExpirationDate { get; }
+
+ /// <summary>
+ /// Gets the username of the principal that will be impersonated by this access token.
+ /// </summary>
+ /// <value>
+ /// The name of the user who authorized the OAuth request token originally.
+ /// </value>
+ string Username { get; }
+
+ /// <summary>
+ /// Gets the roles that the OAuth principal should belong to.
+ /// </summary>
+ /// <value>
+ /// The roles that the user belongs to, or a subset of these according to the rights
+ /// granted when the user authorized the request token.
+ /// </value>
+ string[] Roles { get; }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/IServiceProviderTokenManager.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/IServiceProviderTokenManager.cs
index fa008ac..02ebffb 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/IServiceProviderTokenManager.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/IServiceProviderTokenManager.cs
@@ -29,6 +29,26 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// <param name="token">The request token.</param>
/// <returns>A description of the token. Never null.</returns>
/// <exception cref="KeyNotFoundException">Thrown if the token cannot be found.</exception>
+ /// <remarks>
+ /// It is acceptable for implementations to find the token, see that it has expired,
+ /// delete it from the database and then throw <see cref="KeyNotFoundException"/>,
+ /// or alternatively it can return the expired token anyway and the OAuth channel will
+ /// log and throw the appropriate error.
+ /// </remarks>
IServiceProviderRequestToken GetRequestToken(string token);
+
+ /// <summary>
+ /// Gets details on the named access token.
+ /// </summary>
+ /// <param name="token">The access token.</param>
+ /// <returns>A description of the token. Never null.</returns>
+ /// <exception cref="KeyNotFoundException">Thrown if the token cannot be found.</exception>
+ /// <remarks>
+ /// It is acceptable for implementations to find the token, see that it has expired,
+ /// delete it from the database and then throw <see cref="KeyNotFoundException"/>,
+ /// or alternatively it can return the expired token anyway and the OAuth channel will
+ /// log and throw the appropriate error.
+ /// </remarks>
+ IServiceProviderAccessToken GetAccessToken(string token);
}
}
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/TokenHandlingBindingElement.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/TokenHandlingBindingElement.cs
index e8acdcf..ce7bb98 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/TokenHandlingBindingElement.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/TokenHandlingBindingElement.cs
@@ -127,12 +127,39 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
this.VerifyThrowTokenTimeToLive(userAuthorizationRequest);
}
+ var accessResourceRequest = message as AccessProtectedResourceRequest;
+ if (accessResourceRequest != null) {
+ this.VerifyThrowTokenNotExpired(accessResourceRequest);
+ }
+
return null;
}
#endregion
/// <summary>
+ /// Ensures that access tokens have not yet expired.
+ /// </summary>
+ /// <param name="message">The incoming message carrying the access token.</param>
+ private void VerifyThrowTokenNotExpired(AccessProtectedResourceRequest message) {
+ ErrorUtilities.VerifyArgumentNotNull(message, "message");
+
+ try {
+ IServiceProviderAccessToken token = this.tokenManager.GetAccessToken(message.AccessToken);
+ if (token.ExpirationDate.HasValue && DateTime.Now >= token.ExpirationDate.Value.ToLocalTime()) {
+ Logger.OAuth.ErrorFormat(
+ "OAuth access token {0} rejected because it expired at {1}, and it is now {2}.",
+ token.Token,
+ token.ExpirationDate.Value,
+ DateTime.Now);
+ ErrorUtilities.ThrowProtocol(OAuthStrings.TokenNotFound);
+ }
+ } catch (KeyNotFoundException ex) {
+ throw ErrorUtilities.Wrap(ex, OAuthStrings.TokenNotFound);
+ }
+ }
+
+ /// <summary>
/// Ensures that short-lived request tokens included in incoming messages have not expired.
/// </summary>
/// <param name="message">The incoming message.</param>
@@ -148,7 +175,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
TimeSpan ttl = DotNetOpenAuthSection.Configuration.OAuth.ServiceProvider.SecuritySettings.MaximumRequestTokenTimeToLive;
if (DateTime.Now >= token.CreatedOn.ToLocalTime() + ttl) {
Logger.OAuth.ErrorFormat(
- "OAuth token {0} rejected because it was originally issued at {1}, expired at {2}, and it is now {3}.",
+ "OAuth request token {0} rejected because it was originally issued at {1}, expired at {2}, and it is now {3}.",
token.Token,
token.CreatedOn,
token.CreatedOn + ttl,