//----------------------------------------------------------------------- // // 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 } }