Skip to content
This repository has been archived by the owner on Mar 20, 2019. It is now read-only.

Commit

Permalink
Merge pull request #235 from dotnetjunky/v4.1
Browse files Browse the repository at this point in the history
Fix bug in the LinkedInClient not working 
Fixes #232
  • Loading branch information
AArnott committed Nov 27, 2012
2 parents d8aa2db + e0772ae commit f458900
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class AuthenticationOnlyCookieOAuthTokenManager : IOAuthTokenManager {
/// <summary>
/// Key used for token cookie
/// </summary>
private const string TokenCookieKey = "OAuthTokenSecret";
protected const string TokenCookieKey = "OAuthTokenSecret";

/// <summary>
/// Primary request context.
Expand All @@ -41,7 +41,7 @@ public AuthenticationOnlyCookieOAuthTokenManager(HttpContextBase context) {
/// <summary>
/// Gets the effective HttpContext object to use.
/// </summary>
private HttpContextBase Context {
protected HttpContextBase Context {
get {
return this.primaryContext ?? new HttpContextWrapper(HttpContext.Current);
}
Expand All @@ -54,15 +54,13 @@ private HttpContextBase Context {
/// <returns>
/// The token's secret
/// </returns>
public string GetTokenSecret(string token) {
public virtual string GetTokenSecret(string token) {
HttpCookie cookie = this.Context.Request.Cookies[TokenCookieKey];
if (cookie == null || string.IsNullOrEmpty(cookie.Values[token])) {
return null;
}
byte[] cookieBytes = HttpServerUtility.UrlTokenDecode(cookie.Values[token]);
byte[] clearBytes = MachineKeyUtil.Unprotect(cookieBytes, TokenCookieKey, "Token:" + token);

string secret = Encoding.UTF8.GetString(clearBytes);
string secret = DecodeAndUnprotectToken(token, cookie.Values[token]);
return secret;
}

Expand All @@ -72,7 +70,7 @@ public string GetTokenSecret(string token) {
/// <param name="requestToken">The request token.</param>
/// <param name="accessToken">The access token.</param>
/// <param name="accessTokenSecret">The access token secret.</param>
public void ReplaceRequestTokenWithAccessToken(string requestToken, string accessToken, string accessTokenSecret) {
public virtual void ReplaceRequestTokenWithAccessToken(string requestToken, string accessToken, string accessTokenSecret) {
var cookie = new HttpCookie(TokenCookieKey) {
Value = string.Empty,
Expires = DateTime.UtcNow.AddDays(-5)
Expand All @@ -85,7 +83,7 @@ public void ReplaceRequestTokenWithAccessToken(string requestToken, string acces
/// </summary>
/// <param name="requestToken">The request token.</param>
/// <param name="requestTokenSecret">The request token secret.</param>
public void StoreRequestToken(string requestToken, string requestTokenSecret) {
public virtual void StoreRequestToken(string requestToken, string requestTokenSecret) {
var cookie = new HttpCookie(TokenCookieKey) {
HttpOnly = true
};
Expand All @@ -94,10 +92,36 @@ public void StoreRequestToken(string requestToken, string requestTokenSecret) {
cookie.Secure = true;
}

byte[] cookieBytes = Encoding.UTF8.GetBytes(requestTokenSecret);
var secretBytes = MachineKeyUtil.Protect(cookieBytes, TokenCookieKey, "Token:" + requestToken);
cookie.Values[requestToken] = HttpServerUtility.UrlTokenEncode(secretBytes);
var encryptedToken = ProtectAndEncodeToken(requestToken, requestTokenSecret);
cookie.Values[requestToken] = encryptedToken;

this.Context.Response.Cookies.Set(cookie);
}

/// <summary>
/// Protect and url-encode the specified token secret.
/// </summary>
/// <param name="token">The token to be used as a key.</param>
/// <param name="tokenSecret">The token secret to be protected</param>
/// <returns>The encrypted and protected string.</returns>
protected static string ProtectAndEncodeToken(string token, string tokenSecret)
{
byte[] cookieBytes = Encoding.UTF8.GetBytes(tokenSecret);
var secretBytes = MachineKeyUtil.Protect(cookieBytes, TokenCookieKey, "Token:" + token);
return HttpServerUtility.UrlTokenEncode(secretBytes);
}

/// <summary>
/// Url-decode and unprotect the specified encrypted token string.
/// </summary>
/// <param name="token">The token to be used as a key.</param>
/// <param name="encryptedToken">The encrypted token to be decrypted</param>
/// <returns>The original token secret</returns>
protected static string DecodeAndUnprotectToken(string token, string encryptedToken)
{
byte[] cookieBytes = HttpServerUtility.UrlTokenDecode(encryptedToken);
byte[] clearBytes = MachineKeyUtil.Unprotect(cookieBytes, TokenCookieKey, "Token:" + token);
return Encoding.UTF8.GetString(clearBytes);
}
}
}
74 changes: 74 additions & 0 deletions src/DotNetOpenAuth.AspNet/Clients/OAuth/CookieOAuthTokenManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using System.Web;
using System.Web.Security;

namespace DotNetOpenAuth.AspNet.Clients {

/// <summary>
/// Stores OAuth tokens in the current request's cookie.
/// </summary>
/// <remarks>
/// This class is different from the <see cref="AuthenticationOnlyCookieOAuthTokenManager"/> in that
/// it also stores the access token after the authentication has succeeded.
/// </remarks>
public class CookieOAuthTokenManager : AuthenticationOnlyCookieOAuthTokenManager {
/// <summary>
/// Initializes a new instance of the <see cref="CookieOAuthTokenManager"/> class.
/// </summary>
public CookieOAuthTokenManager() {
}

/// <summary>
/// Initializes a new instance of the <see cref="CookieOAuthTokenManager"/> class.
/// </summary>
/// <param name="context">The current request context.</param>
public CookieOAuthTokenManager(HttpContextBase context)
: base(context) {
}

/// <summary>
/// Gets the token secret from the specified token.
/// </summary>
/// <param name="token">The token.</param>
/// <returns>
/// The token's secret
/// </returns>
public override string GetTokenSecret(string token) {
string secret = base.GetTokenSecret(token);
if (secret != null) {
return secret;
}

// The base class checks for cookies in the Request object.
// Here we check in the Response object as well because we
// may have set it earlier in the request life cycle.
HttpCookie cookie = this.Context.Response.Cookies[TokenCookieKey];
if (cookie == null || string.IsNullOrEmpty(cookie.Values[token])) {
return null;
}

secret = DecodeAndUnprotectToken(token, cookie.Values[token]);
return secret;
}

/// <summary>
/// Replaces the request token with access token.
/// </summary>
/// <param name="requestToken">The request token.</param>
/// <param name="accessToken">The access token.</param>
/// <param name="accessTokenSecret">The access token secret.</param>
public override void ReplaceRequestTokenWithAccessToken(string requestToken, string accessToken, string accessTokenSecret) {
var cookie = new HttpCookie(TokenCookieKey) {
HttpOnly = true
};

if (FormsAuthentication.RequireSSL) {
cookie.Secure = true;
}

var encryptedToken = ProtectAndEncodeToken(accessToken, accessTokenSecret);
cookie.Values[accessToken] = encryptedToken;

this.Context.Response.Cookies.Set(cookie);
}
}
}
2 changes: 1 addition & 1 deletion src/DotNetOpenAuth.AspNet/Clients/OAuth/LinkedInClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public sealed class LinkedInClient : OAuthClient {
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
Justification = "We can't dispose the object because we still need it through the app lifetime.")]
public LinkedInClient(string consumerKey, string consumerSecret)
: this(consumerKey, consumerSecret, new AuthenticationOnlyCookieOAuthTokenManager()) { }
: this(consumerKey, consumerSecret, new CookieOAuthTokenManager()) { }

/// <summary>
/// Initializes a new instance of the <see cref="LinkedInClient"/> class.
Expand Down
3 changes: 2 additions & 1 deletion src/DotNetOpenAuth.AspNet/DotNetOpenAuth.AspNet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<Import Project="$(ProjectRoot)tools\DotNetOpenAuth.props" />
<Import Project="$(ProjectRoot)tools\DotNetOpenAuth.Product.props" />
<PropertyGroup>
<RootNamespace>DotNetOpenAuth.AspNet</RootNamespace>
<RootNamespace>DotNetOpenAuth.AspNet</RootNamespace>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
Expand All @@ -48,6 +48,7 @@
<Compile Include="Clients\OAuth\AuthenticationOnlyCookieOAuthTokenManager.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Clients\OAuth\CookieOAuthTokenManager.cs" />
<Compile Include="Clients\OAuth\IOAuthTokenManager.cs" />
<Compile Include="Clients\OAuth\SimpleConsumerTokenManager.cs" />
<Compile Include="IAuthenticationClient.cs" />
Expand Down

0 comments on commit f458900

Please sign in to comment.