I have API written in flask and I use JWT token for authorization. I would like to protect my staging environment from unautorized access, so I added apache basic authentication, but it uses same "Authorization" header, and angular replaces my basic auth header with JWT header.
Does anyone know how to resolve this issue? Maybe can I change Apache Authorization header to different key?
I'm doubtful that you would be able to change the authorization header on apache (I imagine that it is hard coded to that, as web browsers wouldn't know to send the actual request in a different header). This is just my intuition though, and might very well be wrong.
If you used flask-jwt-extended instead of flask-jwt, you could change the header which contains the JWT using the JWT_HEADER_NAME option (http://flask-jwt-extended.readthedocs.io/en/latest/options.html). Full disclosure, I'm the author of this extension.
If you want to continue to use flask-jwt, you can probably do this by utilizing one of the jwt_*_callback decorators, or by sub-classing flask-jwt and overwriting the method that checks for the JWT in the authorization header.
Related
I want to implement authorization mechanism to my python flask application. I want o manipulate authorization of groups, users and etc... in my application.
After reading through these pages about how to setup authorization through extension
1-https://auth0.com/docs/api-auth/grant/authorization-code
2-https://auth0.com/docs/quickstart/backend/python#add-api-authorization
I added this decorator which is shown in the second link above (interesting thing is that I realized 2nd links decorator has the same decorator names with the 00-Starter-Seed app. So 2nd links decorator does authorization and authentication at the same time ?
def requires_auth(f):
...
..
.
But when I tried to work that decorator, I am getting this error
{
"code": "Error decoding token headers.",
"description": "Invalid header. Use an RS256 signed JWT Access Token"
}
I doubted from maybe I understand the concept of implementing authorization in Auht0 wrong. So, what I understand from it is
1 - check needs to be made to determine whether the incoming request contains valid authorization information (jwt)
2- get access_token and use it in decorator
3-call the api to manipulate groups, users, etc, ... (things I want to do through api) OR use it as function decorator to make use that function only be called by admin
what is the point I am not seeing or understanding wrong ?
Thanks
I made it work. The outline that I followed are
created authorization extension
configured authorization extension API
grand access to auth0-authz(non-interactive client)
in our web app ask created another token for auth0-authz(non-interactive client) to consume API
verified token over urllib.urlopen("https://"+AUTH0_DOMAIN+"/.well-known/jwks.json")
then made a successful API call with new token
Writing a REST API with Pyramid/Cornice using JWT for authentication, I'll have to implement some CSRF protection.
Having thoroughly read up on the topic I understand the problem, but I'm pretty confused about the best way to implement it, it's a bit tricky considering all the possible attack vectors.
Since this API gives access to sensitive data and will be published as open source software, it requires a self-contained protection. It will be used in environments with untrusted subdomains and I can not rely on users to follow security guidelines.
For my stateless service I can either use "Double Submit Cookies" or the "Encrypted Token Pattern"-method.
Double Submit Cookies
To prevent "cookie tossing", the token in the Double Submit method needs to be verifiable. MiTM attacks are an additional threat, which I hope to mitigate sufficiently by forcing HTTPS-cookies only.
To get a verifiable token that can't be easily guessed and replicated by an attacker, I imagine a hashed token like this should work:
pbkdf2_sha256.encrypt($userid + $expire + $mycsrfsecret, salt=$salt)
"exp" is the expire-value from the JWT. The JWT will be issued together with the CSRF-cookie and "exp" can be read by the server, which adds some additional protection as it's variable and the attacker doesn't know it (Might be superfluous?).
On a request I can easily compare the two tokens I receive with each other and use pbkdf2_sha256.verify($tokenfromrequest, $userid + $exp + $mycsrfsecret) to compare it with the values from the JWT-token ('Verifiablity').
Would that approach follow recommended practices?
I've selected pbkdf2 over bcrypt since its verify-method is noticeably quicker.
Expiry would be set to 7 days, after that both the JWT and the CSRF-token would be renewed by a fresh login (They would also be renewed on an intermediate relogin).
Encrypted Token Pattern
The alternative is to send a string to the client, consisting of userid, expiry and nonce, encrypted with a server-side secret. On a request this string is sent along and the server can decrypt it and verify userid and expiry.
This seems the simpler approach, but I'm unsure how to implement it, I don't intend to roll my own crypto and I have not found good examples:
What cipher/library should I use in Python? How do I do Encrypt-then-MAC?
How would I persist the token until its natural expiration? I don't want the users to have to login freshly every time they restart their browsers. Local Storage is not a safe place - but there is no alternative.
Writing a REST API with Pyramid/Cornice using JWT for authentication
While I am not familiar with those frameworks, I suggest you ensure the JWT token is passed within a HTTP header (e.g. My-JWT-Token: ... ) which is NOT the cookie. Then you do not have to worry about the CSRF vector.
Cross Site Request Forgery is an issue due to the nature of the browser's tendency to always submit cookies, which often contain authentication information, to a particular domain. A browser will not automatically submit a custom header, ergo you do not have to worry.
Double Submit Cookies
Your method is overly complicated, you could simply use a GUID. Put that GUID in a cookie, and put it in any other part of the request. If they equal, CSRF check passed. You could also put the GUID into the JWT, then validate the GUID is also in a header/body/query parameter.
Encrypted Token Pattern
This is almost exactly what JWT is, just pass the token in the header as suggested 😄
To answer the questions:
I would suggest hmac as in import hmac. I would not bother encrypting but merely ensure there is no sensitive information in the token. Else PyCrypto may do you well.
This is why cookies exist, which does raise the CSRF issue again. If this is a hard requirement then I suggest the double submit cookie method.
I have an app that I'm writing which authenticates against an Oauth 2.0 authorisation server. I'd like to test the parts that are accessible only after you've logged in but the Oauth server is an external dependency that complicates and make brittle my tests.
Any suggestions on how I should go about this? What the industry practices for something like this? My gut feel is to somehow mock out the server so that it allows access to the protected resources.
In case it matters, this is a Python webapp written using Flask.
I am using a custom oauth server which will run on my own domain and while it's possible to add some kind of sandboxing functionality as FoxMask has suggested, I'd much prefer being able to run the test without requiring an extra server running.
From the consumer (i.e. your application) side, the OAuth2 process can be separated in two parts:
the redirect from your application to the OAuth2 provider's "authorize" URL
the exchange of the "code" returned by the OAuth2 provider for an access token
For #1 all you need to test is that when you invoke the route that starts the authentication process the response returned is a redirect to the OAuth2 provider. This is easily accomplished with Flask's test client. The response should have a status code of 302 and a "Location" header set to the authorize URL for your OAuth2 provider. Note that you do not need to provider to be up, you are just testing that the response is a redirect, but you do not need to actually redirect.
Testing for #2 is a little bit more involved. Your Flask app has a special URL that is designated as the "redirect URL" for the OAuth2 provider to send you back the authorization code. You can just invoke this URL with the Flask test client passing a mock code and that has no issue.
The problem is that in the view function that handles your redirect URL you need to invoke the OAuth2 provider to exchange the auth code for an access token, and this is done synchronously. To prevent this transaction to happen you have to check app.config['TESTING'] and in that case skip the actual request and replace it with a fake response that includes a mock access token.
From then on you will need to also fake any additional calls into the OAuth2 provider that send the access token to request data.
If you are using an OAuth2 client library in your Flask app it may be easier to create the mock provider without having to create testing exceptions in your application. In my case I'm using rauth, and for this I have created a subclass of the OAuth2Service class that overrides the proper methods and responds with mock data that I have captured from a real session. Then in my test setup I just create the mock service and the application is fooled into thinking it is talking to a real server.
I hope this helps.
I got to transfer some files to a remote server for which I have to perform OAuth2.0 to get access token and then simply perform a POST request to upload the files.
Now I am too lazy to setup a Django project on cloud and then perform OAuth2 while there are not "too good" lib for that though.
So, I am thinking to perform OAuth2 using rauth lib as a simple python script without really setting up a server that accepts requests and all..
However, on the remote server profile, I need to provide a redirect_url and of course in the rauth client lib.
Are there any possible ways to do this authorization without really setting up a project on cloud..A simply python script is what I am looking for.
I'm the author and maintainer of rauth.
Rauth no longer enforces a redirect_uri, so if your provider allows it then you can forgo using it. However if you ultimate goal is not to setup a server, this should be doable even with a redirect_uri required by the provider. You can, for example, redirect to localhost where you could setup a minimal server using Flask or if the provider allows it, some other, arbitrary URL, e.g. Facebook provides https://www.facebook.com/connect/login_success.html for this purpose. And the provider you're using might have a similar scheme. Here's an example with rauth.
Another option is to use Bearer Auth with grant_type=password. All OAuth 2.0 providers are supposed to support Bearer Auth, but may not implement the password grant_type. This does not require a redirect_uri, instead you end up passing the server your user credentials and it should return an access token to you. If your provider allows Bearer Auth with grant_type of password, this is probably the ideal for you. Rauth 0.5.3 attempts to use Bearer Auth by default so all you have to do is pass in the grant_type. Be sure to update before giving this a go.
Here's a simple example:
# assume you have constructed an OAuth2Service object and bound it to `serv`
params = {'grant_type': 'password',
'username': 'foo',
'password': 'hunter2'}
s = service.get_auth_session(params=params)
r = s.get('https://example.com/api/some/endpoint')
Depending on the provider and what you want to do, it may require a little more investigation. However, hopefully this gives you something to start with.
Edit
I think my comment about password grant_type is a little confusing: I seem to be implying you have to use it with Bearer Auth (here by Bearer Auth I mean affixing the access token in the Authorization header in the Bearer format), but actually you don't. It's acceptable, although discouraged, to send the credentials along in the entity method[1]. If you're using rauth and find that authentication is not working as expected, you may need to disable Bearer Auth like this:
s = service.get_auth_session('/some/resource',
data={'code': code},
bearer_auth=False)
From the spec:
[1] "Clients SHOULD make authenticated requests with a bearer token using the Authorization request header field with the Bearer HTTP authorization scheme. Resource servers MUST support this method."
I have an application that has a "private" REST API; I use RESTful URLs when making Ajax calls from my own webpages. However, this is unsecure, and anyone could make those same calls if they knew the URL patterns.
What's the best (or standard) way to secure these calls? Is it worth looking at something like OAuth now if I intend to release an API in the future, or am I mixing two separate strategies together?
I am using Google App Engine for Python and Tipfy.
Definitely take a look at OAuth
It is quickly becoming the "de-facto" standard for securing REST APIs and a lot of big companies are using it, including Google, Twitter and Facebook just to name a few.
For Python on GAE you have two options:
The most straightforward way (IMHO) is using David Larlet's library for OAuth Support in Django available on BitBucket.
But since you're not using Django, maybe you want to take a look at the python-oauth2 library that's available on GitHub, and is considered the most up-to-date and unit-tested implementation of OAuth for Python 2.4+.
Either way I think you'd be much better using OAuth than rolling your own service security solution.
Securing a javascript client is nearly impossible; at the server, you have no fool-proof way to differentiate between a human using a web browser and a well-crafted script.
SSL encrypts data over the wire but decrypts at the edges, so that's no help. It prevents man-in-the-middle attacks, but does nothing to verify the legitimacy of the original client.
OAuth is good for securing requests between two servers, but for a Javascript client, it doesn't really help: anyone reading your javascript code can find your consumer key/secret, and then they can forge signed requests.
Some things you can do to mitigate API scraping:
Generate short-lived session cookies when someone visits your website. Require a valid session cookie to invoke the REST API.
Generate short-lived request tokens and include them in your website HTML; require a valid request token inside each API request.
Require users of your website to log in (Google Accounts / OpenID); check auth cookie before handling API requests.
Rate-limit API requests. If you see too many requests from one client in a short time frame, block them.
OAuth would be overkill in your current scenario (potentially insecure), in that it's designed to authorize a third party service to have access to resources on behave of the user.
Securing AJAX request via an authorized user
AFAICT, you are in control of the client, resources and authentication; so you only need to secure access to the URL's and possibly the communication between client and server via SSL [2].
So, use Tipfy's auth extension to secure your URLs:
from tipfy import RequestHandler, Response
from tipfy.ext.auth import AppEngineAuthMixin, user_required
class MyHandler(RequestHandler, AppEngineAuthMixin):
#user_required
def get(self, **kwargs):
return Response('Only logged in users can see this page.')
Securing AJAX request without an authorized user
If a user is unknown, then one could apply CSRF preventions to help protect the REST service from being called from an "unauthorized" client. Tipfy has this built-in to it's WTForms extension, but it's not AJAX. Instead, the session extension could be used to apply an "authenticity_token" to all calls, that needs to be verified on the server.