开发者

How do I use DotNetOpenAuth with Google Apps for Domains as provider

开发者 https://www.devze.com 2023-03-24 22:59 出处:网络
I am using DotNetOpenAuth v3.5.0.10357 for OpenID support. The site was created using the DNOA VS 2010 MVC Template and I have modified it slightly (not using Ajax support or user controls - using Ope

I am using DotNetOpenAuth v3.5.0.10357 for OpenID support. The site was created using the DNOA VS 2010 MVC Template and I have modified it slightly (not using Ajax support or user controls - using OpenID jquery plugin instead). I am using the specific version because I also have implemented Facebook support. This is all working fine. But when I try and use Google apps it doesn't seem to be working as I'd expect. Here's what happens:

1) I submit my form using the following open id provider to : https://www.google.com/accounts/o8/site-xrds?ns=2&hd=example.com (I got this by inspecting the file returned by https://www.google.com/accounts/o8/.well-known/host-meta?hd=example.com)

2) I am redirected to google apps and asked to login with my google apps credentials.

3) I am redirected to: http://example.com/Auth/LogOnPostAssertion?dnoa.uipopup=1&dnoa.popupUISupported=1&index=0&dnoa.userSuppliedIdentifier=https://www.google.com/accounts/o8/site-xrds?ns=2&hd=example.com&dnoa.op_endpoint=https://www.google.com/a/example.com/o8/ud?be=o8&dnoa.claimed_id=&openid.ns=http://specs.openid.net/auth/2.0&openid.mode=id_res&openid.op_endpoint=https://www.google.com/a/example.com/o8/ud?be=o8&openid.response_nonce=2011-08-04T05:03:14ZmDjx966VdNKGAQ&openid.return_to=http://example.com/Auth/LogOnPostAssertion?dnoa.uipopup=1&dnoa.popupUISupported=1&index=0&dnoa.userSuppliedIdentifier=https%3A%2F%2Fwww.google.com%2Faccounts%2Fo8%2Fsite-xrds%3Fns%3D2%26hd%3Dexample.com&dnoa.op_endpoint=https%3A%2F%2Fwww.google.com%2Fa%2Fexample.com%2Fo8%2Fud%3Fbe%3Do8&dnoa.claimed_id=&openid.assoc_handle=redacted_value&openid.sig开发者_StackOverflowned=op_endpoint,claimed_id,identity,return_to,response_nonce,assoc_handle,ns.ext1,ext1.mode,ext1.type.alias3,ext1.value.alias3,ext1.type.alias1,ext1.value.alias1&openid.sig=redacted_value=&openid.identity=http://example.com/openid?id=redacted_value&openid.claimed_id=http://example.com/openid?id=redacted_value&openid.ns.ext1=http://openid.net/srv/ax/1.0&openid.ext1.mode=fetch_response&openid.ext1.type.alias3=http://schema.openid.net/contact/email&openid.ext1.value.alias3=mark.miller@example.com&openid.ext1.type.alias1=http://axschema.org/contact/email&openid.ext1.value.alias1=mark.miller@example.com&openid.ns.ext2=http://specs.openid.net/extensions/ui/1.0&openid.ext2.mode=popup

Then when RelyingParty.GetResponse() is called I am redirected to http://example.com/openid. I know if I'm hosting my own XRD I would need to provide a response, but it seems everything needed is in the response. Shouldn't it just read the values from the request, use the claimed identifier in the query string and be done with it? The controller action is below - the RelyingParty property is of type IOpenIDRelyingParty and wraps an instance of the OpenIdRelyingParty type from the DotNetOpenAuth library.

Should I be handling this case differently? Or is this scenario not fully supported? If it's not supported, does anyone have any direction on where I could add support myself?

public ActionResult LogOnPostAssertion(string openid_openidAuthData, string returnUrl){
var response = this.RelyingParty.GetResponse();
if (response == null)
{
    //Let us submit the request to OpenID provider
    Identifier id;
    if (Identifier.TryParse(openid_openidAuthData, out id))
    {
        try
        {
            var request = this.RelyingParty.CreateRequest(id, Realm.AutoDetect, Url.ActionFull("LogOnPostAssertion"), this.PrivacyPolicyUrl);
            return request.RedirectingResponse.AsActionResult();
        }
        catch (ProtocolException ex)
        {
            ViewBag.Message = ex.Message;
        }
    }
    else
    {
        ViewBag.Message = "Invalid identifier";
    }
} 

if (response != null && String.IsNullOrEmpty(ViewBag.Message))
{
    switch (response.Status)
    {
        case AuthenticationStatus.Authenticated:
            var token = RelyingPartyLogic.User.ProcessUserLogin(response);
            this.FormsAuth.SignIn(token.ClaimedIdentifier, false);
            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");

}

EDIT Ok, so after debugging the same process using my standard gmail account (eg. @gmail.com, not google apps domain, @example.com), I get back a response from google almost identical to the one above (#3). Everything is pretty much the same except for identifiers and things related to the parameter dnoa.userSuppliedIdentifier - which is expected. But the one thing that is not the same is the parameter openid.claimedid parameter. Here's what the two look like:

openid.claimed_id=http://example.com/openid?id=long_integer_value

openid.claimed_id=https://www.google.com/accounts/o8/id?id=some_hash_value

So it looks like DNOA must do a secondary verification to the OP (OpenID Provider) using the value of claimed_id. I'm guessing I need to provide an endpoint that responds at that url. However, my question then becomes, since I don't know the value "id" in advance how do I respond to the request from DNOA?


Ok, so I found the solution here

I created a new Action GoogleAppsLogOn which is the same as the action in my original question and added the following two lines of code at the top:

this.RelyingParty.DiscoveryServices.Clear();
this.RelyingParty.DiscoveryServices.Add(new HostMetaDiscoveryService() { UseGoogleHostedHostMeta = true });

Right before the call to RelyingParty.GetResponse(). If you're using the VS templates and relying party is an IOpenIdRelyingParty, you can simply add DiscoveryServices to the interface and the wrapper class provided in the RelyingPartyLogic project that is also part of the templates.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号