I am building an expo app that leverages auth0 for authentication.
I have trouble switching to another account after I have successfully logged in and logged out. The details reproduce steps are:
Pull the project, yarn install && expo start --ios
(Optional) For your safety, replace auth0ClientId and auth0Domain in App.js with your own auth0 info
Press "Log in with Auth0", get a prompt, and finally see something like below
Log in with gmail (there should be such an option, even though it is not in this picture)
If you successfully log in, you should be able to see "You are logged in, !"
Press "Log out"
If you try to redo step 3-4, you are no longer able to see the universal login page as shown in the picture. Instead, you are logged in directly.
This thread describes the same behavior but he assumes it is client that caches the authentication info in cookie. I don't think this is the reason. I believe auth0 caches the first logged in user on server side and return the cached result regardless. My evidence: I add this console.log at https://github.com/ocdexperience/auth0-example/blob/master/App.js#L68 and every time I try to log in, this line always print that's why I guess await AuthSession.startAsync({ authUrl }) returns the cached result directly.
Thank you for the help.
It sounds like you are being logged in via silent authentication. This does indeed use a session cookie. To fully logout the user you must clear the cookie, or use the recommended method of utilizing the /logout endpoint.
You can test this by logging in with an incognito/private browsing window, or by clearing the cookie before clicking the login button the second time.
I have set up Django OAuth Toolkit in my project where the authorization server is separate from the application server (i.e accounts.example.com and app.example.com). App server redirects to accounts server using authorize flow; the user inputs credentials to sign in to auth server, then auth server redirects the user back to application; so that the app can retrieve tokens.
The above flow currently works as expected. If I do not click explicitly Log out the user and the application signs out (e.g session expires or browser cookies are cleared), the above flow will be performed again and there won't be a need for credentials because auth server still knows who is signed it.
However, I am having trouble with explicitly logging the user out of the application. If a user explicitly clicks login, firstly, the token must be revoked and secondly, the auth server must sign out. What is the proper way to achieve this? As far as I am concerned, I won't be able to use Ajax to log out the user because the session must be destroyed in auth server.
So, I have been thinking of redirecting the user to accounts.example.com/signout?token=${accessToken}&client_id=${clientID}. However, I am not sure if this is the right approach. Is this how these sign out requests work with OAuth? Does that mean that when I sign out from the system, I need to always provide Access Token and Client ID?
I'm using python-social-auth to allow users to login via SAML; everything's working correctly, except for the fact that if a logged-in user opens the SAML login page and logs in again as a different user, they'll get an association with both of the SAML users, rather than switch login.
I understand the purpose behind this (since it's what you can normally do to associate the user with different auth services) but in this case I need to enforce a single association (ie. if you're logged in with a given SAML IdP, you cannot add another association for the same user with the same provider).
Is there any python-social-auth solution for this, or should I cobble together something (for instance, preventing logged-in users from accessing the login page)?
There's no standard way to do it in python-social-auth, there are a few alternatives:
Override the login page and if there's a user authenticated, then log them out first, or show an error, whatever fits your projects.
Add a pipeline function and set it in the top that will act if user is not None, you can raise an error, logout the user, etc.
Override the backend and extend the auth_allowed method in it return False if there's a valid user instance at self.strategy.request.user. This will halt the auth flow and AuthForbidden will be raised.
I have a django-based site that has private content and a small number of necessary users. I would like for everyone to use their Google account to authenticate using python-social-auth (PSA). I would therefore like to use the following process to add new users:
The new user visits the site and clicks on a "request access" button.
PSA would create a disabled user. The requesting user would be redirected to a page stating that access will be granted within 24 hours if approved.
The site admin would receive an email message notifying her of the request. If the new user is approved, then his account is enabled and the user is notified. If the request is not approved then the disabled account is deleted.
Once the user is enabled, he will login using the pipeline from this tutorial that only authenticates registered users. That part's easy. The hard part is figuring out how I'm going to register users but not authenticate them.
I tried extending the SOCIAL_AUTH_PIPELINE by adding a custom pipeline function that disables users if they're new. However, the pipeline continues to execute at that time, and it appears that it then tries to authenticate the new, disabled user. I say this because I'm redirected in my app to this URL:
http://myapp.com/accounts/login/?next=/
...which for me is a 404. This URL seems to be generated by PSA.
So here are my questions:
Is it possible for me to drop out of the SOCIAL_AUTH_PIPELINE and redirect my user to a "please wait for authorization" screen if they're a new user? I don't think that I can use a "partial pipeline" for this because I don't want to pick up the pipeline again later - I just want to "drop out" if this is a new user.
If that's not possible, then what's option B? Is it creating a custom pipeline that only handles registration? If so, then how would one do that?
You can keep your pipeline that flags the user as disabled, but also define this setting SOCIAL_AUTH_INACTIVE_USER_URL = "/wait-for-activation" (point it to the URL that shows the "wait for activation" page).
I don't understand how google achieve the following mechanism of single sign on:
I login in gmail for example (I suppose this creates a cookie withmy authorization)
I open a new tab and direct type the url of "youtube"
Then I enter youtube logged in.
How can this second site detect that I've already been logged in.
They are different domains. Youtube can't read the cookie of Gmail.
All the solutions I've read about Single sign on don't allow this. The client always ask permission to a central login app.
In my example YouTube doesn't know I am the same user logged in Gmail (actually it does know, but I don't understand how)
Note that I type the url of "youtube" by hand. I don't clic the youtube icon from the upper toolbar of gmail (In that case gmail may pass some auth params through the url for example).
The cookies are set on specific domains. Ex:
setcookie(name,value,expire,path,domain)
When you log in on gmail, before "mail.google.com", you have been redirected to "accounts.google.com" then to "mail.google.com" so the cookies are on "accounts.google.com" too.
In this case, the domain is "accounts.google.com" and the path is "/" (the home path).
When you request "www.youtube.com" then you click on "connection" it requests
"accounts.google.com" fast so you can't see this redirection and checks if you have cookies on "accounts.google.com". If so, it checks if the cookies are valid and not expired, or user not banned... Then it redirects you to "www.youtube.com/signin?loginthisSession=Sessionid". This request contains the value of the of sessionid cookie catched from the cookies of "accounts.google.com".
In the last step, "www.youtube.com" logs you and set its own cookie on the domain "www.youtube.com" and saves them.
So the trick is on the 302 HTTP redirect.
Update
i do not know why people keep mentioning iframe take a look at the date whene this questions was posted on 2016 google was not using then iframe as i mentioned the capture of web traffic as you can see SetSID wich means set the cookie of SESSION_ID from accounts.google.dz(com) then redirects to youtube.com it can not be used trought iframe differant domains security measure you can not be redirected from domain to domain trought iframe neither please read this before posting
Cookies and localStorage can be shared between domains using an intermediate domain. On the home page is embedded an "iframe ', which accesses cookies and sends messages to the main.
mail.google.com and youtube.com can share the cookies using accounts.google.es. Open Chrome->Inspect->Resources->Local storage and you will see in accounts.google.com the authentication token in JWT format.
I have detailed the technical steps in this answer: https://stackoverflow.com/a/37565692/6371459. Also take a look at https://github.com/Aralink/ssojwt to see an implementation of a Single Sign On using JWT in a central domain
Check this out.. http://www.codeproject.com/Articles/106439/Single-Sign-On-SSO-for-cross-domain-ASP-NET-applic.
The article consist explanation and sample of SSO cross domain.
As far as I remember, if I am not wrong, cookies contains a specified field that contains the domain that can read and get such cookie. That is made in order to prevent certain web sites to read all your cookie list and make your own business. You should be able to see which kind of sites can 'see' your gmail cookie.
Correct me if I am wrong, this should compile the answer given regarding the SID and gmail-YouTube example..
While evaluating this cross domain SSO topic, I have come up with possible a new SSO synchronization flow using cookie with timestamp. Although it is not a flow used by Google, I think this flow is possible to implement for system with limited number of domains.
This flow do not use 3rd party cookie
This is going to be a long post :)
domains
To make an example, let say we have these domains for our example pet forums:
https://account.domain1.com (For SSO Login)
.domain1.com (e.g. https://cat.domain1.com)
.domain2.com (e.g. https://dog.domain2.com)
.domain3.com (e.g. https://rabbit.domain3.com)
Change to https://account.domain1.com:
Add https://account.domain2.com and https://account.domain3.com, route both host name traffic to the server hosting https://account.domain1.com
Login Steps:
User go to dog.domain2.com, user have not sign in yet.
User click the Login button in dog.domain2.com
User get redirect to account.domain1.com for login
This step can be any Login protocol, OAuth, OIDC, SAML, CAS, etc
So, it is important for user to be redirected back to original page after login
Let say this https://account.domain1.com?redirect_uri=https://dog.domain2.com
redirect_uri as in the URL to go back after login success
User Input username & password, login success
New step, before redirect back to https://dog.domain2.com, set cookies on all domains
Redirect browser to https://accounts.domain2.com?...
Set a cookie on the .domains2.com domain (More on the cookie value later)
Redirect browser to https://accounts.domain2.com?...
Set a cookie on the .domains3.com domain
Redirect browser to https://accounts.domain1.com?...
Set a cookie on the .domains1.com domain
Redirect back to original flow
Redirect user back to their original service, i.e. https://dog.domain2.com
Now, right after login flow we have cookies over all 3 domains. Any of our service (e.g. https://cat.domain1.com / https://dog.domain2.com / https://rabbit.domain2.com ) can access this cookie under their own domain.
Cookie Content
The content of the cookie, should allows for any webpage to look at it, and determine if SSO sync is needed
Different types of cookie content can be stored, including
Boolean indicate user logined or not
User ID
Expired At timestamp
Boolean indicate user logined or not
Storing have_user_login = true / false have sync issue
Suppose User A login, visit https://cat.domain1.com, User A Logout, and User B login
Now, from https://cat.domain1.com standpoint, no sync is needed
However, https://cat.domain1.com is storing User A instead of User B, hence the sync issue.
User ID
While it is tempting to just stored the user_id on those cookie, and let all the domain to see them and set the user accordingly.
This is way too dangerous, since the cookie is set at the parent domain,
if any of the website under your domain been hacked, impersonation might happen (Copying any of the user_id, pasting it to their own browser cookie).
Expired At Timestamp
What I suggest, is for the cookie value to set as the SSO expired time, and set the type as session cookie, this have the following benefits:
An expired time have minimal security impact if leaked / altered
Our website can check the expired time to know if user need to relogin
As for why session cookie, is for when user close them browser, and tried to login again, the cookie will be deleted hence logout the user as well
Any webpage that use the SSO, should also stored a cookie themselves with the same expired time
There will be cases that, User A Login, visit https://cat.domains1.com Then User B Login
Since User A and User B will have a different login expired time, storing and compare that timestamp will tell the user to sync with SSO again
Example checking implement for your service
E.g. On https://cat.domains1.com, you can add this to the top of your page load
<?php
$sso_expired_time = $_COOKIE["sso_expired_time "] ?? 0;
$website_expired_time = $_COOKIE["website_expired_time "] ?? 0;
if( (int) $sso_expired_time < time() || $sso_expired_time !== $website_expired_time ) {
// User not sync, perform sync
setcookie("website_expired_time", $website_expired_time,0,"/", $_SERVER['SERVER_NAME'], true, true);
// Redirect to https://account.domain1.com for Login
// Or, Initiate the login sequence for your selected login protocol
header("Location: https://account.domain1.com/.....")
exit;
}
// User is sync
// Page load success, continue other operation
Logout
Login is very similar to Login, basically:
Before logout goes through, redirect to all 3 domains just like login
Remove the SSO cookie
Continue the normal logout flow
Pro and cons for the methods:
Pro: All domain sync possible
Pro: No need to relies on 3rd party cookie
Cons: First time login longer (around 50ms longer)
Cons: Customization on every website is needed for the sync to works