This is a follow up question for this.
I'm using the latest Django OAuth2 Toolkit (0.10.0) with Python 2.7, Django 1.8 and Django REST framework 3.3
Some background:
When authenticating, the client receive a new AccessToken that he uses every time a makes a new request to the server. This AccessToken is owned by the client and being transferred using Authorization header upon request.
A simple test that I made was grabbing this access token from an authenticated client and send it in the Authorization header using a simple HTTP request from a different machine.
The result was that this new "client" is now authenticated just like the original client, and he can make requests as he pleased.
So the issue is:
The access token is not bind to any form of client validation (Like session id or client IP address). Any one that can get/find/steal/lookup the client's AccessToken, can be fake requests on behalf of this client.
I researched this issue allot but I couldn't find any one who addressed this matter. Maybe i'm doing something wrong in the from of authenticating the client? I would love some insights. Maybe its a simple configuration, out-of-the-box solution that I missed.
Thanks!
This method of attack is called replay attack. This video by Professor Messer explains replay attack.
You can't really implement anything client side (browser) to overcome this because of the transparency of web browsers.
What you can do is to implement a digest authentication using a nonce.
In cryptography, a nonce is an arbitrary number that may only be used once.
a basic implementation looks like this.
User requests API server.
API server responds with a HTTP 401 and a nonce in a WWW-Authenticate header [you have to keep track of nonces] (a JWT with nonce which is set to expire in a small window, may be 2 seconds or less would be better and stateless).
Client signs the request with received nonce, a client nonce and password and calls the resource again.
API server validates the signature, If the signature is valid the request is accepted.
Attacker captures the request and fakes the user.
Since nonce is expired/'used only once' the attacker's request is rejected.
Related
So I'm currently learning the python requests module but I'm a bit confused and was wondering if someone could steer me in the right direction. I've seen some people post headers when they want to log into the website, but where do they get these headers from and when do you need them? I've also seen some people say you need an authentication token, but I've seen some other solutions not even use headers or an authentication token at all. This is supposedly the authentication token but I'm not sure where to go from here after I post my username and password.
<input type="hidden" name="lt" value="LT-970332-9KawhPFuLomjRV3UQOBWs7NMUQAQX7" />
Although your question is a bit vague, I'll try to help you.
Authentication
A web browser (client) can authenticate on the target server by providing data, usually the pair login/password, which is usually encoded for security reasons.
This data can be passed from client to server using the following parts of HTTP request:
URL parameters (http://httpbin.org/get?foo=bar)
headers
body (this is where POST parameters from HTML forms usually go)
Tokens
After successful authentication server generates a unique token and sends it to client. If server wants client to store token as a cookie, it includes Set-Cookie header in its response.
A token usually represents a unique identifier of a user session. In most cases token has an expiration date for security reasons.
Web browsers usually store token as a cookie in internal cookie storage and use them in all subsequent requests to corresponding website. A single website can use multiple tokens and other cookies for a single user.
Research
Every web site has its own authentication format, rules and restrictions, so first thing you need to do is a little research on target website. You need to get information about the client sends auth information to server, what server replies and where session data is being stored (usually you can find it in client request headers).
In order to do that, you may use a proxy (Burp for example) to intercept browser traffic. It can help you to get the data passed from client to server and back.
Try to authenticate and then browse some pages on target site using your web browser with a proxy. After that, using your proxy, examine what parts of HTTP request/response do client and browser use to store information about sessions and authentication.
After that you can finally use python and requests to do what you want.
I have a python application that needs to give users a JSON web token for authentication. The token is built using the PyJWT library (import jwt).
From what I have been reading it seems like an acceptable practice to give the token to a client after they have provided some credentials, such as logging in.
The client then uses that token in the HTTP request header in the Authorization Bearer field which must happen over TLS to ensure the token is not exposed.
The part I do not understand is what if the client exposes that token accidentally? Won't that enable anybody with that token to impersonate them?
What is the most secure way to hand off the token to a client?
You could encrypt the token before handing it off to the client, either using their own public key, or delivering them the key out of band. That secures the delivery, but still does not cover everything.
In short, there's no easy solution. You can perform due diligence and require use of security features, but once the client has decrypted the token, there is still no way to ensure they won't accidentally or otherwise expose it anyway. Good security requires both participants practice good habits.
The nice thing about tokens is you can just give them a preset lifespan, or easily revoke them and generate new ones if you suspect they have been compromised.
Token will be build based on user provided information and what you back-end decided to be part of the token. For higher security you can just widen your token information to some specific data of the user like current ip address or device mac address, this will give you a more secure way of authentication but will restrict user to every time use the same device, as a matter you can send a confirmation email when a new login happens.
Hi I have our website running on appengine with flask as backend framework and we have built our authentication and session management using libraries Flask-OAuth, Flask-Login.
But now I have a requirement to use firebase for authentication.
I am able create sample applications following firebase tutorials but I do no how to integrate with existing application.
In Firenotes samples provided by firebase team they are using two separate services frontend and backend.
I thought of using firebase code in login.html page and once client authenticated pass the info to /profile url -> log the user_id in database and login-user using Flask-Login.
I am not sure whether the above flow is correct and I am not to ensure that it is correct one without any problems in future.
Please help with any ideas as I need to implement it very soon!!
Flask-Login uses session based authentication. Clients login using an authentication scheme. Since you are using Flask-OAuth, it's the oauth flow. If the user successfully authenticates, Flask-Login sends a response during the token exchange step setting an HTTP only cookie (meaning javascript can't access it) with a token unique to the user session. The client then authenticates future requests for the duration of the session with that token. The server can invalidate the session at any time, forcing the client to log in again.
Meanwhile, firebase authentication is JSON Web Token (JWT) authentication scheme. After completing the login flow, the firebase API retrieves a JWT from google's application servers.
To authenticate requests, you need to transmit that JWT on EVERY request. Your server MUST also validate the JWT to ensure that it is both valid and unexpired.
You'll note that the manner by which the JWT arrives at the server is unspecified by the firebase SDK and libraries. I recommend using a Authentication: JWT <google's jwt> header.
One way to resolve your question would be to use the JWT to complete the initial login flow, and then rely on session based auth from there. You'd set up a login endpoint that expects and validates a JWT, and responds with the set cookie header. From that point forward you continue using your flask-login provided session based auth.
Google actually has an example of this in their documentation: https://firebase.google.com/docs/auth/admin/manage-cookies
I'm trying to create a command line client for Jira, but I don't really want to store the username/password, and I don't want to have to put in my password with every single request.
Jira says they have a cookie based API, but it doesn't look like it works the way that I think it works.
Specifically, when using Python's requests library I can only re-use the cookie if I have a Session object that I think keeps a connection to Jira.
But if I try to say, make a requests.post request and requests.get requests to the REST URL, it fails with a 401 and tells me that I'm not authenticated. OTOH, if I create a Session, I can do
session.post(.../rest/auth/1/session)
print(session.get(.../rest/auth/1/session).status_code)
And I'll get the 200 that I expect.
I do notice that there's another cookie in the requests response headers:
atlassian.xsrf.token=SOMETHING|RANDOM|lout
but I didn't see anything about that in the documentation.
Is it possible to do this, or do I have to store the username/password if I want to break the connection in between requests?
You are correct, the session is required. From the documentation:
The client creates a new session for the user, via the JIRA REST API.
JIRA returns a session object, which has information about the session including the session cookie. The client stores this session object.
The client can now set the cookie in the header for all subsequent requests to the JIRA REST API.
In other words, the session is integral to the request, receipt and use of the cookie-based authentication token.
Also, the atlassian.xsrf.token would have been injected by atlassian to prevent cross-site forgery and hijacking of the session/cookie.
The way I see it, here are your simple-but-secure options:
For every invocation of your script, use the session to request-receive-retain the cookie (and then, once all API calls are complete, let everything get discarded)
Base64 encode your username and password, store it in a separate file (encrypted if you so choose), and have your script collect (and decrypt) it then place it in an authorization header. See Hiding a password in a python script (insecure obfuscation only).
If you follow the goal not to authorize every time you send a request to the API, you should send (POST) your authentication requests using the cookie-based authentication /rest/auth/1/session, not Basic Auth, to get the token. You will then use that obtained token subsequently in your further requests (in the Cookie header) to the API without a need to authorize every single request.
Watch out for the important missing piece in the API documentation: you should sent the username, NOT email, to authorize in a cookie-based manner. Even though both variants work for the Basic Auth, only user works for the cookie-based authentication.
I use Django and Django-rest-framework about REST services from Back-end and Mobile Client Apps.
I would to have some responses with encrypted data. I have to return to my client some sensible and private data and I would to apply an additional security layer (in fact I already use SSL, but I would to disarm some attacks (like man in the middle) where some unwanted element can see some data contained in my responses).
I would to avoid this, so I thought to add in my response the encrypted data.
Does that make sense? Is there something similar in Django - REST- Framework?
A good encryption libary with various implementations is Keyczar.
What you would need to do is write a global interceptor on all incoming request to your backend application, and when responses are sent back they are encrypted using the Keyczar library.
On the consumer side (your mobile application) you would need to implement something similar that decrypts the responses from your backend.
BONUS: if you're not doing this already, you probably want to look at using 2-way SSL to ensure that you authenticate the client that calls your backend.