1
//-----------------------------------------------------------------------
2 // <copyright file="Consumer.cs" company="Andrew Arnott">
3 // Copyright (c) Andrew Arnott. All rights reserved.
5 //-----------------------------------------------------------------------
7 namespace DotNetOAuth
{
9 using System
.Collections
.Generic
;
12 using DotNetOAuth
.ChannelElements
;
13 using DotNetOAuth
.Messages
;
14 using DotNetOAuth
.Messaging
;
15 using DotNetOAuth
.Messaging
.Bindings
;
18 /// A website or application that uses OAuth to access the Service Provider on behalf of the User.
21 /// The methods on this class are thread-safe. Provided the properties are set and not changed
22 /// afterward, a single instance of this class may be used by an entire web application safely.
24 public class Consumer
{
26 /// Initializes a new instance of the <see cref="Consumer"/> class.
28 /// <param name="serviceDescription">The endpoints and behavior of the Service Provider.</param>
29 /// <param name="tokenManager">The host's method of storing and recalling tokens and secrets.</param>
30 public Consumer(ServiceProviderDescription serviceDescription
, ITokenManager tokenManager
) {
31 if (serviceDescription
== null) {
32 throw new ArgumentNullException("serviceDescription");
34 if (tokenManager
== null) {
35 throw new ArgumentNullException("tokenManager");
38 this.WebRequestHandler
= new StandardWebRequestHandler();
39 ITamperProtectionChannelBindingElement signingElement
= serviceDescription
.CreateTamperProtectionElement();
40 INonceStore store
= new NonceMemoryStore(StandardExpirationBindingElement
.DefaultMaximumMessageAge
);
41 this.Channel
= new OAuthChannel(signingElement
, store
, new OAuthConsumerMessageTypeProvider(tokenManager
), this.WebRequestHandler
);
42 this.ServiceProvider
= serviceDescription
;
43 this.TokenManager
= tokenManager
;
47 /// Gets or sets the Consumer Key used to communicate with the Service Provider.
49 public string ConsumerKey { get; set; }
52 /// Gets or sets the Consumer Secret used to communicate with the Service Provider.
54 public string ConsumerSecret { get; set; }
57 /// Gets the Service Provider that will be accessed.
59 public ServiceProviderDescription ServiceProvider { get; private set; }
62 /// Gets the persistence store for tokens and secrets.
64 public ITokenManager TokenManager { get; private set; }
67 /// Gets or sets the object that processes <see cref="HttpWebRequest"/>s.
70 /// This defaults to a straightforward implementation, but can be set
71 /// to a mock object for testing purposes.
73 internal IWebRequestHandler WebRequestHandler { get; set; }
76 /// Gets or sets the channel to use for sending/receiving messages.
78 internal OAuthChannel Channel { get; set; }
81 /// Begins an OAuth authorization request and redirects the user to the Service Provider
82 /// to provide that authorization. Upon successful authorization, the user is redirected
83 /// back to the current page.
85 /// <returns>The pending user agent redirect based message to be sent as an HttpResponse.</returns>
87 /// Requires HttpContext.Current.
89 public Response
RequestUserAuthorization() {
90 return this.RequestUserAuthorization(MessagingUtilities
.GetRequestUrlFromContext(), null, null);
94 /// Begins an OAuth authorization request and redirects the user to the Service Provider
95 /// to provide that authorization.
97 /// <param name="callback">
98 /// An optional Consumer URL that the Service Provider should redirect the
99 /// User Agent to upon successful authorization.
101 /// <param name="requestParameters">Extra parameters to add to the request token message. Optional.</param>
102 /// <param name="redirectParameters">Extra parameters to add to the redirect to Service Provider message. Optional.</param>
103 /// <returns>The pending user agent redirect based message to be sent as an HttpResponse.</returns>
104 public Response
RequestUserAuthorization(Uri callback
, IDictionary
<string, string> requestParameters
, IDictionary
<string, string> redirectParameters
) {
105 // Obtain an unauthorized request token.
106 var requestToken
= new RequestTokenMessage(this.ServiceProvider
.RequestTokenEndpoint
) {
107 ConsumerKey
= this.ConsumerKey
,
108 ConsumerSecret
= this.ConsumerSecret
,
110 requestToken
.AddNonOAuthParameters(requestParameters
);
111 var requestTokenResponse
= this.Channel
.Request
<UnauthorizedRequestTokenMessage
>(requestToken
);
112 this.TokenManager
.StoreNewRequestToken(this.ConsumerKey
, requestTokenResponse
.RequestToken
, requestTokenResponse
.TokenSecret
, null/*TODO*/);
114 // Request user authorization.
115 var requestAuthorization
= new DirectUserToServiceProviderMessage(this.ServiceProvider
.UserAuthorizationEndpoint
) {
117 RequestToken
= requestTokenResponse
.RequestToken
,
119 requestAuthorization
.AddNonOAuthParameters(redirectParameters
);
120 return this.Channel
.Send(requestAuthorization
);
124 /// Processes an incoming authorization-granted message from an SP and obtains an access token.
126 /// <returns>The access token, or null if no incoming authorization message was recognized.</returns>
128 /// Requires HttpContext.Current.
130 public GrantAccessTokenMessage
ProcessUserAuthorization() {
131 return this.ProcessUserAuthorization(this.Channel
.GetRequestFromContext());
135 /// Processes an incoming authorization-granted message from an SP and obtains an access token.
137 /// <param name="request">The incoming HTTP request.</param>
138 /// <returns>The access token, or null if no incoming authorization message was recognized.</returns>
139 public GrantAccessTokenMessage
ProcessUserAuthorization(HttpRequest request
) {
140 return this.ProcessUserAuthorization(new HttpRequestInfo(request
));
144 /// Creates a web request prepared with OAuth authorization
145 /// that may be further tailored by adding parameters by the caller.
147 /// <param name="endpoint">The URL and method on the Service Provider to send the request to.</param>
148 /// <param name="accessToken">The access token that permits access to the protected resource.</param>
149 /// <returns>The initialized WebRequest object.</returns>
150 public WebRequest
CreateAuthorizedRequest(MessageReceivingEndpoint endpoint
, string accessToken
) {
151 IDirectedProtocolMessage message
= this.CreateAuthorizedRequestInternal(endpoint
, accessToken
);
152 HttpWebRequest wr
= this.Channel
.InitializeRequest(message
);
157 /// Creates a web request prepared with OAuth authorization
158 /// that may be further tailored by adding parameters by the caller.
160 /// <param name="endpoint">The URL and method on the Service Provider to send the request to.</param>
161 /// <param name="accessToken">The access token that permits access to the protected resource.</param>
162 /// <returns>The initialized WebRequest object.</returns>
163 /// <exception cref="WebException">Thrown if the request fails for any reason after it is sent to the Service Provider.</exception>
164 public Response
SendAuthorizedRequest(MessageReceivingEndpoint endpoint
, string accessToken
) {
165 IDirectedProtocolMessage message
= this.CreateAuthorizedRequestInternal(endpoint
, accessToken
);
166 HttpWebRequest wr
= this.Channel
.InitializeRequest(message
);
167 return this.WebRequestHandler
.GetResponse(wr
);
171 /// Processes an incoming authorization-granted message from an SP and obtains an access token.
173 /// <param name="request">The incoming HTTP request.</param>
174 /// <returns>The access token, or null if no incoming authorization message was recognized.</returns>
175 internal GrantAccessTokenMessage
ProcessUserAuthorization(HttpRequestInfo request
) {
176 DirectUserToConsumerMessage authorizationMessage
;
177 if (this.Channel
.TryReadFromRequest
<DirectUserToConsumerMessage
>(request
, out authorizationMessage
)) {
178 // Exchange request token for access token.
179 string requestTokenSecret
= this.TokenManager
.GetTokenSecret(authorizationMessage
.RequestToken
);
180 var requestAccess
= new RequestAccessTokenMessage(this.ServiceProvider
.AccessTokenEndpoint
) {
181 RequestToken
= authorizationMessage
.RequestToken
,
182 TokenSecret
= requestTokenSecret
,
183 ConsumerKey
= this.ConsumerKey
,
184 ConsumerSecret
= this.ConsumerSecret
,
186 var grantAccess
= this.Channel
.Request
<GrantAccessTokenMessage
>(requestAccess
);
187 this.TokenManager
.ExpireRequestTokenAndStoreNewAccessToken(this.ConsumerKey
, authorizationMessage
.RequestToken
, grantAccess
.AccessToken
, grantAccess
.TokenSecret
);
195 /// Creates a web request prepared with OAuth authorization
196 /// that may be further tailored by adding parameters by the caller.
198 /// <param name="endpoint">The URL and method on the Service Provider to send the request to.</param>
199 /// <param name="accessToken">The access token that permits access to the protected resource.</param>
200 /// <returns>The initialized WebRequest object.</returns>
201 internal AccessProtectedResourcesMessage
CreateAuthorizedRequestInternal(MessageReceivingEndpoint endpoint
, string accessToken
) {
202 if (endpoint
== null) {
203 throw new ArgumentNullException("endpoint");
205 if (String
.IsNullOrEmpty(accessToken
)) {
206 throw new ArgumentNullException("accessToken");
209 AccessProtectedResourcesMessage message
= new AccessProtectedResourcesMessage(endpoint
) {
210 AccessToken
= accessToken
,
211 TokenSecret
= this.TokenManager
.GetTokenSecret(accessToken
),
212 ConsumerKey
= this.ConsumerKey
,
213 ConsumerSecret
= this.ConsumerSecret
,