namespace MvcRelyingParty.Controllers {
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Security.Principal;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using System.Web.UI;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
using DotNetOpenAuth.OpenId.RelyingParty;
using RelyingPartyLogic;
[HandleError]
public class AccountController : Controller {
///
/// Initializes a new instance of the class.
///
///
/// This constructor is used by the MVC framework to instantiate the controller using
/// the default forms authentication and OpenID services.
///
public AccountController()
: this(null, null) {
}
///
/// Initializes a new instance of the class.
///
/// The forms auth.
/// The relying party.
///
/// This constructor is not used by the MVC framework but is instead provided for ease
/// of unit testing this type.
///
public AccountController(IFormsAuthentication formsAuth, IOpenIdRelyingParty relyingParty) {
this.FormsAuth = formsAuth ?? new FormsAuthenticationService();
this.RelyingParty = relyingParty ?? new OpenIdRelyingPartyService();
}
///
/// Gets the forms authentication module to use.
///
public IFormsAuthentication FormsAuth { get; private set; }
///
/// Gets the OpenID relying party to use for logging users in.
///
public IOpenIdRelyingParty RelyingParty { get; private set; }
///
/// Gets the realm to report to the Provider for authentication.
///
/// The URL of this web application's root.
public Realm Realm {
get {
UriBuilder builder = new UriBuilder(Request.Url);
builder.Path = Request.ApplicationPath;
return builder.Uri;
}
}
///
/// Prepares a web page to help the user supply his login information.
///
/// The action result.
public ActionResult LogOn() {
return View();
}
///
/// Accepts the login information provided by the user and redirects
/// the user to their Provider to complete authentication.
///
/// The user-supplied identifier.
/// Whether the user wants a persistent cookie.
/// The URL to direct the user to after successfully authenticating.
/// The action result.
[AcceptVerbs(HttpVerbs.Post), ValidateAntiForgeryToken]
public ActionResult LogOn(string openid_identifier, bool rememberMe, string returnUrl) {
Identifier userSuppliedIdentifier;
if (Identifier.TryParse(openid_identifier, out userSuppliedIdentifier)) {
try {
var request = this.RelyingParty.CreateRequest(openid_identifier, this.Realm, Url.ActionFull("LogOnReturnTo"));
request.SetUntrustedCallbackArgument("rememberMe", rememberMe ? "1" : "0");
// This might be signed so the OP can't send the user to a dangerous URL.
// Of course, if that itself was a danger then the site is vulnerable to XSRF attacks anyway.
if (!string.IsNullOrEmpty(returnUrl)) {
request.SetUntrustedCallbackArgument("returnUrl", returnUrl);
}
// Ask for the user's email, not because we necessarily need it to do our work,
// but so we can display something meaningful to the user as their "username"
// when they log in with a PPID from Google, for example.
request.AddExtension(new ClaimsRequest {
Email = DemandLevel.Require,
FullName = DemandLevel.Request,
PolicyUrl = Url.ActionFull("PrivacyPolicy", "Home"),
});
return request.RedirectingResponse.AsActionResult();
} catch (ProtocolException ex) {
ModelState.AddModelError("OpenID", ex.Message);
}
} else {
ModelState.AddModelError("OpenID", "This doesn't look like a valid OpenID.");
}
return View();
}
///
/// Handles the positive assertion that comes from Providers.
///
/// The action result.
///
/// This method instructs ASP.NET MVC to not validate input
/// because some OpenID positive assertions messages otherwise look like
/// hack attempts and result in errors when validation is turned on.
///
[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post), ValidateInput(false)]
public ActionResult LogOnReturnTo() {
var response = this.RelyingParty.GetResponse();
if (response != null) {
switch (response.Status) {
case AuthenticationStatus.Authenticated:
bool rememberMe = response.GetUntrustedCallbackArgument("rememberMe") == "1";
this.FormsAuth.SignIn(response.ClaimedIdentifier, rememberMe);
string returnUrl = response.GetCallbackArgument("returnUrl");
if (!String.IsNullOrEmpty(returnUrl)) {
return Redirect(returnUrl);
} else {
return RedirectToAction("Index", "Home");
}
case AuthenticationStatus.Canceled:
ModelState.AddModelError("OpenID", "It looks like you canceled login at your OpenID Provider.");
break;
case AuthenticationStatus.Failed:
ModelState.AddModelError("OpenID", response.Exception.Message);
break;
}
}
// If we're to this point, login didn't complete successfully.
// Show the LogOn view again to show the user any errors and
// give another chance to complete login.
return View("LogOn");
}
///
/// Logs the user out of the site and redirects the browser to our home page.
///
/// The action result.
public ActionResult LogOff() {
this.FormsAuth.SignOut();
return RedirectToAction("Index", "Home");
}
}
}