Restrict REST API access - web-services

I have a public facing API that returns some data, internally using the Google Maps API Service. This API is mostly for interal purposes right now, invoked through the webapplication.
However, I wish to restrict the usage of this API i.e. it should only be invoked from my Web Application ( or mobile app) when a user (non-registered) browses it. An http request directly to this API should not be authorized.
I cannot use API keys since the webapp flow should work for non-registered users as well.

If you're not using HTTPS, any security mechanism is flawed, because it can be replicated. IMHO, you could add a HTTP header (e.g. "Request-source: YourApp") and check for its existance in your API.
Of course, once it's documented somehow, anyone can mimic this header. But if you use HTTPS and create a header that's unknown for other people, you prevent this from happening.

Related

django-rest-framework-social-auth requires a client secret for convert token

I am making an Android application with a Django based backend.
The Django server has a REST API to serve user data which I want to protect. I only want my users to log in via Google (or FB which I'm going to implement in the future).
I am using django-rest-framework-social-auth to implement the authorization in the backend.
So the flow as I understand is like this:
The client (my android application), does the whole Google OAuth2.0
flow and obtains the access token
The the client then wants to
convert the Google access token with one with which it can access my
backend server API endpoints. To do this it calls the convert-token
API endpoint implemented in django-rest-framework-social-auth
Now that it has the API access token, it can include that in the header of all further API calls and receive the private data.
Now my concern is, the django-rest-framework-social-auth convert-token endpoint also needs the client-id and client-secret generated by django-oauth for the application. So I will have to store the client-secret somewhere in my mobile app, which entirely defeats the purpose of authenticating whether the request came from the app or not, because someone can decompile the apk and get the app and make token exchange requests on my app's behalf.
Is there any way around this? Is there a "standard" way to implement this which I don't know?

How to check for Cognito permissions in API Gateway

Trying to understand how to use Cognito and API Gateway to secure an API.
Here is what I understand so far from AWS documentation and the Cognito user interface:
Clients
www-public - public facing website
www-admin - administrators website
Resource Servers
Prices - for this simple example the API will provide secured access to this resource.
Scopes
prices.read
prices.write
Again, very simple permissions on the API. Public www users can read prices, administrators can write them.
API Gateway
GET /prices - accessible to authenticated users that can read prices.
POST /prices - only accessible to administrators
Users
Administrators - can update prices via the POST method.
Non-administrators - cannot update prices.
Based on this...
Each client will request the scopes it is interested in. So for the public www site it will request prices.read and for the administration site both prices.read and prices.write.
The API Gateway will use two Cognito Authorisers, one for each HTTP Verb. So the GET method must check the user can read prices and the POST method that they can write prices.
The bit I don't see is how to put all of this together. I can make the clients request scopes but how do they now connect to user permissions?
When the token is generated, where is the functionality that says "Ok, you requested these scopes, now I'm going to check if this user has this permission and give you the right token?"
I understand that scopes ultimately related to the claims that will be returned in the token.For example, requesting the profile scope means that the token will contain certain claims e.g. email, surname etc.
I think based on this that my permissions will ultimately end up being claims that are returned when specific scopes are asked for. The fact that the two clients differ in what they request means that the prices write claim an never be returned to the public www client. It would never issue a token if the prices.write claim was requested.
What I can't see is where this fits in Cognito. There is the option to put users into groups but that is pretty much it. Likewise, there is nothing (that I could see) to relate scopes to claims.
I'm coming from a .Net and Identity Server background. Certainly in the last version of Identity Server I looked at there was a handler method where you would work out which claims to put into a token. I guess this would map into one of the custom handler lambda functions in Cognito. From there this would need to query Cognito and work out what claims to issue?
The final piece of the puzzle is how the API Gateway checks the claims. Can this be done in API Gateway or does the token need to be inspected in the Lambda function I will write to handle the API Gateway request?
Certainly using Identity Server and .Net there was a client library you would use in the API to inspect the claims and redact permissions accordingly. Guessing there is something similar in a Node JS Lambda function?
A few assumptions there as I'm basically in the dark. I think the basics are there but not sure how to connect everything together.
Hoping someone has figured this out.

Securing publicly accessible REST endpoints

We have a REST endpoint that provides some back end services to our publicly available Web site. The web site does not require any user authentication to access its content. Anyone can access it anonymously.
Given this scenario, we would still like to protect the back-end REST api to be somewhat secured in the sense that only users using our Web site can call it.
We dont want a malicious user to run a script outside the browser bombarding it for example.
We dont even want him to run a script automating the UI to access the endpoint.
I understand that a fully public endpoint without user authentication is somewhat impossible to secure. But can we restrict usage to valid scenarios?
Some ideas:
Use TLS/SSL for the communication - this protects the channel only.
Use some Api key (that periodically expires) that the client/browser needs to pass to the server. (a malicious user can still use the key)
Use the key to throttle the number of requests.
Use it with conjunction of a CSRF token??
Use CAPTCHA on the web site to ensure human user ( adds an element of annoyance to the final user).
Use IP whitelisting.
Use load balancing and scaling of server to handle loads.
I suppose this should be a scenario occurring in the wild.
What security steps are prevalent?
Is it possible to restrict usage via only the website and not via a script?
If its not possible to secure, what kind of mitigations are used with such public rest endpoints?

Security about a simple REST web service

Here is my little API with two URL :
/api/location/list -> GET
/api/location/detail -> GET
I'm looking for a process to secure this service with authentication. For now, it can be accessed by only one user (me).
I think oAuth is too complex in my case and I found this resource for designing a simple API.
I understand the principle of private/public key and HMAC but I have a big concern about this :
Say my webservice is consumed by an ajax request with GET verb. I have something like /api/location/list?apikkey=userid&hash=abcde.
A end user can easily sniffed the network during the request (via a simple chrome console), capture full url and access directly to the service multiple times (I think it's a case of replay attacks).
Differents resources talk about timestamp or nonce to make a request unique but I'm a bit lost with implementation.
Any ideas ?
You can try JWToken auth specs, simpler than Oauth, but avoid authorization data as url parameter if possible and use Header's request instead.
If needed consider also ssl encryption at tcp level.
Perhaps you could try to use a token-based approach for security, as described in this blog post:
Implementing authentication with tokens for RESTful applications - https://templth.wordpress.com/2015/01/05/implementing-authentication-with-tokens-for-restful-applications/
The idea is to authenticate to an authentication resource (that can be part of your application) to get temporary token that can be refreshed with a refresh token when expired.
With the use of HTTPS, it seems to be appropriate.
I think that it depends on the security level you expect. Signature-based authentication (the AWS approach) is great but is a bit complex to implement by hand.
Hope it helps you,
Thierry

Secure way to contact REST API for use with Html 5 / Javascript

This is a similar situation to the one raised in this question:
Javascript Calling a Rest API with App Name and App Password - How Can i Secure it
Here is the architecture overview:
The site is Html5/jquerymobile
It contacts what I call a "Wrapper" service.... This is a REST API I wrote in C#, to contact another 3rd party REST API. I do this because there are credentials in the Header and the API uses Basic Authentication. Credentials are therefore not publicized as they are only known server-side.
My "Wrapper" service does not currently implement any additional security. It is currently accessible from anywhere. The easiest and quickest way to lock it down is to restrict by IP, so no other IP anywhere except the server can actually contact my wrapper service.
The questions:
Is the locking by IP the only way to ensure that the API won't get hammered if it was otherwise accessible from anywhere?
If I convert this using Phonegap (which I have... and deployed successfully on Android), obviously the native app won't work if the web service is restricted.
Is there a way around this so I can allow traffic only from the mobile app, and not from any other source? I'm thinking along the lines of MD5 hash or something that could be sent to the wrapper API.. but unfortunately I'm thinking that info can easily be "sniffed".
Is my only viable option here to release the app as a web app, forcing browser use, thereby removing any concerns about allowing my web service to be hammered??
I believe the answer to this is a combination of a user token and encrypting the message through SSL.
The server can issue a valid user a token so we can identify him in future requests.
Encrypting it via SSL will ensure that this token cannot be sniffed.
https://security.stackexchange.com/questions/12531/ssl-with-get-and-post