I'm using smartystreets to verify address, etc.,. The only setting I'm giving them is the referrer URL.
When I request with postman by passing the correct referrer it works fine.
What if someone supplies the same header from AWS CloudFront and steals my account subscription limits.
Trying to understand how my subscription is protected.
Thanks.
Here is how I could query without a subscription from smartystreets,
URL Used GET with (Referrer: https://smartystreets.com/) Header:
https://us-zipcode.api.smartystreets.com/lookup?auth-id=21102174564513388&agent=smartystreets%20(website%3Ademo%2Fsingle-address%40latest)&city=Tustin&state=CA&zipcode=92780&candidates=5&geocode=true&input_id=0
Exposed Authentication TokenID: 21102174564513388
You are correct that if someone managed to steal your domain then they would be able to use your SmartyStreets subscription. The silver lining here is that all requests from browsers that use website keys (which are intended to be used in public, front-facing javascript code) are rate-limited, preventing the number of lookups that can happen. In the event of a stolen domain you could proactively delete the website keys on your account or you could have your SmartyStreets subscription shut down within a matter of minutes to prevent unauthorized access.
More info about website keys and the basics of their security model:
https://smartystreets.com/docs/cloud/authentication
BTW, I'm a back-end engineer at SmartyStreets.
Related
My backend code usually wraps the client calls and exposes them via an endpoint like this:
import stripe
stripe.key = "API_KEY"
def wrap_create_customer():
return stripe.create_customer()
Clearly, it's possible to just reverse engineer my backend API and start calling it to read customer data, process charges etc. Effectively, Stripe API is exposed via my backend, since the Frontend-Backend connection is public. (Just like all backend starter codes in Stripe tutorials).
How do I secure the client-backend communication?
My frontend is a public, static site. It is not authenticated with the backend. To prevent requests from foreign origin, I am requiring the origin of the request to belong to my web domain.
Q: But if that's the fix, it would imply that validating the origin would be a sufficient condition to identify the real owner of the request. Then why doesn't Stripe let us move our code fully client side?
The only reason for requiring the Stripe Secret key is to authenticate requests. Why not just add allowed origins somewhere in the Stripe dashboard instead of requiring the key?
Q2: Is the whole reason behind backend code, to simply hide the Stripe Live key from public? Even if the backend can be accessed via 'non-secure' endpoints?
Q3: What steps should I undertake to have a secure client <-> backend integration, so that my backend is guaranteed to know that the request was indeed made by the client. (Client is a front-end application).
Typically, (I've never worked with stripe in particular, but with other similar providers) this works as follows:
The frontend includes an SDK which is initialized with a vendorId and maybe some productIds. There's nothing secret about this information. Because even if anybody else knows them, the only thing he can do with it is to buy items from your stripe account.
When a checkout is to be made, the client sends a checkout/{venderId}/{productId} request to the payment provider. Some providers only provide "checkout links", where the customers are redirected to a secure page hosted on the provider's system. This handles all the payment relevant stuff (secure input of credit card, ... you really don't want to know the customers credit card information!)
once the checkout is completed, the payment provider calls a webhook at your backend sending you all the necessary information about the customer (name, purchased item, transaction id, ...)
you process that information at your backend, and store it somewhere. You can make some infomation available to the frontend for instance via the transaction id
the fontend will also get the transaction id from the SDK, so it can query your backend using this transaction id. What information you want/need to expose to the frontend is completely up to you.
Typically, there is absolutely no need to expose any other of your communication between your backend and paymentprovider via API, let alone forward data from the payment provider to the frontend. Especially, if anybody can access your API without authentication. Of course, you would probably need also some administrative API access too, but we agree, that this is certainly protected by some strong authentication.
In order to prevent fraud/abuse (such as Card Testing) of your Stripe account by malicious users, you'll want to protect some of your Stripe-powered endpoints. Stripe does recommend several mitigations, including user authentication, rate limits & captchas. Depending on your application & business, you might need a combination of several of these.
Note that user authentication can be added to static sites using a variety of self-hosted or third-party powered tools. GatsbyJS has a some pretty good documentation of this with multiple examples. Pretty much any pure client technique can be spoofed (such as origin, referrer etc), so those alone would not be sufficient to protect your backend server.
I'm using Gmail's API to read messages to an inbox.
I have a project in the cloud developer portfolio. I sign in with the account whose inbox I have to get data from.
I've made a service account without any roles etc and downloaded the required key.
I've built a resource using:
scopes = ["https://www.googleapis.com/auth/gmail.readonly"]
credentials = service_account.Credentials.from_service_account_files(path, scopes=scopes)
service = build(
"gmail",
"v1",
credentials=credentials
)
Which is fine. but when I try and pull information from the inbox:
responses = service.users().messages().list(userId="me").execute()
which gives me:
googleapiclient.errors.HttpError: <HttpError 400 when requesting <email> returned "Precondition check failed.">
I've tried changing "me" to the email, setting some roles. I can access this by using OAuth credentials but not with the service key. What could be causing my issue?
I will just try to expand on what #DalmTo said in the comments.
Service Accounts
Service accounts are special accounts that work without human interaction, they can use some google's API as you would in your normal account. There are some API (like Gmail) that cannot be accessible as a Service account because that would cause problems, like spam or problems.
But in a nutshell service accounts are fully independent accounts that can use the API without human interaction.
Domain Wide Delegation
There are some times that in a company (domain) with enterprise behavior there are some task that should be done to all the users, backup all drive files, check emails for spam malicious content or whatever you can imagine. For that the service account can have a special behavior to substitute an user. So the service account is delegated with the user access to the API inside the domain.
Answering your question
For your specific case:
You cannot use GMail API with a Service account
You cannot use Domain Wide Delegation if you don't have a domain to start with
Alternatives
So at this point your set up makes impossible the use of services accounts, so the only way is using your regular account with regular OAuth authentication.
I won't go into detail because this is not what you have asked for, but in case you are not familiar with it, there are ways to use the refresh token so you only have to authorize your app the first time and whenever the refresh token becomes invalid.
We are developing a hybrid mobile application and for certain function calls, there is a url called. Here is a sample request for getting user information
http://someurl.com/1234/account
where: 1234 - is the user id in the database.
We figured that a "man in the middle attack" is possible for this. The url called by the mobile app can be sniffed, then the hacker just changed the value for the user id and with that he can see information for other users. The question is - would simply changing the url called to https solve this security flaw?
No, it will not. You are exposing user data based on an unauthenticated URL and it is trivial for unauthorized parties to access modified URLs even away from the mobile platform.
Firebase provides database back-end so that developers can focus on the client side code.
So if someone takes my firebase uri (for example, https://firebaseinstance.firebaseio.com) then develop on it locally.
Then, would they be able to create another app off my Firebase instance, signup and authenticate themselves to read all data of my Firebase app?
#Frank van Puffelen,
You mentioned the phishing attack. There actually is a way to secure for that.
If you login to your googleAPIs API Manager console, you have an option to lock down which HTTP referrer your app will accept request from.
visit https://console.developers.google.com/apis
Go to your firebase project
Go to credentials
Under API keys, select the Browser key associated with your firebase project (should have the same key as the API key you use to initialize your firebase app.)
Under "Accept requests from these HTTP referrers (web sites), simply add the URL of your app.
This should only allow the whitelisted domain to use your app.
This is also described here in the firebase launch-checklist here: https://firebase.google.com/support/guides/launch-checklist
Perhaps the firebase documentation could make this more visible or automatically lock down the domain by default and require users to allow access?
The fact that someone knows your URL is not a security risk.
For example: I have no problem telling you that my bank hosts its web site at bankofamerica.com and it speaks the HTTP protocol there. Unless you also know the credentials I use to access that site, knowing the URL doesn't do you any good.
To secure your data, your database should be protected with:
validation rules that ensure all data adheres to a structure that you want
authorization rules to ensure that each bit of data can only be read and modified by the authorized users
This is all covered in the Firebase documentation on Security & Rules, which I highly recommend.
With these security rules in place, the only way somebody else's app can access the data in your database is if they copy the functionality of your application, have the users sign in to their app instead of yours and sign in/read from/write to your database; essentially a phishing attack. In that case there is no security problem in the database, although it's probably time to get some authorities involved.
Update May 2021: Thanks to the new feature called Firebase App Check, it is now actually possible to limit access to your Realtime Database to only those coming from iOS, Android and Web apps that are registered in your Firebase project.
You'll typically want to combine this with the user authentication based security described above, so that you have another shield against abusive users that do use your app.
By combining App Check with security rules you have both broad protection against abuse, and fine gained control over what data each user can access.
Regarding the Auth white-listing for mobile apps, where the domain name is not applicable, Firebase has
SHA1 fingerprint for Android apps and
App Store ID and Bundle ID and Team ID (if necessary) for your iOS apps
which you will have to configure in the Firebase console.
With this protection, since validation is not just if someone has a valid API key, Auth domain, etc, but also, is it coming from our authorized apps and domain name/HTTP referrer in case of Web.
That said, we don't have to worry if these API keys and other connection params are exposed to others.
For more info, https://firebase.google.com/support/guides/launch-checklist
I'm trying to figure out how a site that accepts OpenID logins couldn't be hacked by a simple hosts file update to point to a bogus OpenID provider.
Lets say for instance I want to hack into Joe Smith's account and for this example, lets pretend his OpenID provider is http://jsmith.myopenid.com. What would prevent me from creating an entry in my hosts file, pointing jsmith.myopenid.com to an IP that I control. I would then fake the authentication and return a response saying that the user successfully logged in.
I know there would be an SSL mismatch warning in the browser, but since it's my browser I could easily ignore it. How does the requesting website know that the response it receives is actually from the site that was requested?
This seems like a basic attack, and I'm sure the people behind have included a solution for this, I just must not be searching on the correct terms to find the answer.
The relying party contacts the OpenID provider directly, either before authentication (to establish a shared secret key used to put an HMAC on the OpenID provider's response) or after authentication (to ask it to confirm the response actually came from the OpenID provider).
For your attack to work, you would also need to be able to control DNS lookups of the relying party, not just your own.