securing credentials on front end react-native - react-native

I am creating an app using react-native. This app requires some sensitive data which must be stored securely and there are various options for that e.g, expo-secure-store.
Now i am a but confused regarding securing the data on front end.
I am using react-native-async-storage to store other data on front end.
Now it is treated as a bad practice to use the same for sensitive data.
But my question is, say i use expo-secure-store for sensitive data, but at the time of saving it like this;
SecureStore.setItemAsync(key, value);
where value is the sensitive part, isn't that still getting exposed while setting it in the code.
Please explain this and describe some better practices to store (or access) sensitive data on front end.
Thanks!

The documentation for the Google Maps Android SDK has instructions for restricting the API key usage to an app fingerprint: https://developers.google.com/maps/documentation/android-sdk/get-api-key
This reduces the risk of including the key in your app by only allowing the key to be used from a source that matches the fingerprint of the app certificate.
In practice the value of a Google Maps API key is fairly low, and is not the most attractive target for a bad actor. Frontend API keys are sensitive in that you can be billed for their usage, but unless you are specifically targeted, it's not a likely attack vector.
Truly sensitive keys, like those used to generate auth credentials or payment data, should always be kept on the backend, and any decent third-party service will be set up in a way that forces this to be the case (for example, Stripe).
You may get better answers by asking how or when to store specific keys.

Related

Any local privacy-oriented user authentication for mobile apps?

I'm building an app and I'm being very cautious about the user privacy on the app. I do not want to collect any data. Not even email IDs. Is there any way to do user authentication without email/phone number?
One idea for now is using biometrics on the phone itself. FaceID/TouchID etc. But that brings up challenges wrt syncing their data in case the user wants to use from a different phone. Any workarounds?
You can safely collect as much data as you like inside the app, so long as it stays there.
The problem is that you want to reliably identify a user account (though not any specific user data) without letting any of that data out. It's become quite common to use hashes (usually SHA256) of email addresses as identifiers, however, if everyone uses the same approach it's like a distributed rainbow table. You can however deploy the usual defence against such attacks by salting your hashes so that they are unique to your service.
If you encrypt the user's data on-device using a key that only they know, and only ever transmit and store encrypted data (i.e. to which you have no access), then they would be able to use the same local identifiers and their key to read the data from a different device. Because data is only ever encrypted and decrypted with the same key you can use symmetric encryption - look at using libsodium to do this.
You might want to consider some kind of 2FA to go with this as otherwise intercepting this identifier could allow unauthorised access.
Depending on the sensitivity of the traffic, you may want to try to hide meta-information such as connection dates, times, and volumes, so you could get the app to generate random data to hide the real data within.
Disclaimer - I Am Not A Cryptographer! I recommend you ask for more qualified responses on https://security.stackexchange.com.

Storing API Keys submitted by client in frontend

I know API keys need to be stored securely and should not be accessible client side. That being said, I also know that a lot of Wordpress plugins/ custom sites/ and such allow users to copy paste the API key into a text input on the admin panel.
My question is how do you do this securely? Do they hash it and save it to their database?
Say for example I made a react app or wordpress plugin that allowed users to do something with the Google Maps API. I know I can go get their API key and just hard code it in... but if I wanted to let the user update the key on their own - What would be the reccomended steps?
Thanks!
If I understand you correctly, you want your application to process secrets of third party APIs. A bit scary, but if you get the user consent - why not? First thing first - make sure the user understands what he is doing. Point out exactly what you will do with the API keys, what you will not do with the API keys and how will they be protected.
Personally I would never want to store such secrets in my own database, as this would be a single point of failure. When you are hacked, everyone is hacked. Why not put such secrets in - say - local storage so it never touches one of your servers?
Ok, in case it is your server that needs to do something, you could get the API key passed in a request, do something, but never log or persistently store the secret anywhere.
In case it is enough for the Java Script to do the job, local storage is even better solution.
One could think about encrypting the keys in the local storage, but I don't believe this would improve security a lot. I mean this would be security through obscurity and could by bypassed by someone with physical access to the machine/browser/user agent. But if someone would have such access, then probably some of the API keys would be one of the smaller problems.

Is there a way to secure an API key on a frontend page?

