Question

I am using GAE Python with Django. I tried the following in my code:

Relevant Python code:

providers = { 
    'Google'   : 'https://www.google.com/accounts/o8/ud', 
    'Yahoo'    : 'yahoo.com',  
} 

class BaseRequestHandler(webapp2.RequestHandler): 
    def generate(self, template_name, template_values={}): 
       directory = os.path.dirname(__file__) 
       path = os.path.join(directory, 'templates', template_name) 
       self.response.out.write(template.render(path, template_values, debug=_DEBUG)) 

class MainHandler(BaseRequestHandler): 
    def get(self): 
        user = users.get_current_user() 
        log_in_out_url = users.create_login_url(federated_identity="https://www.google.com/accounts/o8/id") 
        if user: 
            log_in_out_url = users.create_logout_url(self.request.uri) 
        template_values = { 
                          'user': user, 
                          'log_in_out_url': log_in_out_url, 
                          "openid_url_google": providers["Google"], 
                          "openid_url_yahoo": providers["Yahoo"], 
                        } 
        self.generate('homepage.html', template_values); 

Relevant HTML code:

<div id="login_username" > 
    {% if user %} 
        <span class="loginout"> <a href="{{log_in_out_url}}"> Log Out </a> </span> 
    {% else %} 
        <span class="loginout"> <a href="{{log_in_out_url}}"> Log In </a> </span> 
    {% endif %} 

    <ul class="dropdown" id="openid_login_providers" > 
        <li> <a href="{{ openid_url_google }}" > Google </a> </li> 
        <li> <a href="{{ openid_url_yahoo }}" > Yahoo </a> </li> 
    </ul> 
</div > 

On "Inspect Element" in Chrome(when run on my Development server), i see the following substitution by Django:

<div id="login_username"> 
    <span class="loginout"> <a href="/_ah/login?continue=http%3A//localhost%3A8080/"> Log In </a> </span> 
    <ul class="dropdown" id="openid_login_providers"> 
        <li> <a href="https://www.google.com/accounts/o8/id"> Google </a> </li> 
        <li> <a href="yahoo.com"> Yahoo </a> </li> 
    </ul> 
</div> 

[based on the python example provided on https://developers.google.com/appengine/articles/openid?csw=1 ]

When the Google link is clicked, a file named "id" gets downloaded which contains:

<?xml version="1.0" encoding="UTF-8"?>
    <xrds:XRDS xmlns:xrds="xri://$xrds" xmlns="xri://$xrd*($v*2.0)">
        <XRD>
            <Service priority="0">
                <Type>http://specs.openid.net/auth/2.0/server</Type>
                <Type>http://openid.net/srv/ax/1.0</Type>
                <Type>http://specs.openid.net/extensions/ui/1.0/mode/popup</Type>
                <Type>http://specs.openid.net/extensions/ui/1.0/icon</Type>
                <Type>http://specs.openid.net/extensions/pape/1.0</Type>
                <URI>https://www.google.com/accounts/o8/ud</URI>
            </Service>
        </XRD>
</xrds:XRDS>

When the Yahoo link is clicked, it attempts to open the following link:

http://localhost:8080/yahoo.com 

I am sure I am missing something obvious but not able to figure that out. What am i doing wrong

I am interested to provide login support only to Direct Provider Federated Identities (like google and yahoo) where username would not be required to be passed

Changes as per Lipis suggestion:

class Federated(BaseRequestHandler): 
    def get(self): 
        provider_uri = self.request.get('provider') 
        log_in_out_url = "" 
        user = users.get_current_user() 
        if user: 
            log_in_out_url = users.create_logout_url(federated_identity=provider_uri) 
        else: 
            log_in_out_url = users.create_login_url(federated_identity=provider_uri) 
        self.redirect(log_in_out_url) 
        return 

<ul class="dropdown" id="openid_login_providers" > 
    <li> <a href="/federated?provider={{ openid_url_google }}" > Google </a> </li> 
    <li> <a href="/federated?provider={{ openid_url_yahoo }}" > Yahoo </a> </li> 
</ul> 
Was it helpful?

Solution

The providers strings that you have are not URLs that you can simply redirect users to but as mentioned in the official examples they are URIs that should be used in the federated_identity parameter of the create_login_url.

There reason that it points you to http://localhost:8080/yahoo.com is because you are missing the protocol in the <a href="yaho...", so what you have to do is to maybe link to something like this:

<a href="/federated?provider=yahoo.com">

Where you will handle the &provider argument and pass it to the create_login_url(federated_identity=provider) and continue from there.


Also instead of adding manually the providers you could provide all the providers to your template and render it like this:

{% for provider in providers %}
   <li><a href="/federated?provider={{providers[provider]}}">{{provider}}</a></li> 
{% endfor %}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top