I know there are other questions about this, but they are outdated, and I cannot find the answer that would be reliable anywhere.
What is really used by Stack Overflow to autentificate users? The site DotNetOpenAuth claims it is. But to me the most (visually) similar looks to be OAuth C# Library.
So what does it really use? Or how can I mimic the same UI?
I want to create the very same OpenID authentication using ASP.NET MVC.
In OpenID we simply give a certificate symbolizing the person as legal and give access to whole database. Since stackoverflow or askubuntu belong to same domain they can exchange certificates with full access to user databases.
Is OpenID Dead? Yes, OpenID is an obsolete standard that is no longer supported by the OpenID Foundation.
OAuth is simply a secure authorization protocol that deals with the authorization of third-party applications to access the user data without exposing their password. (e.g. login with Facebook, gPlus, Twitter in many websites) all work under this protocol.
In mid-January 2008, Yahoo! announced initial OpenID 2.0 support, both as a provider and as a relying party, releasing the provider service by the end of the month. In early February, Google, IBM, Microsoft, VeriSign and Yahoo! joined the OpenID Foundation as corporate board members.
StackOverflow uses DotNetOpenAuth.
From the blog:
but fortunately we have an excellent dialog with Andrew Arnott, the primary author of the open source DotNetOpenAuth library we use
I was able to get OpenID authentication with DotNetOpenAuth
on my web site (www.mydevarmy.com) in a fairly short time (note that I am a total noob to ASP.NET, MVC, DotNetOpenAuth, etc).
DotNetOpenAuth
comes with various samples and they even have an ASP.NET MVC sample, but they only provide a View and Controller in that sample and they don't actually have a Model which is the M in MVC :). Subsequently I asked the following question on SO:
What are the responsibilities of the components in an MVC pattern for a simple login
So how would a VERY SIMPLE OpenID login look like in MVC? Well, let's take a look...
1. You will need a Model:
public class User
{
[DisplayName("User ID")]
public int UserID{ get; set; }
[Required]
[DisplayName("OpenID")]
public string OpenID { get; set; }
}
public class FormsAuthenticationService : IFormsAuthenticationService
{
public void SignIn(string openID, bool createPersistentCookie)
{
if (String.IsNullOrEmpty(openID)) throw new ArgumentException("OpenID cannot be null or empty.", "OpenID");
FormsAuthentication.SetAuthCookie(openID, createPersistentCookie);
}
public void SignOut()
{
FormsAuthentication.SignOut();
}
}
2. You will need a Controller:
[HandleError]
public class UserController : Controller
{
private static OpenIdRelyingParty openid = new OpenIdRelyingParty();
public IFormsAuthenticationService FormsService { get; set; }
protected override void Initialize(RequestContext requestContext)
{
if (FormsService == null)
{
FormsService = new FormsAuthenticationService();
}
base.Initialize(requestContext);
}
// **************************************
// URL: /User/LogIn
// **************************************
public ActionResult LogIn()
{
if (User.Identity.IsAuthenticated)
{
return RedirectToAction("Profile", "User");
}
Identifier openID;
if (Identifier.TryParse(Request.QueryString["dnoa.userSuppliedIdentifier"], out openID))
{
return LogIn(new User { OpenID = openID }, Request.QueryString["ReturnUrl"]);
}
else
{
return View();
}
}
[HttpPost]
public ActionResult LogIn(User model, string returnUrl)
{
string openID = ModelState.IsValid?model.OpenID:Request.Form["openid_identifier"];
if (User.Identity.IsAuthenticated)
{
return RedirectToAction("Profile", "User");
}
else if (!string.IsNullOrEmpty(openID))
{
return Authenticate(openID, returnUrl);
}
else if(ModelState.IsValid)
{
ModelState.AddModelError("error", "The OpenID field is required.");
}
// If we got this far, something failed, redisplay form
return View(model);
}
// **************************************
// URL: /User/LogOut
// **************************************
public ActionResult LogOut()
{
if (User.Identity.IsAuthenticated)
{
FormsService.SignOut();
}
return RedirectToAction("Index", "Home");
}
// **************************************
// URL: /User/Profile
// **************************************
[Authorize]
public ActionResult Profile(User model)
{
if (User.Identity.IsAuthenticated)
{
// ------- YOU CAN SKIP THIS SECTION ----------------
model = /*some code to get the user from the repository*/;
// If the user wasn't located in the database
// then add the user to our database of users
if (model == null)
{
model = RegisterNewUser(User.Identity.Name);
}
// --------------------------------------------------
return View(model);
}
else
{
return RedirectToAction("LogIn");
}
}
private User RegisterNewUser(string openID)
{
User user = new User{OpenID = openID};
// Create a new user model
// Submit the user to the database repository
// Update the user model in order to get the UserID,
// which is automatically generated from the DB.
// (you can use LINQ-to-SQL to map your model to the DB)
return user;
}
[ValidateInput(false)]
private ActionResult Authenticate(string openID, string returnUrl)
{
var response = openid.GetResponse();
if (response == null)
{
// Stage 2: user submitting Identifier
Identifier id;
if (Identifier.TryParse(openID, out id))
{
try
{
return openid.CreateRequest(openID).RedirectingResponse.AsActionResult();
}
catch (ProtocolException ex)
{
ModelState.AddModelError("error", "Invalid OpenID.");
ModelState.AddModelError("error", ex.Message);
return View("LogIn");
}
}
else
{
ModelState.AddModelError("error", "Invalid OpenID.");
return View("LogIn");
}
}
else
{
// Stage 3: OpenID Provider sending assertion response
switch (response.Status)
{
case AuthenticationStatus.Authenticated:
Session["FriendlyIdentifier"] = response.FriendlyIdentifierForDisplay;
FormsAuthentication.SetAuthCookie(response.FriendlyIdentifierForDisplay, true);
if (!string.IsNullOrEmpty(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Profile", "User");
}
case AuthenticationStatus.Canceled:
ModelState.AddModelError("error", "Authentication canceled at provider.");
return View("LogIn");
case AuthenticationStatus.Failed:
ModelState.AddModelError("error", "Authentication failed: " + response.Exception.Message);
return View("LogIn");
}
}
return new EmptyResult();
}
}
3. You will need a view:
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<YourProject.Models.User>" %>
<asp:Content ID="loginTitle" ContentPlaceHolderID="TitleContent" runat="server">
Log in - YourWebSiteName
</asp:Content>
<asp:Content ID="loginContent" ContentPlaceHolderID="MainContent" runat="server">
<p>
<%--- If you have a domain, then you should sign up for an affiliate id with MyOpenID or something like that ---%>
Please log in with your OpenID or <a href="https://www.myopenid.com/signup?affiliate_id=????">create an
OpenID with myOpenID</a> if you don't have one.
</p>
<%
string returnURL = HttpUtility.UrlEncode(Request.QueryString["ReturnUrl"]);
if (returnURL == null)
{
returnURL = string.Empty;
}
using (Html.BeginForm("LogIn", "User", returnURL))
{%>
<%= Html.LabelFor(m => m.OpenID)%>:
<%= Html.TextBoxFor(m => m.OpenID)%>
<input type="submit" value="Log in" />
<%
} %>
<%--- Display Errors ---%>
<%= Html.ValidationSummary()%>
</asp:Content>
Note that I have not provided you with the Profile
view, but that should be simple enough to figure out.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With