Don't understand how to logout of FusionAuth from Django Application - python

I am writing a Django app that uses a 3rd-Party Authentication Service implemented with FusionAuth.
I can successfully register and login (using the authorization code flow).
However, logging out is not working. I can logout from the local Django app, but when I try to login after that FusionAuth recognizes that my access_token is still valid and just goes directly to the redirect page (the page you usually goto after successfully logging into FusionAuth).
Clearly I don't understand something about FusionAuth. I have tried both the python client and the restful API and I don't really understand what it does. According to the documentation it "...is intended to be used to remove the refresh token and access token cookies if they exist on the client and revoke the refresh token". Why then is the access_token still valid?

There seem like a couple of issues here.
First, you need to redirect the browser to https://your.fusionauth.instance/oauth2/logout and that will delete your FusionAuth SSO session. That will stop the behavior of FusionAuth redirecting you. This is because you have an SSO session cookie, and going to that URL will delete it.
Second, if you want to revoke the access token, that takes a bit more work. It is stateless. It's not the same as a session, and is distinct from the SSO session mentioned above. The access token is something you present to other APIs, not to FusionAuth. Here's some more info: https://fusionauth.io/learn/expert-advice/tokens/revoking-jwts
Hope this helps.

Related

How to test api with session in django

I am currently building an auth app that provides register, login, logout ... functionalities. Everything seems to work fine, however when I log the user in, I cannot logout, I get an Anonymous user error instead. After searching on the internet I came to the conclusion that it is not the best to build an api with sessions and instead to use tokens(JWT). With sessions I cannot test my API with tools like POSTMAN because that requires cookies (technically you can use cookies in POSTMAN though). Having said that, sessions seem to be more stable and secure so how would I go about testing my API using the sessions stored in the cookie? Thanks.
Postman supports using cookies.
when you enable it you can access it through scripts.
write a script for you login and logout to set cookies ( if it wasn't updated automatically)
you can read more about it here.

Best way to log a user out of several, owned websites?

I have several apps that connect to a central OAuth2 server (this is the only login method). When a user hits Log out, I want him to be logged out of all the apps and the OAuth server.
All the apps are Django at the moment but that might change, so I'm looking for the most cross-framework way to do it. I must also keep in mind that all the apps might handle sessions differently (some server-side, some client-side).
All logouts must be handled by POST requests as the good practice recommends.
The strategy I have in mind:
On the app, the user clicks on Log out
This Log out link points towards the logout page on the OAuth server, on which a POST request to /logout is issued immediately (or after a countdown).
The session is killed on the OAuth server and the user is logged out of it.
A ?next=... parameter redirects the user back to app A.
The app pulls the user status from OAuth server (server- or client-side) : if logged out from the OAuth server, then logout from the app also.
New apps would just have to implement this pulling mecanism along with the logout link pointing towards the OAuth server logout page, so there's nothing to configure in the OAuth server for new apps.
Do I miss something?
you may want to follow this draft, https://openid.net/specs/openid-connect-session-1_0.html

Box API OAuth2.0 in script

I am writing a script to automate the process of regularly upload specific files to Box.
After reading the BOX API, I know I have to use client-id and client-secret to get an authentication url which open in browser, then I login in by username and password, click allow, then I get redirect to a url I provided with Auth Code attached to the end of this redirect url.
problem now is, I am writing a script not an web or mobile app. Therefore, I have to avoid these UI web html manual login.
Is there a way??? I can get this authentication url by code in python using BOX's python SDK.Then I can open a browser in python by webbrowser module then I can type in username/password. Then I get redirected. Maybe I can use some special redirect url to send auth code back to my code? I don't know how to do that.
Please help!
You should use JWT authentication.
Unlike the standard OAuth 2 flow, JWT will allow you to use your own identity
provider to bypass the application auth and redirect. Building with JWT will allow
you to hide the Box process behind the scenes.
Authenticate with JWT

External login with Oauth2

I'm working on a Django application with users through Django's auth, on the other side there is an Oauth2.0 server that already has all users and their permissions registered. My goal now is to integrate the Django app with the Oauth2.0 server so we won't have to administrate the users ourselves. This would make it so the when the users want to log into our app they are redirected to the Oauth2.0 login site and then redirected to the home of our app once they login successfully.
I think I understand how Oauth2.0 works but I have a couple of questions I couldn't find anywhere else.
Is the scenario I'm describing possible? As in the users would no longer have to be registered in our app and a 3rd party Auth server would provide access to our app or not.
Once I get the access token after the user login where is it safe to keep the access token? I was thinking I could save to AT as a session variable so as to keep the end user's session linked to his account which is external to our Django app.
Every time the user makes a request I would check the AT I'm keeping, if the verification is OK our app responds with the view, otherwise the user is redirected to the login. Is this flow correct or am I not understanding how this integration would work?
What would happen in the case the user is given more permissions but I hold an old token? How do I handle these cases?
I would suggest using a third-party application, like django-allauth. You can simply disable creating local accounts, and enable a single custom social provider that interacts with your OAuth2.0 authorization server.
As noted here, the process of creating your own custom OAuth provider isn't documented, but shouldn't be too difficult.
Once I get the access token after the user login where is it safe to keep the access token?
Allauth will store the access token in the database. If you want to put it in the session too, you can, but there's no point unless you want the client to make requests to the resource server directly.
Every time the user makes a request I would check the AT I'm keeping, if the verification is OK our app responds with the view, otherwise the user is redirected to the login. Is this flow correct or am I not understanding how this integration would work?
That's fine. If your authorization server has no way to invalidate issued access tokens, though, you can just assume that the access token is good up until the expiration date.
What would happen in the case the user is given more permissions but I hold an old token? How do I handle these cases?
Just use the access token normally. If the resource server indicates that it's invalid, prompt the user to log in again. You will get a new access token for that user that reflects their current permissions.

Strange session behaviour with a Flask app on Heroku

I have a web application that uses GitHub's OAuth API in order to allow the app's users to interact with GitHub. However, I'm seeing some very odd behaviour with regards to the session cookie.
As a bit of background, I am using peewee to interface with Heroku's Postgres server, and have a User model like so:
class User(peewee.Model):
login = peewee.TextField(unique=False)
token = peewee.TextField()
I am using the web application flow described in the GitHub OAuth documentation, and am successfully getting called back with an access token, which I store in the database, and also in the session [1]:
#app.route('/callback')
def finishlogin():
# I've verified that `token` and `login` are both valid at this point
user = User.create(login=login, token=token)
session['token'] = token
return redirect(url_for('home'))
My route for home is as follows:
#app.route('/')
def home():
if 'token' in session:
user = User.get(token=session.get('token'))
return 'Your login is {}'.format(user.login)
else:
# ...
So far, so good, and this works correctly. However, I am experiencing instances of users logging in, refreshing the page and finding that they are suddenly logged in as someone else. Logging the requests to the app shows that on the second request the session cookie itself has sent the wrong value (i.e. session.get('token') in home() returns a valid, but incorrect value. Clearly the user's browser can't know any other session value, so it seems that there is some "leakage" in setting the session between different clients and requests.
I'm not sure what the problem might be. My database is stored on the Flask g object as described in the peewee docs and has before_request and teardown_request hooks set up to open and close the database connection, and from all the documentation and example code I have read (and I've read a lot!), I seem to be using the session object correctly. I have set up a working secret_key for the session store.
I'm wondering if this could be something going on with Heroku and their routing mesh? But then, how would one user suddenly send another user's session?
Any hints or advice would be appreciated—I've been staring at this for a long time and am at my wits' end.
[1] I'm aware that storing the token directly is a bad design choice. The application is non-public and this will be fixed, but for now I want to describe the problem as it exists, even though it's not ideal.
Answering my own question for future reference.
It seems that this was being caused by Flask's default session cookie behaviour, which is to send a Set-Cookie header with every single request, even for static assets. Our local Squid proxy was therefore gladly caching those requests and re-issuing Set-Cookie headers for every user.
Setting Cache-Control headers for the whole app seems to fix the issue.

Categories