//-----------------------------------------------------------------------
//
// Copyright (c) Microsoft. All rights reserved.
//
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.AspNet.Clients {
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Web;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.RelyingParty;
///
/// Base classes for OpenID clients.
///
public class OpenIdClient : IAuthenticationClient {
#region Constants and Fields
///
/// The _openid relaying party.
///
private static readonly OpenIdRelyingParty RelyingParty =
new OpenIdRelyingParty(new StandardRelyingPartyApplicationStore());
///
/// The _provider identifier.
///
private readonly Identifier providerIdentifier;
///
/// The _provider name.
///
private readonly string providerName;
#endregion
#region Constructors and Destructors
///
/// Initializes a new instance of the class.
///
///
/// Name of the provider.
///
///
/// The provider identifier, which is the usually the login url of the specified provider.
///
public OpenIdClient(string providerName, Identifier providerIdentifier) {
Requires.NotNullOrEmpty(providerName, "providerName");
Requires.NotNull(providerIdentifier, "providerIdentifier");
this.providerName = providerName;
this.providerIdentifier = providerIdentifier;
}
#endregion
#region Public Properties
///
/// Gets the name of the provider which provides authentication service.
///
public string ProviderName {
get {
return this.providerName;
}
}
#endregion
#region Public Methods and Operators
///
/// Attempts to authenticate users by forwarding them to an external website, and upon succcess or failure, redirect users back to the specified url.
///
///
/// The context of the current request.
///
///
/// The return url after users have completed authenticating against external website.
///
[SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings",
Justification = "We don't have a Uri object handy.")]
public virtual void RequestAuthentication(HttpContextBase context, Uri returnUrl) {
Requires.NotNull(returnUrl, "returnUrl");
var realm = new Realm(returnUrl.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped));
IAuthenticationRequest request = RelyingParty.CreateRequest(this.providerIdentifier, realm, returnUrl);
// give subclasses a chance to modify request message, e.g. add extension attributes, etc.
this.OnBeforeSendingAuthenticationRequest(request);
request.RedirectToProvider();
}
///
/// Check if authentication succeeded after user is redirected back from the service provider.
///
///
/// The context of the current request.
///
///
/// An instance of containing authentication result.
///
public virtual AuthenticationResult VerifyAuthentication(HttpContextBase context) {
IAuthenticationResponse response = RelyingParty.GetResponse();
if (response == null) {
throw new InvalidOperationException(WebResources.OpenIDFailedToGetResponse);
}
if (response.Status == AuthenticationStatus.Authenticated) {
string id = response.ClaimedIdentifier;
string username;
Dictionary extraData = this.GetExtraData(response) ?? new Dictionary();
// try to look up username from the 'username' or 'email' property. If not found, fall back to 'friendly id'
if (!extraData.TryGetValue("username", out username) && !extraData.TryGetValue("email", out username)) {
username = response.FriendlyIdentifierForDisplay;
}
return new AuthenticationResult(true, this.ProviderName, id, username, extraData);
}
return AuthenticationResult.Failed;
}
#endregion
#region Methods
///
/// Gets the extra data obtained from the response message when authentication is successful.
///
///
/// The response message.
///
/// Always null.
protected virtual Dictionary GetExtraData(IAuthenticationResponse response) {
return null;
}
///
/// Called just before the authentication request is sent to service provider.
///
///
/// The request.
///
protected virtual void OnBeforeSendingAuthenticationRequest(IAuthenticationRequest request) { }
#endregion
}
}