I have read several introductory articles about implementing Web Push notifications for desktop browsers but am unable to understand the security part behind storing the obtained subscriptions from users's browser on backend server.
There are many websites that ask for permission to send you push notifications without authenticating/registering on those websites first. If I do grant them the permission and they store this permission string onto their backend server for later use, who's to say I wont generate another subscription string and send it to their backend server's endpoint that they used to save my subscription? and therefore flood their database with subscription entries.
What is the mechanism of identification and validation of received subscription on the backend server when there is no authentication/registration of users available on the website?
To illustrate better:
Website JS code asks browser for push permission -> I grant it by pressing 'allow' on the popped up window -> they take it and store it on their server using HTTP POST for example. Using a simple script I establish connection with the same HTTP endpoint and POST more subscriptions in the same format as the endpoint expects, therefore flooding the backend database.
After a lot of reading and consulting with one of the popular Web Push notification services I confirmed that it is indeed possible to flood backend server's database with forged subscription URLs when there is no authentication available on the website that uses the notification service.
The ways to defend against such attack are similar to the ways of defending agianst DDoS attacks: IP filtering, deleting database entries manually, etc.
Related
I need to send a particular header parameter in all ajax calls which is a very confidential information. I don't want from the end user to see any of the requests made in network tab of any browser. Is there any way to prevent it? or is it possible to make ajax calls directly from node server which doesn't go through browser?
Any call made on the client side cannot be hidden, as it's "client" side of the website. Even if you'd success to hide it in browser, any software could monitor it with tools such as network sniffers / monitors, WireShark for instance.
So the answer is no
When you go to a restaurent and order something, can the waiter subsequently make you forget your last instruction/order? The answer is NO, same as the answer to this question.
It all starts with client making a request to the server, hence client is the driving force of the whole interaction. Server just serves as per the instructions from client (and maliciously does some extra work on its own, say auditing, database update, cookie addition etc.).
Hence there is no way a 'server' can restrict client to see its own instructions.
Just simply don't send sensitive information directly via headers. Encrypt them via your client side code and add them within cookies or any other HTTP header(s).
Quoting from internet:
Client/server architecture is a producer/consumer computing
architecture where the server acts as the producer and the client as a
consumer. The server houses and provides high-end, computing-intensive
services to the client on demand. These services can include
application access, storage, file sharing, printer access and/or
direct access to the server’s raw computing power.
Client/server architecture works when the client computer sends a
resource or process request to the server over the network connection,
which is then processed and delivered to the client. A server computer
can manage several clients simultaneously, whereas one client can be
connected to several servers at a time, each providing a different set
of services. In its simplest form, the internet is also based on
client/server architecture where web servers serve many simultaneous
users with website data.
Never trust to client. Ever. Never ever. Doesn't matter what you do assume its been cracked. Hackers have all the tools and complete control of the client and all software running on it. Assume they've written their own network stack, their own TLS implementation, their own browser, their own operating system...
If you need to keep it secure, keep it on your servers. If you need to communicate 'privileged' information (assuming you remember that once you've sent it to a client they can access it) don't, tokenise it on your server and send them the token. And if you're generating tokens make sure they're very random and utterly opaque - don't encrypt anything in the token because you should assume they can crack that too, regardless how secure you think the library you are using is (assume it'll one day be cracked).
Never expose the confidential data on the client-side.
The best practice is to encrypt your confidential data on the server-side, send it to the client, and decrypt on the server end when the client sends you back.
If you don't want encryption or this confidential information is result of user actions itself then make a key-value pair in a database, where the key is something which can be exposed to the client (let's say username) and value is the confidential information. Hence now we have 1-1 mapping, so fetch this confidential information on server-side from database using the key we are getting from the frontend.
I hope this will help.
Good Luck!!
Once a user subscribes to push notifications, I get the subscription info in my JavaScript code. I want to send this information to the server for storage to be used for future notifications.
I assume that the endpoint for the AJAX POST request should be public (the website itself is publicly accessible). Should the endpoint be completely open? Should I use some token generated on the server that expires after a certain period of time?
My concern is that, if it's open, it can be used maliciously to post data to my server. Should there be some validation of the data? If so, what kind of validation applies to subscription JSON objects?
What's the best practice for doing this securely (if any)?
Background:
I am building a reactJS application using AWS cognito, dynamo and S3. The application is based in the recruitment sector where employers and employees can post and view jobs respectively. When an employee applies for a job the employer can view the employees profile and decided whether or not to message them. Employees and employers converse via an on-site messaging service.
The Question:
What is the best method to facilitate user chat?
i.e. what is a nice & efficient way to store messages and notify users when they have a new message.
Our current approach is to have a setTimeout() on the site and check for new messages but this will be very inefficient so i'm looking for some guidance.
I would like to stay inside the amazon infrastructure as much as possible but I am open to all suggestions.
I'm currently building something similar for a startup I'm working at. Our React app is served by node.js server, while the API backend is provided by a django API with drf. As in your user chat case, we need to handle some real time data arriving in the frontend.
Our approach
The solution may be split up into inter server and server-browser realtime communication:
We use redis (aws elasticache to be exact) as a publish/ subscribe message queue to push incoming data from the API backend to the nodejs server. Specifically, whenever an instance of the model in question is created due to an HTTP POST call (i.e. in your case a message, which is send to the server), we publish JSON serialized information on a channel specific to the actors of concern.
On the node.js servers, we subscribe to channels of interest and receive information from the backend in real-time. We then use socket.io to provide a websocket connection to the frontend, which may be easily integrated with React.
Limitations of this approach
You cannot simply server your React app as a static website from S3 and have to rely on a node x React approach. react-boilerplat(by Max Stoiber I think) is a great way to start.
What's more, you can also use websockets end to end. We use this approach as our data source isn't a browser but a constrained device.
Hope that helps!
Is there anyway to secure an API key when using it on a React javascript file ? For example;
emailjs.init("API_KEY");
You may want to check how Google Firebase does pure client-side authentication: https://firebase.google.com/products/auth/
Edited:
This general introduction to Authentication using API-keys, OAuth etc (source: codecademy course on bulding web-apps) may help understand what API keys are meant for and why it should't be necessary to secure them. The reason is that there are other ways to deal with secret information, as described in this article.
Authentication
INTRODUCTION
Authentication is the process used by applications to determine and confirm identities of users. It ensures that the correct content is shown to users. More importantly, it ensures that incorrect content is secured and unavailable to unauthorized users.
In this article, we’ll discuss a few of the common design patterns for these interactions. You’ll need to have some basic understanding of HTTP requests, since these methods all use HTTP requests to exchange information.
PASSWORD AUTHENTICATION
The most common implementation of authentication requires a user to input their username or email and a password. The application's server then checks the supplied credentials to determine if the user exists and if the supplied password is correct. If the credentials are correct, the user is logged in and able to use the application as thatthe user.
Typically, upon a successful login, the application will respond with an authentication token (or auth token) for the client to use for additional HTTP requests. This token is then stored on the user's computer, preventing the need for users to continuously log in.
This token generally expires after a certain amount of time, ensuring the correct user is using the application over time as well.
API KEYS
While it is common to think of authentication as the interaction between a human user and an application, sometimes the user is another application.
Many apps expose interfaces to their information in the form of an API (application program interface). For example, the Spotify API provides endpoints for almost all of its functionality. This allows applications to fetch data from the Spotify music catalog and manage user’s playlists and saved music.
Since these external requests could overwhelm a service and also access user information, they need to be secured using authentication.
The most basic pattern for API access from another application is using an API key.
Public APIs usually provide a developer portal where you can register your application and generate a corresponding API key. This key is then unique to your application. When your application makes a request, this key is sent along with it. The API can then verify that your application is allowed access and provide the correct response based on the permission level of your application.
The API can track what type and frequency of requests each application is making. This data can be used to throttle requests from a specific application to a pre-defined level of service. This prevents applications from spamming an endpoint or abusing user data, since the API can easily block that application's API key and prevent further malicious use of the API by that application.
OAUTH
For many applications, a generic developer-level API key is not sufficient. As mentioned earlier, APIs sometimes have the ability to provide access to user-level data. However, most services only provide this private data if the user enables it.
For example, Facebook doesn't want Tinder to access all of their users' data, just the users who have opted in to allowing the sharing of data to better help them find a match in their area.
A basic approach to this problem might be to have the user provide their login credentials to the intermediary application, but this is not very secure and would give full access to the requesting application, when the requesting application might only need a very limited set of privileges to function.
OAuth defines a more elegant approach to this problem. It was developed in November 2006 by lead Twitter developer Blaine Cook and version 1.0 was published in April 2010.
OAuth is an open standard and is commonly used to grant permission for applications to access user information without forcing users to give away their passwords.
An open standard is a publicly available definition of how some functionality should work. However, the standard does not actually build out that functionality.
As a result, each API is required to implement their own version of OAuth and therefore may have a slightly different implementation or flow. However, they're all based around the same OAuth specification.
This can make using a new OAuth API a little more frustrating. However, with time you will begin noticing the similarities between API authentication flows and be able to use them in your applications with increasing ease. Below is a summary of the standard OAuth flow.
GENERIC OAUTH FLOW
Many applications implementing OAuth will first ask the user to select which service they would like to use for credentials:
Login with Google, Facebook or Twitter
After selecting the service, the user will be redirected to the service to login. This login confirms the user’s identity and typically provides the user with a list of permissions the originating application is attempting to gain on the user’s account.
If the user confirms they want to allow this access, they will be redirected back to the original site, along with an access token. This access token is then saved by the originating application.
Like a developer API key, this access token will be included on requests by the application to prove that the user has granted access and enable access to the appropriate content for that user. When a user returns to the application, the token will be retrieved and they will not have to re-authenticate.
OAUTH 2
Since OAuth evolved out of Twitter, there were important use cases not originally considered as part of the specification. Eventually, this led to the creation of a new version of the specification, called OAuth 2.
Among other improvements, OAuth 2 allows for different authentication flows depending on the specific application requesting access and the level of access being requested.
OAuth 2 is still an open standard, so each API will have its own flow based on its particular implementation. Below, we’ll discuss a few of the common OAuth 2 flows and how they are used.
CLIENT CREDENTIALS GRANT
Sometimes an application will not need access to user information but may implement the added security and consistency of the OAuth 2 specification. This type of grant is used to access application-level data (similar to the developer API key above) and the end user does not participate in this flow.
Instead of an API key, a client ID and a client secret (strings provided to the application when it was authorized to use the API) are exchanged for an access token (and sometimes a refresh token). We will discuss refresh tokens in more depth later.
This flow is similar to our first example, where an email and password were exchanged for an authentication token.
It is essential to ensure the client secret does not become public information, just like a password. As a result, developers should be careful not to accidentally commit this information to a public git repository. Additionally, to ensure integrity of the secret key, it should not be exposed on the client-side and all requests containing it should be sent server-side.
Similar to the previously-mentioned keys, the returned access token is included on requests to identify the client making the requests and is subject to API restrictions.
This access token is often short-lived, expiring frequently. Upon expiration, a new access token can be obtained by re-sending the client credentials or, preferably, a refresh token.
Refresh tokens are an important feature of the OAuth 2 updates, encouraging access tokens to expire often and, as a result, be continuously changed (in the original OAuth specification, access tokens could last for time periods in the range of years). When a refresh token is used to generate a new access token, it typically expires any previous access tokens.
AUTHORIZATION CODE GRANT
This flow is one of the most common implementations of OAuth and will look familiar if you’ve ever signed into a web application with Google or Facebook. It is similar to the OAuth flow described earlier with an added step linking the requesting application to the authentication.
A user is redirected to the authenticating site, verifies the application requesting access and permissions, and is redirected back to the referring site with an authorization code.
The requesting application then takes this code and submits it to the authenticating API, along with the application’s client ID and client secret to receive an access token and a refresh token. This access token and refresh token are then used in the same manner as the previous flow.
To avoid exposing the client ID and secret, this step of the flow should be done on the server side of the requesting application.
Since tokens are tied both to users and requesting applications, the API has a great deal of control over limiting access based on user behavior, application behavior, or both.
IMPLICIT GRANT
The previous two methods cause the client secret key to be exposed, so they need to be handled server-side. Some applications may need to access an OAuth API but don't have the necessary server-side capabilities to keep this information secure.
The Implicit Grant OAuth flow was designed for this very use case. This flow prompts the user through similar authorization steps as the Authorization Code flow, but does not involve the exchange of the client secret.
The result of this interaction is an access token, and typically no refresh token. The access token is then used by application to make additional requests to the service, but is not sent to the server side of the requesting application.
This flow allows applications to use OAuth APIs without fear of potentially exposing long-term access to a user or application's information.
CONCLUSION
OAuth provides powerful access to a diverse set of sites and information. By using it correctly, you can reduce sign-up friction and enrich user experience in your applications.
No, if it's out in public, it is public.
But you can set up a server that takes care of the communication in the background so you key would be kept secret.
In the case of Firebase it seams, that there shouldn't be a security risk though. See this answer here
I've been looking around for an answer to this question, but it looks like that nobody does this. Imagine you are designing a javascript REST client, and you want to create a login page. Surely, after the login you will be authenticated.
So the following requests to the REST API will depend on your current user id, which should be stored on the client side following the RESTful way.
My question is how to store this "session" information using Javascript. I've looked into cookies, but it seems to me too much plain text for one to trust. Also using cookies one could store there an session id that maps to the user information on the server, but this violates the Stateless concept from REST.
Which the best approach to solve this problem?
We are also building similar kind of architecture where RESTful API will be accessed by a javascript client.
We will authenticate client with client credentials and generate an authentication token and that will be sent to client. Client will store it in cookie or in local data store. Further requests to API from this client will be sent using HTTP authorization header and including that token in the header. We will authorize the request at API end for the given token and request will be served once it is authenticated.
Until n unless you don't access cookie information on server side I don't think this will violate stateless principle of REST as we are not maintaining any state of the client on server (we are but not binding it to any server). Regarding the authentication process using token, I don't think we are binding the server and client here, because we have multiple servers and using load balancer and still this request may be served by any server (similar to Google api).
Note: We are doing this using HTTPS protocol so we are sure that all this communication is secured.