I have an application written in angularjs and a dropwizard backend. All API calls are ajax, with the exception of file downloads, which is done by performing a redirect to a standard GET request.
All API calls are secured through a token which is passed as a Token header. We use SSL for all APIs.
The download GET request works but I'm having a hard time figuring out how to secure it. I have no way of setting a custom header, which is required to pass the token. So theoretically, I'm left with two options, clearly none of them acceptable: 1. Pass the token as one the GET parameters 2. Leave the download unsecured.
Any ideas how to secure file download?
Putting a secret token in a URL query parameter isn't great because URL tend to be leakable, for example through history/logging/referrers. There are ways to mitigate this: for example you could have the server side issue a download token that is only good for one use or for a limited amount of time. Or the client could pass a time-limited token created using a signature over the secret token that the server side could verify.
Alternatively you could, just for this one interface (eg path-limited, quitckly-expiring) put the token in a cookie.
Another approach is to download the whole file through AJAX, thus allowing you to set the header as normal. Then you have to present the content as a downloadable local resource, which requires a cocktail of browser-specific hacks (eg using data: or filesystem: URLs, and potentially links with the download attribute). Given the complication this isn't usually worth bothering with, especially if the file is very large which may present further storage constraints.
Related
I am building my first ever Chrome browser extension and I am struggling to find the right solution for handling authentication. There is a requirement that the extension stay logged in as long as possible, to reduce the need for the user to log in often. This means we would need to use Refresh Tokens. I would very much like to handle all authentication on the background script but this is no longer persistent in MV3 nor does it have access to the DOM.
This being the case, I see these options:
use Auth0 React SDK on the content scripts - this means all my authentication logic will run in a somewhat less secure environment but the token will be handled by the library and I will be able to access it in all my content and popup scripts (if I need persistence across page refreshes, I would still need to use localStorage, I believe). But this means that the background script will not have access to the token and it will need one of the other scripts to retrieve it and send it through a message
implement the Authorization Code Flow with PKCE following the steps in this tutorial on the background script - this will mean that all my auth logic is running in a more secure environment but I don't have a way of storing the token, other than using chrome.storage. It's also a bit tricky to silently retrieve the token (or check if user is still logged in) from the background script (it can be done using an injected iframe and the web_message response type or with chrome.identitybut there are still issues with the redirect_uri which needs to be listed in the Allowed Origin config of the Auth0 app - so you can only easily do this on the pages of the extension).
I know that the recommended solution for an SPA is using the SDK but I would like to know if this is also the right solution for a browser extension. Based on this article on Token Storage, localStorage is dangerous especially due to third-party scripts. Seeing that the MV3 manifest has now removed the ability to execute remote code, is localStorage an acceptable way to store tokens?
I have implemented both options using the docs provided but I am unsure as to what is the best solution, given the changes introduced by MV3.
Thank you
I am building a frontend application using react and I am wondering whether it is risky to expose API endpoint URLs (ex: https://myapi.com/v1/getitems) on GitHub, assuming that the endpoint has several security measures that are not exposed such as CORS and JWT Token Bearer Authentication. I would assume not, since, if someone were to take the endpoint and send requests, they would need a token and be allowed to do so by CORS.
Is there any security risk in doing so?
Yes. Don't add the base url of your api on github in plain view. Even though you might have CORS and Authorization, that doesn't stop a malicious actor to keep spamming your back-end.
What you do is create a .env file in your root folder. You can use a library like #beam-australia/react-env and there are others as well.
You add in the .env file the values that are important for your environment and that are usually secrets, and you want them to not be visible in your code. You do it like so:
API_URL="https://myapi.com/v1"
And then you access this variable in your code with env("API-URL") ( in the #beam-australia/react-env case, but others libraries work the same). Keep in mind that you need to add .env in .gitignore so that the .env file is not pushed to github.
Regarding requests, you can make one like so:
fetch(`${env("API_URL}/getitems`)
This way your code will be stripped of the API's base url and if someone sees your code it will see only the endpoint, not the full url.
Publishing the code of the API is risky on its own. Somebody can find a vulnerability in it and instantly hack it. If you add the address of the API to the code you help this kind of attacks. They can get the address with some investigation; OSINT and social engineering too, but better to reduce the attack surface.
As of the secrets, they must never be near to the code, because you or another developer can accidentally publish it. It happened too many times with many developers, so better to take this seriously. If you want to keep the address in secret, then you must extract it from the code and put it in the configuration of the production environment which is imported from a totally different location than your code. Using environment variables like Alex suggested is a good idea for this. Nowadays it is common to use docker, which has a way to manage secrets, so you don't need to reinvent the wheel: https://docs.docker.com/engine/swarm/secrets/ Another aspect that the configuration belongs to the actual instance. In OOP terms you want to describe the injected properties of an object in its class or in a global variable, which is an antipattern.
As of client side REST clients like javascript applications running in the browser or Android/iOS apps, you must not publish your secrets along with the REST client, otherwise it is not a secret anymore. In that case you need a server side part for the REST client and for example sign and encrypt JWT there with a secret key. It is your decision whether this server side part of the REST client sends the HTTP request to the REST API and in that case you can hide the URI of the REST API or it just manages the JWT and the client side part of the REST client sends it. If the server side part of the REST client sends the HTTP request to the REST API, then you can even use traditional sessions with session cookies between the client side and the server side parts of the REST client, but you cannot use them between the server side part of the REST client and the REST API where the communication must be stateless. Though it does not make much sense to have a separate REST API if you don't have multiple different REST clients in this scenario e.g. browser clients for JS and JSless browsers, Android and iOS clients, fully automated clients running on servers, etc. So don't confuse the REST client - REST API relationship with the browser - HTTP server relationship, because they are not necessarily the same. Most of the REST clients run on servers, not in the browser.
Sorry if this might be a bit of a trivial question, but I wanna be sure and couldn't exactly find a definitive answer online.
I am writing a small app that uses Mapbox, and I am using react-map-gl for it. They require the access token on the client side, so they suggest using an environment variable. My question is would it be okay to simply create a .env file in the front-end folder and put the variable there?
Thanks!
You can't get away from revealing API keys on the front end. If someone wants to dig around in your source code, they will find them.
However, you should always configure any API key that is visible on the Internet to be restricted to specific referrers, i.e. the domain of your website.
Usually this is done during creation of an API key through your provider's dashboard.
For Mapbox, you can read the documentation on restricting API tokens here. It states:
You can make your access tokens for web maps more secure by adding URL restrictions. When you add a URL restriction to a token, that token will only work for requests that originate from the URLs you specify. Tokens without restrictions will work for requests originating from any URL.
(emphasis my own)
They require the access token on the client side, so they suggest using an environment variable. My question is would it be okay to simply create a .env file in the front-end folder and put the variable there?
There are two reasons one uses environment variables in front-end development:
As a convenience, to keep environment-specific configuration removed from source code.
To keep sensitive information out of source code. You shouldn't commit API tokens or other similarly sensitive details to your version control.
Using environment variables in front-end code will not to keep their values secret from the end user. Whatever the value of an environment variable is at build time will be visible in the compiled output.
I am using ionic framework as a matter of course I use angular.js for front end. on the back end, I use spring-boot for data handling and API management.
I have used a single session and csrf token exchange between client and server.
However, I have been asked to use in some sections one extra security control. as an example one section of application can take as long as server is alive. Another section can stay alive till couple of weeks and another section will ask in every single request or every single.
How can I handle this design problem?
Modern webapps use JSON Web Tokens (JWT)
there is also an angular package you can use.
These tokens are sent with every request and contain arbitrary information about the user or other data. They are issued by your API on successful login and stored in your frontend. The issued token is then attached to every request header when requesting your API. You can then in the backend decode the token and determine if the user has all the required rights to continue, if the token is still valid our outdated for your different use cases.
I am not familiar with your backend solution but i am sure you can find some jwt packages for it or implement an easy solution yourself. (Googling for spring jwt gave quite some results)
I'm pretty new to go and I want to build a CRUD rest API on GAE without views just simple JSON Rest API.
There is allot of frameworks out there,
go-http-routing-benchmark.
But I'm not sure which one will be most suitable for GAE.
My main concern is how to handle a safe and secure session .
As mentioned in a comment, you can start with the Go standard library, and only utilize 3rd party libs if you reach a point when the standard library is not sufficient for you (which point you may never reach).
If your clients are not browsers (you said you don't want any views) but any other arbitrary HTTP clients, an HTTP session may not be what you want. An HTTP session is usually managed by storing a session ID in an HTTP cookie which is automatically sent by the browser along with each HTTP request, and at the server side this session ID is read and an associated, server side data structue is looked up by it.
A common solution is to use some kind of secret information referred to as a key or API key. The idea is that if you want to grant access to someone, you generate a secret key (e.g. a random text) at server side which you store in the database. You send this key to the client who has to attach this to every API request he makes. At server side in the beginning of each API request you can check if the provided API key is valid (this also identifies the caller) and act accordingly.
The API key can be sent in various ways by the clients, e.g. as a URL parameter (strongly not recommended for unsecure HTTP requests but is perfectly fine for HTTPS requests), as an HTTP header field or as part of the request data structure. It is really up to you how you expect it, usually depends on how the requests look like (e.g. if they don't include any data, it's better to put the KEY in a header or URL parameter; if the clients are expected to send other, complex data which can be in the form of JSON text, it can be convenient to also include the API key in the JSON data too).