I used gaesessions on Google App Engine with Python to handle user login sessions. The following are some of my codes:
When a user logs in:
from gaesessions import get_current_session
...
session = get_current_session()
if session.is_active():
session.terminate()
session['account'] = account
# Do some stuff to log the user in
When the user logs out:
session = get_current_session()
account = session['account']
# Do some stuff to log the user out
The above codes worked just fine most of the time, except that sometimes (very rarely, maybe once in a month) GAE complained about the statement account = session['account'] when the user logs out with the error message: KeyError: 'account' I wonder if anybody has encountered the same problem?
BTW, I also clean up expired sessions as below. Is it necessary? (I have no idea when a session goes expired) Or could it be the cause of the problem? Thanks.
while not delete_expired_sessions():
pass
Your session dictionary doesn't have the account key set to anything. This could be that a request runs your logout method without being logged in. This could happen by someone who is not logged in, yet visits your logout handler.
Eg. A user requests yourwebsite.com/logout without being actually logged in yet.
Related
I've been learning Auth0 for a React / React Native project. With two different apps now, including one from their site, I see the following behavior:
clear browser cache
login
enter password, now logged in
select logout
--> now logged out
select login
am NOT prompted for password again, just logged in without interaction.
It seems the session has been kept alive even though I logged out. I would expect that if I manually log out of an application, I must re-authorize with my password on the next login attempt.
As I said I've seen this twice now, once with my own project and once with the tutorial they provide at https://auth0.com/blog/react-tutorial-building-and-securing-your-first-app/ . Doesn't make any sense to me. Am I missing something?
Thanks ~~
This is the Seamless SSO behaviour explained here. This is now enabled by default on all tenants and it "seamlessly" logs the user in without showing any prompts if a session exists for the user in the Authorization server (Auth0 in this case). Previously you would get a prompt that said "Last time you logged in with ..." Clicking it would login you in without requiring a password.
If you are "Logging out" and yet you can log back in again without needing to enter credentials, the most likely explanation is that you are actually not calling the https://YOUR_AUTH0_DOMAIN/v2/logout endpoint which logs out the user by clearing their SSO cookie in Auth0. You can confirm this endpoint is called from Network tab in your browser when you click to logout.
The Auth0 React quickstart by default does not call the logout endpoint, it only removes the tokens from browser storage. To clear the SSO cookie and logout from IdP using Auth0.js you need to call the logout function as well. Refer to the Auth0.js logout function here.
Hope that helps.
I'm writing an app that uses Google API to authenticate with G+ account in our app.
Currently the customer wants on logging out not only revoke access token for our application but also log out from Google Account used to authenticate.
The solution I've come with was:
/**
* Signs the user out.
*/
HeaderCtrl.prototype.signOut = function() {
// this part revokes token
$http.jsonp('https://accounts.google.com/o/oauth2/revoke?token=' +
accessToken, {
params: {
callback: 'JSON_CALLBACK',
format: 'json'
}
}).success( /* Do stuff on success */);
// this part logs out from google account
$http.jsonp('https://accounts.google.com/logout');
};
The second call works but logs an error on response processing:
Refused to execute script from 'https://accounts.google.com/logout' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
What ways to log out from Google account using AngularJS would you use?
you should not log out your users from Google, they certainly don't want it anyway. Thus, https://accounts.google.com/logout should never be reached.
What you actually want is to make them log out from your website. Revoking the token should be enough for Google authentication's side (your website won't assume the client is logged from to his old token)
Once signOut method is called, just consider he isn't logged any more and end the session in your website.
I think you are tring to do many things that are not related to a "normal logout" experience.
Maybe you should talk to your "customer" to clarify the user stories he/she wants.
A normal logout is one line of js (source) :
gapi.auth.signOut();
If I'm not wrong, what you are doing first in your code (ie revoking the access token), is something that provides an option to remove the association between the account on your app and the google account used for sign-in. As indicated on the link, you must provide this option to the user to follow the g+ developer policies but it's not the same as signing out. Maybe you should try, as a user, these two feature on a site providing a g+ sign-in, such as stack overflow. (Be sure to know your password before revoking the g+ association.)
And for the log out of Google, your app should not do it, and Google should not provide you a way to do it. (And I'd rather think that it's impossible.)
However you can kindly remind your user, after log out, that he/she may need to log out from Google too. Try to log out from stack overflow and look at what happens.
I am running a Google App Engine project where everytime the user takes an action I want to check to see if the user is 1)logged in 2)an admin. This is the code I have for the appuser:
class AppUser
{
private UserService userService;
private User user;
public AppUser()
{
userService = UserServiceFactory.getUserService();
user = userService.getCurrentUser();
}
public IsAdministrator()
{
if(IsLoggedIn())
{
return userService.IsUserAdmin();
}
return false;
}
public IsLoggedIn()
{
return user == null;
}
}
When I log out with my app this works fine. However, if I log out on another page (like on google calendars or something) the app still thinks I'm logged in. Is there another better way to check if the user is still logged in?
Also I know that this can be done with security-constraint in the web.xml however that will not work in this case as I need to take certain actions if the user has logged off.
I am using App Engine SDK 1.7 and GWT SDK 2.4
Two ways to notify app about user logging out:
Synchronously - server actively notifies client (browser) about log-out. Use Channels API to send push notification to client. There is a GWT wrapper.
Asynchronously - server notifies client about log-out when client makes communication to server, i.e. in every RPC call add authentication check. If user id logged-out, raise an exception, which can be handled by GWT.
I ran into this today, though it was worse: I'd logged out as user A (from a Google Sites page), and logged in as user B, but my GAE app still thought I was logged in as user A. Argh.
The reason for this is that there are two cookies involved, one for tracking which Google user is logged into Google, and another for tracking which GAE application user is logged into my GAE application. Recall that a GAE could be using any federated authentication service, not just Google's. My application has no access to the google.com cookies, so I can't directly check whether user A is still logged in (or which user is currently logged in).
Unfortunately, I've not yet found a straight forward "federated logOUT" mechanism, though it is possible that Google Identity Toolkit can be used for detecting that the expected user is no longer logged in.
I found others discussing this issue:
How to manage multiple accounts login and logout in different browser pages?
UserService retrieves wrong user after logout
Update
I came up with a solution that works for my application, where I have a page that redirects the user, a student, to his or her classroom's home page. Since this is accessed infrequently by any one student (a few times a day), but which needs to know which student is logged in, I took the following approach which works for me:
User goes to page A, which clears the ACSID and SACSID cookies, and redirects to Google for the user to login.
User is probably already logged in, so Google (with several redirects) updates the ACSID and SACSID cookies to the currently logged in user, and redirects back to my application at page B.
Page B finally takes action on behalf of the logged in user, "confident" that the correct user is logged in (to the extent that pages are confident). ;-)
Here's a code sketch of the approach:
# My BaseHandler has a clear_cookie
class LoginAndRedirectHandler(base_handler.BaseHandler):
def get(self):
self.clear_cookie('ACSID')
self.clear_cookie('SACSID')
self.clear_cookie('dev_appserver_login')
if 'continue' in self.request.params and \
self.request.params['continue'].startswith('/'):
url = self.request.params['continue']
else:
# Whatever your page is that needs an up to date logged in user
url = users.create_login_url('/PageB')
if isinstance(url, unicode):
url = url.encode('utf8')
logging.info('Redirecting to ' + url)
self.redirect(url)
return
The reason I said infrequently above is that this process is expensive in time, with at least 4 or 5 redirects involved.
I am looking to implement Google Authenticator into a CakePHP application. The trick is that a user can determine whether or not they want to use it. This means that if a user is using the multi-part login, they will log in normally with their username and password. Once they have successfully submitted their correct username / password combination, they need to be redirected to the page that asks for their passcode from Google Authenticator.
How do you limit the Authentication success until AFTER they enter the passcode? I can do the redirect and everything just fine, but if they exit the passcode form and go to the site, they have already authenticated using their username / password and they can navigate through the site just fine.
I need some direction on how to shut down authentication until AFTER the passcode confirmation is successful. Any ideas?
I noticed this question is pretty old and unanswered, I also work on something similar so I'll share my two cents. Hope you've already solved this problem by now.
Your user management system should provide a session key only after the entire login process was fulfilled, this means that you should let users in only after they provide all auth data through all steps.
receive user and password
check credentials and authentication options
if credentials are ok and no Google Auth enabled, give him session key, else retry
if credetials are ok and Google Auth enabled, pass $_POST['user'] to challenge form
if TOTP password matches server-side check, return session key, else retry
$_POST[] ----> loginCheck() ----> if(GAuth) ----> checkTotp() ----> sessionKey
| |
*---------------------------------*
loginCheck() should check if user and passwords are ok, otherwise deny access
if(GAuth) should return true or false, depeding if your user uses GAuth
checkTotp should be a method to check TOTP password on client and server
sessionKey should be the token used to access protected content, stored server-side and client-side for a period of time
Or adapt this idea to your needs ... in my opinion you should accept the user in the system when he passes all authentication trials.
You could make an user form that hols user/password and passcode and process all data at once and avoid two pages.
Read more about https://www.rfc-editor.org/rfc/rfc6238
I'm using a very simple GAE instance from a Greasemonkey script. This worked fine for the last months, but now a path is appended to the final 'continue' location, which breaks the login process for me.
The basic workflow, under the assumption that the user is logged into his Google Account, but his token for the GAE instance has timed out:
User opens page A with the GM script installed.
The GM script runs and tries to access the GAE instance with a GM_xmlhttpRequest().
The GAE instance returns "login_needed|<loginurl>". The GM script extracts the loginurl and sets window.location on it.
The user is redirected to the loginurl and eventually back to A. However, this time, actual data is returned by the GM_xmlhttpRequest().
The last step no longer works, as the user is now redirected to the loginurl plus some, which gives a 404 on the target site.
The GAE code is just about half a screen of code. The authentication relevant code is this:
if not users.get_current_user():
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write('login_needed|'+users.create_login_url(self.request.get('uri')))
The sequence of requests is as follows, all caused by redirects:
GET https://mygaeinstance.appspot.com/?uri=https://targetsite.com/
GET https://www.google.com/accounts/ServiceLogin?service=ah&passive=true&continue=https://appengine.google.com/_ah/conflogin%3Fcontinue%3Dhttps://targetsite.com/<mpl=gm&ahname=MyGAEInstance&sig=<some sig>
GET https://appengine.google.com/_ah/conflogin?continue=https%3A%2F%2Ftargetsite.com%2F&pli=1&auth=<some base64 auth token>
GET https://targetsite.com/_ah/conflogin?state=<some base64 state>
targetsite.com doesn't like that path and as you can see, it wasn't in the initial 'continue' argument passed to appengine.google.com, which was just "https://targetsite.com/". What did I do wrong and how can I fix this?
A recent change to our login flow for App Engine has created an issue whereby a login with a continue URL that's outside the app's own domain will result in an erroneous redirect such as the one you're observing.
We're working on fixing this. In the meantime, a workaround is to set up a redirect handler on your own app. Make that the target of the continue parameter, and have it send a final redirect to your actual target.
This redirect is caused by an expired auth token. To make it work again, you need to invalidate the token on the client, as described here: What is the proper URL to get an Auth Cookie from a GAE based Application