//----------------------------------------------------------------------- // // Copyright (c) Microsoft. All rights reserved. // //----------------------------------------------------------------------- namespace DotNetOpenAuth.AspNet.Clients { using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Web; /// /// Represents the base class for OAuth 2.0 clients /// public abstract class OAuth2Client : IAuthenticationClient { #region Constants and Fields /// /// The provider name. /// private readonly string providerName; /// /// The return url. /// private Uri returnUrl; #endregion #region Constructors and Destructors /// /// Initializes a new instance of the class with the specified provider name. /// /// /// Name of the provider. /// protected OAuth2Client(string providerName) { Requires.NotNull(providerName, "providerName"); this.providerName = providerName; } #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. /// /// /// The return url after users have completed authenticating against external website. /// public virtual void RequestAuthentication(HttpContextBase context, Uri returnUrl) { Requires.NotNull(context, "context"); Requires.NotNull(returnUrl, "returnUrl"); this.returnUrl = returnUrl; string redirectUrl = this.GetServiceLoginUrl(returnUrl).AbsoluteUri; context.Response.Redirect(redirectUrl, endResponse: true); } /// /// Check if authentication succeeded after user is redirected back from the service provider. /// /// /// The context. /// /// /// An instance of containing authentication result. /// public virtual AuthenticationResult VerifyAuthentication(HttpContextBase context) { Requires.NotNull(context, "context"); string code = context.Request.QueryString["code"]; if (string.IsNullOrEmpty(code)) { return AuthenticationResult.Failed; } string accessToken = this.QueryAccessToken(this.returnUrl, code); if (accessToken == null) { return AuthenticationResult.Failed; } IDictionary userData = this.GetUserData(accessToken); if (userData == null) { return AuthenticationResult.Failed; } string id = userData["id"]; string name; // Some oAuth providers do not return value for the 'username' attribute. // In that case, try the 'name' attribute. If it's still unavailable, fall back to 'id' if (!userData.TryGetValue("username", out name) && !userData.TryGetValue("name", out name)) { name = id; } // add the access token to the user data dictionary just in case page developers want to use it userData["accesstoken"] = accessToken; return new AuthenticationResult( isSuccessful: true, provider: this.ProviderName, providerUserId: id, userName: name, extraData: userData); } #endregion #region Methods /// /// Gets the full url pointing to the login page for this client. The url should include the specified return url so that when the login completes, user is redirected back to that url. /// /// /// The return URL. /// /// /// An absolute URL. /// [SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "Login", Justification = "Login is used more consistently in ASP.Net")] protected abstract Uri GetServiceLoginUrl(Uri returnUrl); /// /// Given the access token, gets the logged-in user's data. The returned dictionary must include two keys 'id', and 'username'. /// /// /// The access token of the current user. /// /// /// A dictionary contains key-value pairs of user data /// protected abstract IDictionary GetUserData(string accessToken); /// /// Queries the access token from the specified authorization code. /// /// /// The return URL. /// /// /// The authorization code. /// /// /// The access token /// protected abstract string QueryAccessToken(Uri returnUrl, string authorizationCode); #endregion } }