javascriptdjangoopenidopenid-selector

Workaround bug in openid-selector (prototype.js version) that disables Google and Yahoo login buttons


I'm trying to use the prototype version of the openid selector found in openid-selector-1.3.zip, downloaded from Google Code 2011-May-03, with django-openid-auth

I've turned off demo mode in the javascript code.

The combination works with a launchpad.net openid but not with Google or Yahoo.

When I click Google or Yahoo, nothing happens! The button for google or yahoo renders as sunken. That's it. Also the django devserver never shows a form POST when clicking the Google or Yahoo buttons.

When pressing AOL a text field and a submit button is added to the form.... but this does not happen when pressing Google or Yahoo... no extra field and no sign-in/submit button.

I suspect a javascript error or a problem with naming or id-ing the elements. My hope is that someone who has done this before can quickly see the problem looking at how the form is set up in the template below.

The browsers tested were Firefox 3.6.16 (linux), and google chrome (linux). They seem to function comparably, both will login the launchpad openid but do nothing beyond sinking the identifier button when google or yahoo is clicked.

Here's the django dev webserver log, showing that all the static pieces are being loaded. These are copied from the openid-selector distribution at code.google.com with only a couple of minor changes (turn off demo, set image directory). This is to show that the right pieces are being delivered (of course, these could also be cached so absence would not be conclusive...)

[03/May/2011 04:58:53] "GET / HTTP/1.1" 200 115
[03/May/2011 04:58:56] "GET /openid/login HTTP/1.1" 301 0
[03/May/2011 04:58:56] "GET /openid/login/ HTTP/1.1" 200 2182
[03/May/2011 04:58:56] "GET /static/css/openid.css HTTP/1.1" 200 1007
[03/May/2011 04:58:56] "GET /static/js/prototype.js HTTP/1.1" 200 162353
[03/May/2011 04:58:56] "GET /static/js/openid-prototype.js HTTP/1.1" 200 5931
[03/May/2011 04:58:56] "GET /static/js/openid-en.js HTTP/1.1" 200 2302
[03/May/2011 04:58:56] "GET /static/images/openid-providers-en.png HTTP/1.1" 200 15894

django-openid-auth only provides a text entry/submit button form as an example. But it supports a login.html template, so in project/templates/openid/login.html I have this template, which is being rendered:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <title>Please Login</title>
        <!-- Simple OpenID Selector -->
        <link type="text/css" rel="stylesheet" href="/static/css/openid.css" />
        <script type="text/javascript" src="/static/js/prototype.js"></script>
        <script type="text/javascript" src="/static/js/openid-prototype.js"></script>
        <script type="text/javascript" src="/static/js/openid-en.js"></script>
        <script type="text/javascript">
                document.observe('dom:loaded', function() {
                        openid.init('openid_identifier');
                });
        </script>
        <!-- /Simple OpenID Selector -->
        <style type="text/css">
                /* Basic page formatting */
                body {
                        font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
                }
        </style>
</head>

<body>
        <h2>Please Select Your Provider for Login</h2>
        <p>Select your identity provider from the list below. You will be sent there to log in and returned here as an identified user. There are no registration forms for this website or extra passwords to remember. </p>
{% if form.errors %}
<p class="errors">Please correct errors below:<br />
    {% if form.openid_identifier.errors %}
    <span class="error">{{ form.openid_identifier.errors|join:", " }}</span>
    {% endif %}
    {% if form.next.errors %}
    <span class="error">{{ form.next.errors|join:", " }}</span>
    {% endif %}
</p>
{% endif %}
        <br/>
        <!-- Simple OpenID Selector -->
        <form action="{{ action }}" name="fopenid" method="post" id="openid_form">
          {% csrf_token %}
                <input type="hidden" name="action" value="verify" />
                <fieldset>
                        <legend>Sign-in or Create New Account</legend>
                        <div id="openid_choice">
                                <p>Please click your account provider:</p>
                                <div id="openid_btns"></div>
                        </div>
                        <div id="openid_input_area">
                                <input id="openid_identifier" name="openid_identifier" type="text" maxlength="255" value="http://" />
                                <input id="openid_submit" type="submit" name="bsignin" value="Sign-In" />
                        </div>
                        <noscript>
                        <p>You need javascript and cookies enabled and an OpenID to use this site.  You are using a browser that does not support javascript or has javascript turned off.</p>
                        </noscript>
                </fieldset>
       </form>
        <!-- /Simple OpenID Selector -->
</body>
</html>

Any idea what the problem could be? I thought it could involve the naming of the form elements but I thought I maintained the original ids. I did change the form name of the text field.

This seems like it should be a solved problem so that I could simply download a version of openid-selector customized for django. But I couldn't find one. Is there a better way to go about this integration?


Solution

  • I was able to correct the Google/Yahoo button inactivity problem in openid-prototype.js by changing the form submission handling just a bit, as follows:

    STEP 1: In init(), openid-prototype.js approx line 47, change

    $('openid_form').submit=this.submit

    to

    $('openid_form').onsubmit=this.submit

    [The previous setting in STEP 1 seemed to be causing bizarre behavior when single stepping. However, function this.submit === openid.submit now only gets called when there is a submit button to click on. To preserve the original interface without adding a button, I changed the signin procedure for simple endpoints to call both functions in STEP 2]

    STEP 2: In signin(), openid-prototype.js approx line 95, change

    if (!onload) {$('openid_form').submit();}

    to

    if (!onload) {if (this.submit()){$('openid_form').submit();}}}

    After making these two changes, it worked. I could click on Google or Yahoo and the openid form would be POSTed to the form handling view in django-openid-auth