How to get the request's Authentication Header in Tornado - python

I've been looking on how to get the Authorization Header from a Tornado GET/POST Request, but there's none. Anyone can help on this?
The reason is that I want to implement JWT in my Python application.
For example, this tornado API just creates a GET request:
class HeaderHandler(tornado.web.RequestHandler):
def get(self):
headers = tornado.httputil.HTTPHeaders()
response = {
'message': str(headers)
}
self.write(response)
I want to access this API via http://localhost:{port} and I will add a header which is
Authentication: Bearer {token}
But this code doesn't work. It cannot fetch the authorization header passed to the request. Any help is appreciated. Thanks!

In Tornado, accessing the bearer token from JWT can be achieved by:
token = self.request.headers.get('Authorization')

According to the docs, a request object containing headers is available as RequestHandler.request, so try e.g.
self.write(repr(self.request.headers))

Related

How can I test AWS Cognito protected APIs in Python?

I'm trying to test out some AWS APIs that are protected by Cognito. I found the first part on how to get the Json token but I can't figure out how to use the token correctly so I can authenticate on the API.
Here's my code :
import boto3 as boto3;
import requests
username='test#gmail.com'
password='test1234567'
client = boto3.client('cognito-idp')
response = client.initiate_auth(
AuthFlow='USER_PASSWORD_AUTH',
AuthParameters={
"USERNAME": username,
"PASSWORD": password,
},
ClientId='12121212121212',
)
token = response['AuthenticationResult']['AccessToken']
#print("Log in success")
#print("Access token:", response['AuthenticationResult']['AccessToken'])
#print("ID token:", response['AuthenticationResult']['IdToken'])
url = 'https://XXXXXXXX.execute-api.eu-west-1.amazonaws.com/Prod/incidents'
#print('url:', url)
#response = requests.get(url, headers={'authorization': token })
#print('GET:', response.status_code)
head = {'Authorization': token}
response = requests.get(url, headers=head)
print(response.content)
I'm getting the following error message :
b'{"message":"Authorization header requires \'Credential\' parameter. Authorization header requires \'Signature\' parameter. Authorization header requires \'SignedHeaders\' parameter. Authorization header requires existence of either a \'X-Amz-Date\' or a \'Date\' header. Authorization=
Ok so I found the problem and it's working fine now, 2 things were wrong :
The endpoint was wrong - AWS doesn't send a correct error message (!)
The request has to be sent with response['AuthenticationResult']['IdToken']
Please make sure you have selected Cognito or IAM in your API Gateway. From the error message it seems you have selected IAM for protecting the API.
Check the Authorization header's name which you configured for your Cognito Authorizer. You need to use same header name while passing the Cognito token.
If you have configured OAuth scopes in API Gateway side, then you must use access token. And no scope is configured then you can use ID token for authorization.
That said, you can try from Postman application for testing purpose.

Netsuite: OAuth1 / Token-Based Authentication where to put the state parameter

I want to connect to Netsuite via Token-Based Authentication (i.e. OAuth1) as documented here.
In the section Step One Obtain An Unauthorized Request Token it is written that an optional state parameter can be added to the Authorization Header. There they also refer to RFC 6749, Section 4.1.1 for further information. However, what is explained there has nothing to do with OAuth1.0 but Oauth2.0.
The reason why I depend on the state parameter is that I have the url to which the callback server shall forward the request after the authorization is done encoded in it (using JWT).
Now when I create the OAuth1 authorization header with oauthlib using the sign method from oauthlib.oauth1.Client in Python
from oauthlib.oauth1 import SIGNATURE_HMAC_SHA256
from oauthlib.oauth1 import Client
client = Client(client_key=CONSUMER_KEY,
client_secret=CONSUMER_SECRET,
callback_uri=CALLBACK_URL,
signature_method=SIGNATURE_HMAC_SHA256)
uri, headers, body = client.sign(uri="https://123456.restlets.api.netsuite.com/rest/requesttoken", http_method='POST')
I get this for headers:
headers = {
'Authorization': 'OAuth oauth_nonce="123..", oauth_timestamp="163...", oauth_version="1.0", oauth_signature_method="HMAC-SHA256", oauth_consumer_key="f18...", oauth_callback="...", oauth_signature="9kae..."'
}
I can acquire the temporary credentials when sending the request with this headers to https://123456.restlets.api.netsuite.com/rest/requesttoken.
Still as I need the state parameter later on on my side I somehow need to add the state parameter to the authorization header (at least that is what Netsuite says in their documentation).
When I add my state parameter to the authorization header (the one created before by the sign method from oauthlib.oauth1.Client) like this
from oauthlib.common import to_unicode
headers["Authorization"] = f'{headers["Authorization"]}, state="{to_unicode(data=state, encoding="UTF-8")}"'
which results in this for headers (I will refer to it as new_headers):
# headers with state appended to Authorization
headers = {'Authorization': 'OAuth oauth_nonce="123...", oauth_timestamp="163...", oauth_version="1.0", oauth_signature_method="HMAC-SHA256", oauth_consumer_key="f18...", oauth_callback="...", oauth_signature="9kae...", state="eyJ0..."'}
I get this response when trying to send a request to the request token url with this header:
{"error" : {"code" : "USER_ERROR", "message" : "Invalid login attempt."}}
When I do it differently (not as specified in the doc) and add the state parameter to the request token url like this "https://123456.restlets.api.netsuite.com/rest/requesttoken?state=eyJ0..." and send the previous header with authorization not including the state (i.e. headers) I again get to the login page. So I can assume this could work.
My problem is that I cannot test it at the moment with a Netsuite account so I just need to implement it according to the documentation and hope that I send the state parameter in the right way and it is forwarded to the callback server after a user logs in.
Now my question is:
Is the documentation correct and the state parameter needs to be added to the authorization header like in "new_headers" above and I just do sth wrong here. If so what am I doing wrong here?
Or is the documentation misleading as simply adding the state parameter as a normal query parameter to the request token url like this "https://123456.restlets.api.netsuite.com/rest/requesttoken?state=eyJ0..." is correct?
I would really appreciate some help here!
Best regards,
JayKay

