//-----------------------------------------------------------------------
//
// Copyright (c) Outercurve Foundation. All rights reserved.
//
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.OAuth {
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth.ChannelElements;
using DotNetOpenAuth.OAuth.Messages;
using DotNetOpenAuth.OpenId.Extensions.OAuth;
using DotNetOpenAuth.OpenId.RelyingParty;
using Validation;
///
/// A website or application that uses OAuth to access the Service Provider on behalf of the User
/// and can attach OAuth requests to outbound OpenID authentication requests.
///
///
/// The methods on this class are thread-safe. Provided the properties are set and not changed
/// afterward, a single instance of this class may be used by an entire web application safely.
///
public class WebConsumerOpenIdRelyingParty : Consumer {
///
/// Initializes a new instance of the class.
///
/// The endpoints and behavior of the Service Provider.
/// The host's method of storing and recalling tokens and secrets.
public WebConsumerOpenIdRelyingParty() {
}
///
/// Attaches an OAuth authorization request to an outgoing OpenID authentication request.
///
/// The OpenID authentication request.
/// The scope of access that is requested of the service provider.
public void AttachAuthorizationRequest(IAuthenticationRequest openIdAuthenticationRequest, string scope) {
Requires.NotNull(openIdAuthenticationRequest, "openIdAuthenticationRequest");
var authorizationRequest = new AuthorizationRequest {
Consumer = this.ConsumerKey,
Scope = scope,
};
openIdAuthenticationRequest.AddExtension(authorizationRequest);
}
///
/// Processes an incoming authorization-granted message from an SP and obtains an access token.
///
/// The OpenID authentication response that may be carrying an authorized request token.
/// The cancellation token.
///
/// The access token, or null if OAuth authorization was denied by the user or service provider.
///
///
/// The access token, if granted, is automatically stored in the .
/// The token manager instance must implement .
///
public async Task ProcessUserAuthorizationAsync(IAuthenticationResponse openIdAuthenticationResponse, CancellationToken cancellationToken = default(CancellationToken)) {
Requires.NotNull(openIdAuthenticationResponse, "openIdAuthenticationResponse");
// The OAuth extension is only expected in positive assertion responses.
if (openIdAuthenticationResponse.Status != AuthenticationStatus.Authenticated) {
return null;
}
// Retrieve the OAuth extension
var positiveAuthorization = openIdAuthenticationResponse.GetExtension();
if (positiveAuthorization == null) {
return null;
}
using (var client = this.CreateHttpClient(new AccessToken(positiveAuthorization.RequestToken, string.Empty))) {
var request = new HttpRequestMessage(this.ServiceProvider.TokenRequestEndpointMethod, this.ServiceProvider.TokenRequestEndpoint);
using (var response = await client.SendAsync(request, cancellationToken)) {
response.EnsureSuccessStatusCode();
// Parse the response and ensure that it meets the requirements of the OAuth 1.0 spec.
string content = await response.Content.ReadAsStringAsync();
var responseData = HttpUtility.ParseQueryString(content);
string accessToken = responseData[Protocol.TokenParameter];
string tokenSecret = responseData[Protocol.TokenSecretParameter];
ErrorUtilities.VerifyProtocol(!string.IsNullOrEmpty(accessToken), MessagingStrings.RequiredParametersMissing, typeof(AuthorizedTokenResponse).Name, Protocol.TokenParameter);
ErrorUtilities.VerifyProtocol(tokenSecret != null, MessagingStrings.RequiredParametersMissing, typeof(AuthorizedTokenResponse).Name, Protocol.TokenSecretParameter);
responseData.Remove(Protocol.TokenParameter);
responseData.Remove(Protocol.TokenSecretParameter);
return new AccessTokenResponse(accessToken, tokenSecret, responseData);
}
}
}
}
}