summaryrefslogtreecommitdiffstats
path: root/samples/DotNetOpenAuth.ApplicationBlock/TwitterConsumer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'samples/DotNetOpenAuth.ApplicationBlock/TwitterConsumer.cs')
-rw-r--r--samples/DotNetOpenAuth.ApplicationBlock/TwitterConsumer.cs118
1 files changed, 117 insertions, 1 deletions
diff --git a/samples/DotNetOpenAuth.ApplicationBlock/TwitterConsumer.cs b/samples/DotNetOpenAuth.ApplicationBlock/TwitterConsumer.cs
index 29973c2..2e160f4 100644
--- a/samples/DotNetOpenAuth.ApplicationBlock/TwitterConsumer.cs
+++ b/samples/DotNetOpenAuth.ApplicationBlock/TwitterConsumer.cs
@@ -7,10 +7,13 @@
namespace DotNetOpenAuth.ApplicationBlock {
using System;
using System.Collections.Generic;
+ using System.Configuration;
using System.IO;
using System.Net;
+ using System.Web;
using System.Xml;
using System.Xml.Linq;
+ using System.Xml.XPath;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth;
using DotNetOpenAuth.OAuth.ChannelElements;
@@ -20,7 +23,8 @@ namespace DotNetOpenAuth.ApplicationBlock {
/// </summary>
public static class TwitterConsumer {
/// <summary>
- /// The description of Twitter's OAuth protocol URIs.
+ /// The description of Twitter's OAuth protocol URIs for use with actually reading/writing
+ /// a user's private Twitter data.
/// </summary>
public static readonly ServiceProviderDescription ServiceDescription = new ServiceProviderDescription {
RequestTokenEndpoint = new MessageReceivingEndpoint("http://twitter.com/oauth/request_token", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
@@ -30,6 +34,16 @@ namespace DotNetOpenAuth.ApplicationBlock {
};
/// <summary>
+ /// The description of Twitter's OAuth protocol URIs for use with their "Sign in with Twitter" feature.
+ /// </summary>
+ public static readonly ServiceProviderDescription SignInWithTwitterServiceDescription = new ServiceProviderDescription {
+ RequestTokenEndpoint = new MessageReceivingEndpoint("http://twitter.com/oauth/request_token", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
+ UserAuthorizationEndpoint = new MessageReceivingEndpoint("http://twitter.com/oauth/authenticate", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
+ AccessTokenEndpoint = new MessageReceivingEndpoint("http://twitter.com/oauth/access_token", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
+ TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() },
+ };
+
+ /// <summary>
/// The URI to get a user's favorites.
/// </summary>
private static readonly MessageReceivingEndpoint GetFavoritesEndpoint = new MessageReceivingEndpoint("http://twitter.com/favorites.xml", HttpDeliveryMethods.GetRequest);
@@ -43,6 +57,45 @@ namespace DotNetOpenAuth.ApplicationBlock {
private static readonly MessageReceivingEndpoint UpdateProfileImageEndpoint = new MessageReceivingEndpoint("http://twitter.com/account/update_profile_image.xml", HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest);
+ private static readonly MessageReceivingEndpoint VerifyCredentialsEndpoint = new MessageReceivingEndpoint("http://api.twitter.com/1/account/verify_credentials.xml", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest);
+
+ private static InMemoryTokenManager ShortTermUserSessionTokenManager {
+ get {
+ var store = HttpContext.Current.Session;
+ var tokenManager = (InMemoryTokenManager)store["TwitterShortTermUserSessionTokenManager"];
+ if (tokenManager == null) {
+ string consumerKey = ConfigurationManager.AppSettings["twitterConsumerKey"];
+ string consumerSecret = ConfigurationManager.AppSettings["twitterConsumerSecret"];
+ if (IsTwitterConsumerConfigured) {
+ tokenManager = new InMemoryTokenManager(consumerKey, consumerSecret);
+ store["TwitterShortTermUserSessionTokenManager"] = tokenManager;
+ } else {
+ throw new InvalidOperationException("No Twitter OAuth consumer key and secret could be found in web.config AppSettings.");
+ }
+ }
+
+ return tokenManager;
+ }
+ }
+
+ private static WebConsumer signInConsumer;
+
+ private static object signInConsumerInitLock = new object();
+
+ private static WebConsumer TwitterSignIn {
+ get {
+ if (signInConsumer == null) {
+ lock (signInConsumerInitLock) {
+ if (signInConsumer == null) {
+ signInConsumer = new WebConsumer(SignInWithTwitterServiceDescription, ShortTermUserSessionTokenManager);
+ }
+ }
+ }
+
+ return signInConsumer;
+ }
+ }
+
/// <summary>
/// Initializes static members of the <see cref="TwitterConsumer"/> class.
/// </summary>
@@ -51,6 +104,13 @@ namespace DotNetOpenAuth.ApplicationBlock {
ServicePointManager.FindServicePoint(GetFavoritesEndpoint.Location).Expect100Continue = false;
}
+ public static bool IsTwitterConsumerConfigured {
+ get {
+ return !string.IsNullOrEmpty(ConfigurationManager.AppSettings["twitterConsumerKey"]) &&
+ !string.IsNullOrEmpty(ConfigurationManager.AppSettings["twitterConsumerSecret"]);
+ }
+ }
+
public static XDocument GetUpdates(ConsumerBase twitter, string accessToken) {
IncomingWebResponse response = twitter.PrepareAuthorizedRequestAndSend(GetFriendTimelineStatusEndpoint, accessToken);
return XDocument.Load(XmlReader.Create(response.GetResponseReader()));
@@ -87,5 +147,61 @@ namespace DotNetOpenAuth.ApplicationBlock {
string responseString = response.GetResponseReader().ReadToEnd();
return XDocument.Parse(responseString);
}
+
+ public static XDocument VerifyCredentials(ConsumerBase twitter, string accessToken) {
+ IncomingWebResponse response = twitter.PrepareAuthorizedRequestAndSend(VerifyCredentialsEndpoint, accessToken);
+ return XDocument.Load(XmlReader.Create(response.GetResponseReader()));
+ }
+
+ public static string GetUsername(ConsumerBase twitter, string accessToken) {
+ XDocument xml = VerifyCredentials(twitter, accessToken);
+ XPathNavigator nav = xml.CreateNavigator();
+ return nav.SelectSingleNode("/user/screen_name").Value;
+ }
+
+ /// <summary>
+ /// Prepares a redirect that will send the user to Twitter to sign in.
+ /// </summary>
+ /// <param name="forceNewLogin">if set to <c>true</c> the user will be required to re-enter their Twitter credentials even if already logged in to Twitter.</param>
+ /// <returns>The redirect message.</returns>
+ /// <remarks>
+ /// Call <see cref="OutgoingWebResponse.Send"/> or
+ /// <c>return StartSignInWithTwitter().<see cref="MessagingUtilities.AsActionResult">AsActionResult()</see></c>
+ /// to actually perform the redirect.
+ /// </remarks>
+ public static OutgoingWebResponse StartSignInWithTwitter(bool forceNewLogin) {
+ var redirectParameters = new Dictionary<string, string>();
+ if (forceNewLogin) {
+ redirectParameters["force_login"] = "true";
+ }
+ Uri callback = MessagingUtilities.GetRequestUrlFromContext().StripQueryArgumentsWithPrefix("oauth_");
+ var request = TwitterSignIn.PrepareRequestUserAuthorization(callback, null, redirectParameters);
+ return TwitterSignIn.Channel.PrepareResponse(request);
+ }
+
+ /// <summary>
+ /// Checks the incoming web request to see if it carries a Twitter authentication response,
+ /// and provides the user's Twitter screen name and unique id if available.
+ /// </summary>
+ /// <param name="screenName">The user's Twitter screen name.</param>
+ /// <param name="userId">The user's Twitter unique user ID.</param>
+ /// <returns>
+ /// A value indicating whether Twitter authentication was successful;
+ /// otherwise <c>false</c> to indicate that no Twitter response was present.
+ /// </returns>
+ public static bool TryFinishSignInWithTwitter(out string screenName, out int userId) {
+ screenName = null;
+ userId = 0;
+ var response = TwitterSignIn.ProcessUserAuthorization();
+ if (response == null) {
+ return false;
+ }
+
+ XDocument xml = VerifyCredentials(TwitterSignIn, response.AccessToken);
+ XPathNavigator nav = xml.CreateNavigator();
+ screenName = nav.SelectSingleNode("/user/screen_name").Value;
+ userId = int.Parse(nav.SelectSingleNode("/user/id").Value);
+ return true;
+ }
}
}