summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth.AspNet/Clients/OAuth/OAuthClient.cs
blob: 4152f0a50e9a5c6180635fff517c9fc76a6666a3 (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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
//-----------------------------------------------------------------------
// <copyright file="OAuthClient.cs" company="Microsoft">
//     Copyright (c) Microsoft. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------

namespace DotNetOpenAuth.AspNet.Clients {
	using System;
	using System.Diagnostics.CodeAnalysis;
	using System.Web;
	using DotNetOpenAuth.Messaging;
	using DotNetOpenAuth.OAuth;
	using DotNetOpenAuth.OAuth.ChannelElements;
	using DotNetOpenAuth.OAuth.Messages;
    using System.Collections.Generic;

	/// <summary>
	/// Represents base class for OAuth 1.0 clients
	/// </summary>
	public abstract class OAuthClient : IAuthenticationClient {
		#region Constructors and Destructors

		/// <summary>
		/// Initializes a new instance of the <see cref="OAuthClient"/> class.
		/// </summary>
		/// <param name="providerName">
		/// Name of the provider. 
		/// </param>
		/// <param name="serviceDescription">
		/// The service description. 
		/// </param>
		/// <param name="consumerKey">
		/// The consumer key. 
		/// </param>
		/// <param name="consumerSecret">
		/// The consumer secret. 
		/// </param>
		protected OAuthClient(
			string providerName, ServiceProviderDescription serviceDescription, string consumerKey, string consumerSecret)
			: this(providerName, serviceDescription, new InMemoryOAuthTokenManager(consumerKey, consumerSecret)) {}

		/// <summary>
		/// Initializes a new instance of the <see cref="OAuthClient"/> class.
		/// </summary>
		/// <param name="providerName">
		/// Name of the provider. 
		/// </param>
		/// <param name="serviceDescription">
		/// The service Description.
		/// </param>
		/// <param name="tokenManager">
		/// The token Manager.
		/// </param>
		[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "I don't know how to ensure this rule is followed given this API")]
		protected OAuthClient(
			string providerName, ServiceProviderDescription serviceDescription, IConsumerTokenManager tokenManager)
			: this(providerName, new DotNetOpenAuthWebConsumer(serviceDescription, tokenManager)) {}

		/// <summary>
		/// Initializes a new instance of the <see cref="OAuthClient"/> class.
		/// </summary>
		/// <param name="providerName">
		/// The provider name.
		/// </param>
		/// <param name="webWorker">
		/// The web worker.
		/// </param>
		/// <exception cref="ArgumentNullException">
		/// </exception>
		/// <exception cref="ArgumentNullException">
		/// </exception>
		protected OAuthClient(string providerName, IOAuthWebWorker webWorker) {
			Requires.NotNull(providerName, "providerName");
			Requires.NotNull(webWorker, "webWorker");

			this.ProviderName = providerName;
			this.WebWorker = webWorker;
		}

		#endregion

		#region Public Properties

		/// <summary>
		/// Gets the name of the provider which provides authentication service.
		/// </summary>
		public string ProviderName { get; private set; }

		#endregion

		#region Properties

		/// <summary>
		/// Gets the OAuthWebConsumer instance which handles constructing requests to the OAuth providers.
		/// </summary>
		protected IOAuthWebWorker WebWorker { get; private set; }

		#endregion

		#region Public Methods and Operators

		/// <summary>
		/// Attempts to authenticate users by forwarding them to an external website, and upon succcess or failure, redirect users back to the specified url.
		/// </summary>
		/// <param name="context">
		/// The context.
		/// </param>
		/// <param name="returnUrl">
		/// The return url after users have completed authenticating against external website. 
		/// </param>
		public virtual void RequestAuthentication(HttpContextBase context, Uri returnUrl) {
			Requires.NotNull(returnUrl, "returnUrl");
			Requires.NotNull(context, "context");

			Uri callback = returnUrl.StripQueryArgumentsWithPrefix("oauth_");
			this.WebWorker.RequestAuthentication(callback);
		}

		/// <summary>
		/// Check if authentication succeeded after user is redirected back from the service provider.
		/// </summary>
		/// <param name="context">
		/// The context.
		/// </param>
		/// <returns>
		/// An instance of <see cref="AuthenticationResult"/> containing authentication result. 
		/// </returns>
		public virtual AuthenticationResult VerifyAuthentication(HttpContextBase context) {
			AuthorizedTokenResponse response = this.WebWorker.ProcessUserAuthorization();
			if (response == null) {
				return AuthenticationResult.Failed;
			}

			AuthenticationResult result = this.VerifyAuthenticationCore(response);
            if (result.IsSuccessful && result.ExtraData != null)
            {
                // add the access token to the user data dictionary just in case page developers want to use it
                var wrapExtraData = result.ExtraData.IsReadOnly 
                    ? new Dictionary<string, string>(result.ExtraData) 
                    : result.ExtraData;
                wrapExtraData["accesstoken"] = response.AccessToken;

                AuthenticationResult wrapResult = new AuthenticationResult(
                    result.IsSuccessful,
                    result.Provider,
                    result.ProviderUserId,
                    result.UserName,
                    wrapExtraData
                );

                result = wrapResult;
            }

            return result;
		}

		#endregion

		#region Methods

		/// <summary>
		/// Check if authentication succeeded after user is redirected back from the service provider.
		/// </summary>
		/// <param name="response">
		/// The response token returned from service provider 
		/// </param>
		/// <returns>
		/// Authentication result 
		/// </returns>
		protected abstract AuthenticationResult VerifyAuthenticationCore(AuthorizedTokenResponse response);
		#endregion
	}
}