(Part 1 is here)
The main part of the Openid support is in the controllers and in the view. Fortunately the heavy lifting has been done already, with a library called DotNetOpenId and sample code that started life in Rob Connery's storefront sample, and was worked on by my colleagues Howard Van Rooijen and Pete Worthington before I got hold of it.
First, install the DotNetOpenId library and reference it from the Oxite.MVC project
Add an action called OpenIdSignIn to AccountController:
public ActionResult OpenIdSignIn()
var openid = new OpenIdRelyingParty();
if (openid.Response == null)
string claimedUrl = Request["openid.claimed_id"];
// Stage 2: user submitting Identifier
if (Identifier.TryParse(claimedUrl, out id))
IAuthenticationRequest request = openid.CreateRequest(claimedUrl);
// email and display name would be nice, but we can do without it
ClaimsRequest claimsRequest = new ClaimsRequest
Email = DemandLevel.Request,
Nickname = DemandLevel.Request
ModelState.AddModelError("_FORM", "Invalid identifier");
// Stage 3: OpenID Provider sending assertion response
ClaimsResponse claimsResponse = openid.Response.GetExtension<ClaimsResponse>();
// did we get a claims response?
if (claimsResponse == null)
nickname = openid.Response.ClaimedIdentifier.ToString();
email = string.Empty;
nickname = claimsResponse.Nickname;
email = claimsResponse.Email;
LogOpenIdLogin(openid.Response.ClaimedIdentifier, nickname, email);
ModelState.AddModelError("_FORM", "Canceled at provider");
return new EmptyResult();
private void LogOpenIdLogin(Identifier claimedIdentifier, string nickname, string email)
// if the user record does not exist, create it
string userName = claimedIdentifier.ToString();
IUser user = MembershipRepository.GetUser(userName);
if (user == null)
Guid defaultLanguageID = LanguageRepository.GetLanguage(Config.Site.LanguageDefault).ID;
MembershipRepository.AddOpenIdUser(userName, nickname, email, defaultLanguageID);
And in the SignIn.aspx view add a form for the OpenId to be entered:
<h2>Use Your Open ID</h2>
<form method="post" action="<% =Url.Action("OpenIdSignIn") %>" class="login">
<!-- BEGIN ID SELECTOR -->
<input type="text" class="openidinput" size="40" id="openid.claimed_id" name="openid.claimed_id" />
idselector_input_id = "openid.claimed_id";
<!-- END ID SELECTOR -->
<input type="submit" value="<%= Localize("Login") %>" class="submit button" />
Open ID is an identity system that allows you to sign in to websites with a single account.
Your username and password are secure with Open ID - and you don't have to remember yet another password.
And that's all.
There’s lots more that can be done with OpenId here. For instance, the OpenId login form would be useful on the comments page - OpenId users are more likely to be just casual commenters, whereas the people writing the blog could take the time to make a local login. The users created via OpenId do not have any permissions, so they can add comments but not post; which is a sensible default.
I have more than one OpenId, so it would be nice to group them together into my account. Oxite is not yet an OpenId provider, which would be interesting.
A mature system would be able to block open ids based on patterns in the url, allowing or disallowing providers based on security considerations. But Oxite first should gain ability to list users, and change their permissions – e.g. admin, editor, contributor or locked out, and track the user's time and IP of the last login, etc
I’m sure that I made mistakes in this implementation – there’s lots that I don’t know about MVC and about OpenId.