How to return a bearer JWT token FROM Flask?

How to form a response from Flask python server which would contain the bearer token in the response. More precisely, I am looking to somehow securely propagate the JWT token from Flask python server back to the client (angular page). I can just return it in form of the querystring in GET redirect. What are other possibilities in terms of returning the JWT access token back to the client? I tried setting the response form python, and to set the jwt token in Authorization field, but nothing worked. This is what I tried:
1.
r = Response(headers={
"Authorization": "bearer jwtcntent",
"Access-Control-Allow-Origin": "*",
},
is_redirect=True,
url="https://localhost:5000/callback",
)
return r
r = redirect("http://localhost:5000/callback")
r.headers = {"authorization": "bearer jwtcntent"}
return r
r = Response(headers={
"Authorization": "Bearer jwtcntent",
"Access-Control-Allow-Origin": "*",
},
allow_redirects=True,
url="https://localhost:5000/callback",
)
return r
Any recommendations?
You can store it in an httponly cookie, but you need to make sure to handle CSRF attacks if you do so. Flask-JWT-Extended has built in support for this which you might find useful, either as a solution or as a reference for whatever you end up doing:
https://flask-jwt-extended.readthedocs.io/en/stable/token_locations/#cookies
You can also just send the token back as part of the JSON body and then storing it in local/session storage, which is probably the most common pattern.
Are you able to implement a regular OAuth flow in your Authorization Server? OAuth flows are standardized and use secure ways of returning an access token to the client.
I don't recommend using the Authorization header for returning responses. This header is a request header, it has no meaning in a response. If you really need to do it through the header you can add Access-Control-Expose-Headers header to let your client read the Authorization header from a response.

Python request to authorize app api made via tyk gateway

I'm working on a python script (2.7.x) that tries to connect to a third party api via tyk gateway. The end api expects an auth token in the request header and tyk also requires its own auth token to be present in the request header.
Now the problem that I'm facing is:
When I try to make a request to the third party app via tyk, app is not recognising the auth token passed in the header.
From debugging I was able to figure out that tyk is not passing the authentication header to the app.
I'm using following piece of code to make the request
request.post("https://myurl.com",
data={"data": data_a},
headers={"Authorization": "Basic <TYK_TOKEN>, Bearer <APP_TOKEN> })
Things I have tried:
Tried passing the app token first and tyk token second, then the request won't pass tyk authorization.
Tried passing app token alone in the request, then the request won't pass tyk authorization.
Tried passing app token under 'Application-Authorization' header and tyk token under 'Authorization' header, then the request won't pass app authorization.
Please advise a solution.
Thanks
in advance
Leonid from Tyk here.
So basically your upstream is protected by auth token, and your own API protected by token as well.
If your 3-rd party API have a static api key, you can just embed it to all requests as a global header:
If you have a dynamic 3-rd party key, which varies for different users, you can embed it to Key metadata, for example, "upstream_api_key" field, and add global header with dynamic value: "$tyk_meta.upstream_api_key".
If your user needs to pass this token, and you need forward it to upstream, Tyk and Upstream authentification should happen in different HTTP headers.
Hope it helps!

Use JWT with TurboGears2

I'm currently stopped in my work because of some authentication work on a project.
I set up a REST API, which needs to have a JWT authentication system.
Some work was already done and I overrode it. So the library used was Python's TurboGears2, and I used PyJWT to manage tokens.
My WS and the token's creation works well. The post method with auth info JSON request's body can create a token, that's sent in the response.
But after that, when I do a 'GET' request on the restricted resource, I can't retrieve the token.
What I do: send a GET request to the restricted resource, with "Authorization: Bearer <TOKEN>" in request headers.
But when I do a 'request.authorization' in my web service function, I always get 'None'.
Do I need to set up a full auth system using TurboGears to access this header?
thanks for help
Where are you trying to access the request.authorization from?
I tried with a newly quickstarted application and modified the index to print the authorization header:
#expose('testauth.templates.index')
def index(self):
"""Handle the front-page."""
print(request.authorization)
return dict(page='index')
And I sent the authorization header from Postman.
It worked fine and printed my test header
Authorization(authtype='Bearer', params='HELLO')
I also tried to disable any auth_backend so that authentication is disabled and it still works as expected.

Categories

Resources