My service allow any HTML documents to be converted to PDF using a POST request.
It is mostly used on the backend of my client's server and thus, the API key used for the communication is kept private.
Now, I'm thinking of a way to let my client's visitors be able to call my service on behalf of my client API key, without exposing this secure API Key.
My main issue here is security. If my client add an XHR POST requests that contains the API key, someone can take that API key and use it for their own purpose and abusing my client's account.
I could filter by domain, but this is easily spoofed so it's not possible.
I was wondering if there was a way to call a private service and be identified without risking its identity to be stolen, from the client ('s client) side?
If you're providing this sublet for authenticated users, then it's fairly trivial to give them unique keys (something that hashes their user ID or session against the API key and an initial timestamp, and checks it / logs it / looks for brutes before accessing the API). If you're doing it on the open web, without any kind of user authentication, then rate limiting gets very tricky indeed. Generally you'd want to use a combination of session hashes, IP address, operating system and browser data to create an anonymous profile that gets a temporary key on the frontend. One fairly solid way to do this is to force users through a CAPTCHA before serving a temporary key that allows them a limited number of uses of the permanent key. Any user whose ip/browser/session matches the existing attributes of a known client key is shunted to that one (and gets to skip the CAPTCHA); anyone who doesn't match an existing profile gets the CAPTCHA. That makes you a less attractive target for spoofing. On top of that, you should always rate-limit the entire thing, within a reasonable number of hits per day based on what kind of traffic you expect (or can afford), just so you don't have any surprises. This is the minimal security you'd want if your client's money is on the line every time their API key is used. It will require a simple database to store these "profiles", track usage, check for brutes and maintain the currently valid client keys. Client keys should always be expired regularly - either with a time diff against when they were created, or a regular cron process, or a maximum number of uses, etc.
One other thing I frequently do is rate-limit based on a curve. If I think 5 uses per minute is reasonable, for example, then after 5 uses in a minute from a session, each usage adds a delay of a fraction of a second * the number of uses in the last minute, squared, before the data is served.
The best answer would be to put this all behind a login system and secure that.
Assuming that you are using OAuth kind of system, In that case, make use of Access Token Mechanism that provides access to private API/User's data on behalf of User(Client) without exposing his/her credentials or API Key(Authentication key), also the access token can be expired based on the time/usage.
Example: The access token is generated against a single endpoint that can be the Html Conversion endpoint and will be expired once the action completion.
https://auth0.com/docs/tokens/access-token
And following blog post would be helpful to architect your authentication system
https://templth.wordpress.com/2015/01/05/implementing-authentication-with-tokens-for-restful-applications/
there is no good way to do front-end secure storage but my recommendation is :
is an API that used HMAC signing of requests in combination with OAuth authentication. The API key is actually a signing key. they key does not get transferred. The API key can still get found on the front-end but it becomes useless because you still need the OAuth token to send a valid request.
i know users will have to login in, but you can see this as an advantage because atleast you can log who is using the app by getting information from oauth.
please consider back-end secure storage!
You can use JWT tokens in my opinion. On the basis of username, password or any other info you can generate unique jwt tokens for different users.
Anyone can decipher these jwt tokens but not he unique security token.
If you want to add more more security to tokens, use JWE, encrypted web tokens.
More about these schemes can be found at https://medium.facilelogin.com/jwt-jws-and-jwe-for-not-so-dummies-b63310d201a3
Hashing is a decent option and should be done anyway, but for a fully secure method that wouldn't add too much complexity, you could simply abstract away from the authorization/API key by building your own API to interface with the API. This way you could both limit the kinds of things that can be done with the API key and also completely obscure the API key from the user
I don't think you should always go for user auth or JWT, it just doesn't fit all use cases. The idea of using a Captcha is interesting but also somewhat complex.
If complexity is not an issue I would rather use an infrastructure approach, I'm most familiar with AWS so I'll focus on that. Assuming you can change the host of your front end you can have your site hosted on an S3 bucket, served through a CDN, and create a proxy Lambda function that will hold the logic to call your API and store the API key as an encrypted environment variable. This Lambda you call through an API Gateway that can only be called by a specific IAM role which the S3 bucket also uses. You can also use a Cognito User Pool without authentication.
Going back to a simpler alternative the Captcha approach can be implemented as an attestation provider. I know of two services that do this, Firebase and KOR Connect. Due to Firebase using this approach only for their own resources as of the time of this writing I much rather use KOR Connect as it’s a very simple middleware that basically solves this issue. I won't go into detail about these services as it’s not the main concern of this topic but you can check the documentation their respective links.

Architecturing testmode/livemode using OAuth 2 token

The title is a bit obscure. I'm interested about some feedbacks on a specific architecture pattern.
Let's take as an example the Stripe API: when you are using this API, the system is basically broken into two parts: live mode and test mode. If you hit the "/customers" end-point, you can either retrieve test mode customers or live mode customers, based on the type of API key used.
I'm asking myself how I could implement such a pattern using an OAuth 2 access token.
In my workflow, I have a single application page (JavaScript) that communicates through my API. I have a "live"/"test" switch, so basically my whole website is replicated into two distinct environments.
When I log in into my application, my authorization server creates a unique access token (OAuth 2 Bearer token), that is send for each requests. But obviously, my access token is tied to the "session", not an "environment" (live or false), so if I want to implement a switch live mode / test mode, I cannot rely on the token, because the token is "generic".
I've thought about two options:
Depending on live mode or test mode, I send an additional header to all my request (like X-Livemode which is either true or false). Then, in my back-end, I reuse this header to automatically adds a filter on all my requests.
If I switch to live mode or test mode, I ask my authorization server another access token. This would means that access token would have additional context information. However this seems a bit complicated, and I'm not sure that OAuth 2 spec allows token to have such additional information.
I'm not sure if this post is clear or not :p.
The second part of the question, is what is the best way to implement such a system where all the resources are basically duplicated between live / test mode ?
In my understand, it should be as simple as adding a "isLivemode" property to all resources, and make sure that all my SQL queries are aware of this. Is this correct?
Thanks!
A much simpler solution I've used in the past (albeit a bit of a workaround) is just to append "live" or "test" (base64 or hex encoded) to the api key, like so:
Imagine your actual key is:
9a0554259914a86fb9e7eb014e4e5d52
In your key presentation, present your key to the user as:
9a0554259914a86fb9e7eb014e4e5d526c697665
Then use a regular expression to strip off the known characters.
Alternatively, if you're equipped to handle key-value maps, a more "OAuth2-spec" approach would be to generate unique keys for live and test and do a key-value map lookup on the request to determine if one belongs to live or test.

Best way to generate API Key?

Use Case
I'm building an iPhone app with a simple signup and login.
When a user signs up/logs in, I want the Ruby (Sinatra) server to generate/fetch and return an access token for that user that the iPhone client can then send with every subsequent request using Basic Authentication over HTTPS.
I'm not yet implementing OAuth 2.0 so that third party apps can access the server. Right now, I'm just building a simple, internal API (for my own, first-party, iPhone app).
Example
Basically, I want to generate a secret API key like Stripe's: https://manage.stripe.com/account/apikeys
For example: sk_test_NMss5Xyp42TnLD9tW9vANWMr
What's the best way to do that, say in Ruby?
The Ruby stdlib provides an entire class of secure random data generators called SecureRandom. Whatever you want, you can probably find it there.
Stripe's keys are essentially URL-safe Base64. You can get something very similar like so:
require 'securerandom'
p "sk_test_" + SecureRandom.urlsafe_base64
(Stripe does strip out non-alphanumeric characters, but that's trivial to do with gsub if you don't want hyphens in your keys.)
I recently published a gem called sssecrets (for Simple Structured Secrets) to solve this problem.
Sssecrets is a reusable implementation of GitHub's API token format (which is also used by NPM), and it's designed to make it simple for developers to issue secure secret tokens that are easy to detect when leaked.
Simple Structured Secrets provides a compact format with properties that are optimized for detection with static analysis tools. That makes it possible to automatically detect when secrets are leaked in a codebase using features like GitHub Secret Scanning or GitLab Secret Detection.
Why Use Structured Secrets?
Using a structured format for secrets is really important for security reasons. If you're a developer and your application issues some kind of access tokens (API keys, PATs, etc), you should try to format these in a way that both identifies the string as a secret token and provides insight into its permissions. For bonus points, you should also provide example (dummy) tokens and regexes for them in your documentation.
Here's an example of a bad secret. As of the time of writing, HashiCorp Vault's API access tokens look like this (ref):
f3b09679-3001-009d-2b80-9c306ab81aa6
You might think that this is pretty is a pretty easy pattern to search for, but here's the issue: It's just a UUID string.
While random, strings in this format are used in many places for non-sensitive purposes. Meaning that, given a random UUID formatted string, it's impossible to know whether it's a sensitive API credential or a garden-variety identifier for something mundane. In cases like these, secret scanning can't help much.
What's in a Structured Secret?
Structured secrets have three parts:
A prefix (2-10 characters, defined by you)
30 characters of randomness
A 6 character checksum
That's it!
Here's the format:
[prefix]_[randomness][checksum]
An example Sssecret, with an org of t and a type of k, looks like this:
tk_GNrRoBa1p9nuwm7XrWkrhYUNQ7edOw4GUp8I
Prefix
Token prefixes are a simple and effective method to make tokens identifiable. Slack, Stripe, GitHub, and others have adopted this approach to great effect.
Sssecrets allows you to provide two abbreviated strings, org and type, which together make up the token prefix. Generally, org would be used to specify an overarching identifier (like your company or app), while type is intended to identify the token type (i.e., OAuth tokens, refresh tokens, etc) in some way. To maintain a compact and consistent format for Sssecret tokens, org and type together should not exceed 10 characters in length.
Entropy
Simple Structured Secret tokens have an entropy of 178:
Math.log(((“a”..“z”).to_a + (“A”..“Z”).to_a + (0..9).to_a).length)/Math.log(2) * 30 = 178
See the GitHub blog.
Checksum
The random component of the token is used to calculate a CRC32 checksum. This checksum is encoded in Base62 and padded with leading zeroes to ensure it's always 6 characters in length.
The token checksum can be used as a first-pass validity check. Using these checksums, false positives can be more or less eliminated when a codebase is being scanned for secrets, as fake tokens can be ignored without the need to query a backend or database.
Note that this library can only check whether a given token is in the correct form and has a valid checksum. To fully determine whether a given token is active, you'll still need to implement your own logic for checking the validity of tokens you've issued.
Another note: Because Sssecrets uses the same format as GitHub tokens, you can also perform offline validation of GitHub-issued secrets with SimpleStructuredSecrets#validate.
Further Reading
You can learn more about GitHub's design process and the properties of this API token format on the GitHub blog.