How to set authorization header (JWT) - python

I am working on JWT authorization and I'm not able to figure out how to send the JWT as a request header for every request, so that I can use it to check if the user is authorized.
Right now, I am generating the JWT immediately after login, and setting it as a cookie. I want to use header instead of cookie. How can I achieve this?
I am using django 1.6, if it is relevant information.

It really depends on your request library. Could you tell me what library you're using to make requests? BUT: most request libraries out there should let you set the header of the request to include a JWT. Therefore, when the server receives the request, the server will "know" you are authorized because the JWT is in the header.
Take a look at How to add JWT to authorization header? as an example!
As for this:
Right now, I am generating the JWT immediately after login, and setting it as a cookie. I want to use header instead of cookie. How can I achieve this?
It's totally fine to set your JWT as a cookie. What you must do for every request is to get the JWT from the cookie. Look at: https://www.w3schools.com/js/js_cookies.asp for more details!

Related

How to Authenticate to Anchor.fm form using Python?

I'm trying to use Python to authenticate to https://anchor.fm/login.
The problem is that the payload requires a _csrf property.
So I don't think it's possible to use a simple POST method.
So, I would like to know if it is possible to get the attributes of the form (id="LoginForm") to do the authentication:
If yes, is there any package that helps me to do this? Or some other method.
The login page makes a GET request to https://anchor.fm/api/csrf to get a csrf token. This request also sets a cookie, which is then sent together with the login form. I haven't checked that, but it seems it should be enough to make that GET request, grab the csrf token and the cookie, and attach them to the POST you make with the login form. (the csrf token in the _csrf body field, as you noted)

How tornado authentication works?

How authentication works in tornado with set_secure_cookie method?
where are these cookies get stored for multiple users ?
how can we authenticate each API calls inside the framework ?
Cookies are just HTTP headers. Nothing special. Cookies work like this:
Browser sends a request to server. This can by any request, like a regular page request, or a login form submission. For this example, let's just talk about a login request.
Server will look at the submitted username and password and make sure they are correct. Then server will set a cookie on this browser so that it can later identify the user. To set a cookie, the server will send a header called Set-Cookie along with the response. It will look like this - Set-Cookie: sessionId=username.
When the browser will get the response, it will also notice that there's a SET-COOKIE header on the response. Now the browser will save this value somewhere on your computer, it doesn't matter. What matters is after this, whenever the browser will send the request to your server, it will also send this cookie in the request headers like this - Cookie: sessionId=username.
Next time, server will also notice the Cookie header in the request. And so, it will get the username of the logged in user from there.
And that is how cookies work.
Now to answer your questions:
How authentication works in tornado with set_secure_cookie method?
You might have noticed a big security flaw in the above example. To identify the user we have set the sessionId value in plain text. Anyone can easily send a different username in the cookie and our server will treat them as that user. For example if Alice wants to hack Bob's account, all she has to do is send the session cookie like this - Cookie: sessionId=bob. And our server will treat Alice as Bob.
This is where the set_secure_cookie method comes in. It will set a signed token, instead of a plain username. Tornado will set signed cookies based on your cookie_secret setting value. This is secure because cookies are signed based on the cookie_secret which nobody knows accept you. The cookie will look like this - sessionId=slsafj7987LJflsfslfljk68686sfj. Now, Alice can't impersonate as Bob.
where are these cookies get stored for multiple users ?
Nowhere. Since the cookies are signed, Tornado will decode the value from the signed cookies as the request comes in. For example if a cookie header looks like this - Cookie: sessionId=alksjfl98798yfaslkdjf. Tornado will decode this - alksjfl98798yfaslkdjf value to extract the encoded username. It happens on-the-fly.
how can we authenticate each API calls inside the framework ?
Do the API calls require session, like user authentication so that users can see and edit their account etc? Then all you need is set_secure_cookie method.
If the API calls are independent of each other, then you should let your users use your APIs with an "access key". You will need to store these access keys in a database. Your users will send this access key with every request, in the form of an HTTP header or just a request query parameter:
# as a header
API-Access-Key: <long-random-key>
# OR as a query string
http://yourserver.com?key=<long-random-key>

Understanding the Python requests module

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.

Is it possible to use Jira cookie based auth with separate connections?

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.

How is Flask-Login's request_loader related to user_loader?

I apologize in advance for asking a rather cryptic question. However, I did not understand it despite going through a lot of material. It would be great if you could shed some light on this.
What is the purpose of a request_loader in flask-login? How does it interact with the user_loader decorator?
If I am using a token based authentication system (I am planning on sending the token to my angularJS front end, storing the token there and sending that token in the authorization-token header), will I need a request_loader or will a user_loader (where I check the auth header and see if the user exists) suffice?
From the Flask-Login documentation:
Sometimes you want to login users without using cookies, such as using
header values or an api key passed as a query argument. In these cases,
you should use the request_loader callback. This callback should
behave the same as your user_loader callback, except that it accepts
the Flask request instead of a user_id.
So, to answer your question, they both serve the same function for Flask-Login. They are both used to load the user. request_loader, however, is appropriate for custom logins.
Here's a great tutorial I found that utilizes request_loader to take advantage of token based authentication (The post is not my own, I'm merely sharing the link): http://gouthamanbalaraman.com/blog/minimal-flask-login-example.html
I need to make this clear.
This is the reason why you shoud use request_loader with flask_login.
There will be a lot of #login_required from flask_login used in your api to guard the request access.
You need to make a request to pass the check of auth.
And there will be a lot of current_user imported from flask_login,
Your app need to use them to let the request act as the identity of the current_user.
There are two ways to achieve the above with flask_login.
Using user_loader makes the request to be OK for #login_required.
It is often used for UI logins from browser.
It will store session cookies to the browser and use them to auth later.
So you need to login only once and the session will keep for a time.
Using request_loader will also be OK with #login_required.
But it is often used with api_key or basic auth.
For example used by other apps to interact with your flask app.
There will be no session cookies,
so you need to provide the auth info every time you send request.
With both user_loader and request_loader,
now you got 2 ways of auth for the same api,
protected by #login_required,
and with current_user usable,
which is really smart.
To verify users with Flask-Login's session_id for frontend requests through Angular, you must set the withCredentials configuration flag to true.
That is, if you are using Angular's $http.post(url,data [,config]) or $http.get(url [,config]), make sure the config object contains the property withCredentials set to true. This will instruct the browser to use its cookies in the same way it would for a full-on page visit.
For example,
$http.post('/api/login',{username:'myusername',password:'mypassword'},{withCredentials:true})
will post the data {username:'myusername',password:'mypassword'} to your site/app's /api/login route and, if you're using Flask-Login and are logged in, Flask will know.
You can set this behavior for all $http service requests by setting
$httpProvider.defaults.withCredentials=true
somewhere in your app. Currently, I have that line of code in my app.config block, which seems appropriate to me:
var myApp = angular.module('myApp');
myApp.config(function ($httpProvider) {
$httpProvider.defaults.withCredentials = true;
});
(Since this post is about Flask, folks may want to send form data through Angular in such a way that it can be found in request.form, which has a similar solution, fyi.)

Categories

Resources