summaryrefslogtreecommitdiffstats
path: root/src/DotNetOAuth/CommonConsumers/GoogleConsumer.cs
blob: b8c14e752a2da2426e643693fcf0d7416f63d8ba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//-----------------------------------------------------------------------
// <copyright file="GoogleConsumer.cs" company="Andrew Arnott">
//     Copyright (c) Andrew Arnott. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------

namespace DotNetOAuth.CommonConsumers {
	using System;
	using System.Collections.Generic;
	using System.Linq;
	using System.Xml.Linq;
	using DotNetOAuth.ChannelElements;
	using DotNetOAuth.Messaging;

	/// <summary>
	/// A consumer capable of communicating with Google Data APIs.
	/// </summary>
	public class GoogleConsumer : CommonConsumerBase {
		/// <summary>
		/// The Consumer to use for accessing Google data APIs.
		/// </summary>
		private static readonly ServiceProviderDescription GoogleDescription = new ServiceProviderDescription {
			RequestTokenEndpoint = new MessageReceivingEndpoint("https://www.google.com/accounts/OAuthGetRequestToken", HttpDeliveryMethods.AuthorizationHeaderRequest | HttpDeliveryMethods.GetRequest),
			UserAuthorizationEndpoint = new MessageReceivingEndpoint("https://www.google.com/accounts/OAuthAuthorizeToken", HttpDeliveryMethods.AuthorizationHeaderRequest | HttpDeliveryMethods.GetRequest),
			AccessTokenEndpoint = new MessageReceivingEndpoint("https://www.google.com/accounts/OAuthGetAccessToken", HttpDeliveryMethods.AuthorizationHeaderRequest | HttpDeliveryMethods.GetRequest),
			TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() },
		};

		/// <summary>
		/// A mapping between Google's applications and their URI scope values.
		/// </summary>
		private static readonly Dictionary<Applications, string> DataScopeUris = new Dictionary<Applications, string> {
			{ Applications.Contacts, "http://www.google.com/m8/feeds/" },
			{ Applications.Calendar, "http://www.google.com/calendar/feeds/" },
		};

		/// <summary>
		/// The URI to get contacts once authorization is granted.
		/// </summary>
		private static readonly MessageReceivingEndpoint GetContactsEndpoint = new MessageReceivingEndpoint("http://www.google.com/m8/feeds/contacts/default/full/", HttpDeliveryMethods.GetRequest);

		/// <summary>
		/// Initializes a new instance of the <see cref="GoogleConsumer"/> class.
		/// </summary>
		/// <param name="tokenManager">The token manager.</param>
		/// <param name="consumerKey">The consumer key.</param>
		public GoogleConsumer(ITokenManager tokenManager, string consumerKey)
			: base(GoogleDescription, tokenManager, consumerKey) {
		}

		/// <summary>
		/// The many specific authorization scopes Google offers.
		/// </summary>
		[Flags]
		public enum Applications : long {
			/// <summary>
			/// The Gmail address book.
			/// </summary>
			Contacts = 0x1,

			/// <summary>
			/// Appointments in Google Calendar.
			/// </summary>
			Calendar = 0x2,
		}

		/// <summary>
		/// Requests authorization from Google to access data from a set of Google applications.
		/// </summary>
		/// <param name="requestedAccessScope">The requested access scope.</param>
		public void RequestAuthorization(Applications requestedAccessScope) {
			Uri callback = MessagingUtilities.GetRequestUrlFromContext().StripQueryArgumentsWithPrefix(Protocol.Default.ParameterPrefix);
			var extraParameters = new Dictionary<string, string> {
				{ "scope", this.GetScopeUri(requestedAccessScope) },
			};
			var request = this.Consumer.PrepareRequestUserAuthorization(callback, extraParameters, null);
			this.Consumer.Channel.Send(request).Send();
		}

		/// <summary>
		/// Gets the access token on the next page request after a call to <see cref="RequestAuthorization"/>.
		/// </summary>
		/// <returns>The access token that should be stored for later use.</returns>
		public string GetAccessToken() {
			var response = this.Consumer.ProcessUserAuthorization();
			return response != null ? response.AccessToken : null;
		}

		/// <summary>
		/// Gets the Gmail address book's contents.
		/// </summary>
		/// <param name="accessToken">The access token previously retrieved from the <see cref="GetAccessToken"/> method.</param>
		/// <returns>An XML document returned by Google.</returns>
		public XDocument GetContacts(string accessToken) {
			var response = this.PrepareAuthorizedRequestAndSend(GetContactsEndpoint, accessToken);
			XDocument result = XDocument.Parse(response.Body);
			return result;
		}

		/// <summary>
		/// A general method for sending OAuth-authorized requests for user data from Google.
		/// </summary>
		/// <param name="endpoint">The Google URL to retrieve the data from.</param>
		/// <param name="accessToken">The access token previously retrieved from the <see cref="GetAccessToken"/> method.</param>
		/// <returns>Whatever the response Google sends.</returns>
		public Response PrepareAuthorizedRequestAndSend(MessageReceivingEndpoint endpoint, string accessToken) {
			return this.Consumer.PrepareAuthorizedRequestAndSend(endpoint, accessToken);
		}

		/// <summary>
		/// Gets the scope URI in Google's format.
		/// </summary>
		/// <param name="scope">The scope, which may include one or several Google applications.</param>
		/// <returns>A space-delimited list of URIs for the requested Google applications.</returns>
		private string GetScopeUri(Applications scope) {
			return string.Join(" ", GetIndividualFlags(scope).Select(app => DataScopeUris[(Applications)app]).ToArray());
		}
	}
}