diff options
Diffstat (limited to 'src/DotNetOpenAuth.AspNet/Clients/OAuth')
3 files changed, 107 insertions, 5 deletions
diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth/AuthenticationOnlyCookieOAuthTokenManager.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth/AuthenticationOnlyCookieOAuthTokenManager.cs new file mode 100644 index 0000000..10cf39d --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth/AuthenticationOnlyCookieOAuthTokenManager.cs @@ -0,0 +1,96 @@ +//----------------------------------------------------------------------- +// <copyright file="AuthenticationOnlyCookieOAuthTokenManager.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet.Clients { + using System; + using System.Text; + using System.Web; + using System.Web.Security; + + /// <summary> + /// Stores OAuth tokens in the current request's cookie + /// </summary> + public class AuthenticationOnlyCookieOAuthTokenManager : IOAuthTokenManager { + /// <summary> + /// Key used for token cookie + /// </summary> + private const string TokenCookieKey = "OAuthTokenSecret"; + + /// <summary> + /// Primary request context. + /// </summary> + private readonly HttpContextBase primaryContext; + + /// <summary> + /// Initializes a new instance of the <see cref="AuthenticationOnlyCookieOAuthTokenManager"/> class. + /// </summary> + public AuthenticationOnlyCookieOAuthTokenManager() { + } + + /// <summary> + /// Initializes a new instance of the <see cref="AuthenticationOnlyCookieOAuthTokenManager"/> class. + /// </summary> + /// <param name="context">The current request context.</param> + public AuthenticationOnlyCookieOAuthTokenManager(HttpContextBase context) { + this.primaryContext = context; + } + + /// <summary> + /// Gets the effective HttpContext object to use. + /// </summary> + private HttpContextBase Context { + get { + return this.primaryContext ?? new HttpContextWrapper(HttpContext.Current); + } + } + + /// <summary> + /// Gets the token secret from the specified token. + /// </summary> + /// <param name="token">The token.</param> + /// <returns> + /// The token's secret + /// </returns> + public 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); + 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 void ReplaceRequestTokenWithAccessToken(string requestToken, string accessToken, string accessTokenSecret) { + var cookie = new HttpCookie(TokenCookieKey) { + Value = string.Empty, + Expires = DateTime.UtcNow.AddDays(-5) + }; + this.Context.Response.Cookies.Set(cookie); + } + + /// <summary> + /// Stores the request token together with its secret. + /// </summary> + /// <param name="requestToken">The request token.</param> + /// <param name="requestTokenSecret">The request token secret.</param> + public void StoreRequestToken(string requestToken, string requestTokenSecret) { + var cookie = new HttpCookie(TokenCookieKey); + byte[] cookieBytes = Encoding.UTF8.GetBytes(requestTokenSecret); + var secretBytes = MachineKeyUtil.Protect(cookieBytes, TokenCookieKey, "Token:" + requestToken); + cookie.Values[requestToken] = HttpServerUtility.UrlTokenEncode(secretBytes); + this.Context.Response.Cookies.Set(cookie); + } + } +}
\ No newline at end of file diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth/LinkedInClient.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth/LinkedInClient.cs index d349576..ac8186d 100644 --- a/src/DotNetOpenAuth.AspNet/Clients/OAuth/LinkedInClient.cs +++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth/LinkedInClient.cs @@ -48,6 +48,9 @@ namespace DotNetOpenAuth.AspNet.Clients { /// <summary> /// Initializes a new instance of the <see cref="LinkedInClient"/> class. /// </summary> + /// <remarks> + /// Tokens exchanged during the OAuth handshake are stored in cookies. + /// </remarks> /// <param name="consumerKey"> /// The LinkedIn app's consumer key. /// </param> @@ -57,7 +60,7 @@ namespace DotNetOpenAuth.AspNet.Clients { [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) - : base("linkedIn", LinkedInServiceDescription, consumerKey, consumerSecret) { } + : this(consumerKey, consumerSecret, new AuthenticationOnlyCookieOAuthTokenManager()) { } /// <summary> /// Initializes a new instance of the <see cref="LinkedInClient"/> class. diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth/TwitterClient.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth/TwitterClient.cs index 0ec0780..96c1701 100644 --- a/src/DotNetOpenAuth.AspNet/Clients/OAuth/TwitterClient.cs +++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth/TwitterClient.cs @@ -28,15 +28,15 @@ namespace DotNetOpenAuth.AspNet.Clients { public static readonly ServiceProviderDescription TwitterServiceDescription = new ServiceProviderDescription { RequestTokenEndpoint = new MessageReceivingEndpoint( - "https://twitter.com/oauth/request_token", + "https://api.twitter.com/oauth/request_token", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest), UserAuthorizationEndpoint = new MessageReceivingEndpoint( - "https://twitter.com/oauth/authenticate", + "https://api.twitter.com/oauth/authenticate", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest), AccessTokenEndpoint = new MessageReceivingEndpoint( - "https://twitter.com/oauth/access_token", + "https://api.twitter.com/oauth/access_token", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest), TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() }, }; @@ -48,6 +48,9 @@ namespace DotNetOpenAuth.AspNet.Clients { /// <summary> /// Initializes a new instance of the <see cref="TwitterClient"/> class with the specified consumer key and consumer secret. /// </summary> + /// <remarks> + /// Tokens exchanged during the OAuth handshake are stored in cookies. + /// </remarks> /// <param name="consumerKey"> /// The consumer key. /// </param> @@ -57,7 +60,7 @@ namespace DotNetOpenAuth.AspNet.Clients { [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 TwitterClient(string consumerKey, string consumerSecret) - : base("twitter", TwitterServiceDescription, consumerKey, consumerSecret) { } + : this(consumerKey, consumerSecret, new AuthenticationOnlyCookieOAuthTokenManager()) { } /// <summary> /// Initializes a new instance of the <see cref="TwitterClient"/> class. |