The following code demonstrates the problem I have, it is available on Github. When I remove the secure route for login the code works, but when I secure the page it doesn't. Or if I make the homepage secure:always / optional. This code won't work on your dev server unless you change the http scheme in main.py from https to http.
Why does this code not work with logins going over https?
app.yaml
application: testapp
version: 1
runtime: python27
api_version: 1
threadsafe: yes
libraries:
- name: webapp2
version: latest
handlers:
- url: /login
script: main.app
secure: always
- url: /.*
script: main.app
secure: never
main.py
import webapp2
from google.appengine.ext.webapp import template
from google.appengine.api import users
from login import LoginHandler
from admin import AdminHandler
class HomeHandler(webapp2.RequestHandler):
def get(self):
user = users.get_current_user()
if users.is_current_user_admin():
loggedin = "Admin"
values = {'loggedin': loggedin,
'logout_url': users.create_logout_url("/")}
elif user:
loggedin = "User"
values = {'loggedin': loggedin,
'logout_url': users.create_logout_url("/")}
else:
loggedin = "Anonymous"
values = {'loggedin': loggedin,
'logout_url': users.create_logout_url("/")}
self.response.out.write(template.render('home.html', values))
app = webapp2.WSGIApplication([
webapp2.Route(r'/', HomeHandler),
webapp2.Route(r'/login', LoginHandler, schemes=['https']),
webapp2.Route(r'/admin', AdminHandler, schemes=['https'])
], debug=True)
login.py
import webapp2
from google.appengine.ext.webapp import template
from google.appengine.api import users
# Login page Request Handler Class
class LoginHandler(webapp2.RequestHandler):
def get(self):
user = users.get_current_user()
values = {'login_url': users.create_login_url("/")}
self.response.out.write(template.render('login.html', values))
admin.py
import webapp2
from google.appengine.ext.webapp import template
from google.appengine.api import users
# Login page Request Handler Class
class AdminHandler(webapp2.RequestHandler):
def get(self):
user = users.get_current_user()
values = {'user': users.nickname()}
self.response.out.write(template.render('admin.html', values))
home.html
<html>
<body>
<p>Who is logged in: {{loggedin}}</p>
<ul>
<li>
{% ifequal loggedin "Anonymous" %}
<a href="/login">Login</a>
{% else %} <!-- user is logged in -->
<a href="{{logout_url}}">Logout</a>
{% endifequal %}
</li>
{% ifequal loggedin "Admin" %}
<li class="right">
<a href="/admin">Admin</a>
</li>
{% endifequal %}
</ul>
</body>
</html>
login.html
<html>
<body>
<ul>
<li>
<a href="{{login_url}}">Login</a>
</li>
</ul>
</body>
</html>
admin.html
<html>
<body>
<p>Your logged in as: {{user}}</p>
</body>
</html>
As you can see a very simple example, user clicks the login link, goes to the login page where they login with Google Authentication and redirected back to the unsecured home page. When the user gets back to the home page the expected behavior is that "Who is logged in" returns either admin/user/anonymous but all I get is anonymous, the logout url isn't added or the admin url for an admin user. If I make the login normal http then if I have a secure route to say /admin that request receives a 401 Error.
This code only works when I make make everything HTTPS. I know others are using secure login pages and still able to access the user information on unsecure pages. I believe this has to do with how the cookie is being set, but I am at a loss at what I'm doing wrong.
Have you checked with FireCookie (or similar) the cookie's details? The path, the domain and so on? Are you using different domain name for secured? like secure.app.com for https and www.app.com for http?
I never tried https on GAE, i'm just wondering trying to help so sorry if I'm saying obvious stuff.