diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2009-06-23 18:02:45 -0700 |
---|---|---|
committer | Andrew Arnott <andrewarnott@gmail.com> | 2009-06-23 18:02:45 -0700 |
commit | 73bdb918f37382a8985f597416746b4c55283dca (patch) | |
tree | 678165d15a154fa9cf49cf3bc1c30465445ea5bd | |
parent | 7b6219a7c1b2b076ad2f08f60a6c9e6dbab7e8e9 (diff) | |
download | DotNetOpenAuth-73bdb918f37382a8985f597416746b4c55283dca.zip DotNetOpenAuth-73bdb918f37382a8985f597416746b4c55283dca.tar.gz DotNetOpenAuth-73bdb918f37382a8985f597416746b4c55283dca.tar.bz2 |
Added IServiceProviderAccessToken and added a method to get it on the IServiceProviderTokenManager interface.
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, |