views:

56

answers:

2

I'm trying to use a single HTTPHandler to authenticate a user's open id and receive a claimresponse. The initial authentication works, but the claimresponse does not. The error I receive is "This webpage has a redirect loop." What am I doing wrong?

public class OpenIdLogin : IHttpHandler
{
    private HttpContext _context = null;

    public void ProcessRequest(HttpContext context)
    {
        _context = context;
        var openid = new OpenIdRelyingParty();
        var response = openid.GetResponse();
        if (response == null)
        {
            // Stage 2: user submitting Identifier
            openid.CreateRequest(context.Request.Form["openid_identifier"]).RedirectToProvider();
        }
        else
        {
            // Stage 3: OpenID Provider sending assertion response
            switch (response.Status)
            {
                case AuthenticationStatus.Authenticated:
                    //FormsAuthentication.RedirectFromLoginPage(response.ClaimedIdentifier, false);
                    string identifier = response.ClaimedIdentifier;

                    //****** TODO only proceed if we don't have the user's extended info in the database **************

                    ClaimsResponse claim = response.GetExtension<ClaimsResponse>();
                    if (claim == null)
                    {
                        //IAuthenticationRequest req = openid.CreateRequest(identifier);
                        IAuthenticationRequest req = openid.CreateRequest(Identifier.Parse(identifier));

                        var fields = new ClaimsRequest();
                        fields.Email = DemandLevel.Request;
                        req.AddExtension(fields);
                        req.RedirectingResponse.Send(); //Is this correct?
                    }
                    else
                    {
                        context.Response.ContentType = "text/plain";
                        context.Response.Write(claim.Email); //claim.FullName;
                    }
                    break;
                case AuthenticationStatus.Canceled:
       //TODO   
                    break;
                case AuthenticationStatus.Failed:
       //TODO   
                    break;
            }
        }
    }
A: 

Generally once you get an accepted request, you want to store the claimed identifier and use it for the rest of the session. The message likely means that the provider is denying your request because it believes you have a redirect loop. Instead of verifying the ID on every request, you should accept that the user is authenticated until the session ends.

NickLarsen
+1  A: 

The redirect loop is because if you ever get a positive assertion back without an email you send the user right back to ask for it... over and over... The trouble is that some OPs will never give you an email address. And these same OPs may just immediately redirect with another positive assertion that again lacks email address.

When claims don't come back with a positive assertion, you need to show the user a page of your own asking him for those claims personally.

Andrew Arnott
Thanks! Although, I haven't tested yet, you're answer makes sense! What I need to do then is have a mechanism to request the claim only once regardless success/fail of the claim request.
Mark E