I'm using a simple service called I'm PDF to create PDF versions on online invoices. Right now, the client has to login to see the online version, but as a result, the api service doesn't have access to it either. How would I detect that the pdf service is accessing the site and allow it accordingly without a password?
I thought $_Server['http_referrer'] would do it, but I didn't have any luck. I wasn't sure even what the variables would be, so I had a var_dump($_Server)it emailed to me, whenever the page was visited. It sent it beautifully when I went to the page, but when the pdf was generated, no luck.
Any ideas?
Thanks for your help!
You need to identify the user. The only way with this service seems to be to append something to the pdf URL (GET parameter).
So create some secret on the server side, sign user id with it, append it to impdf URL and parse it with your secret on request. You will end up with user id that you can use for authorization.
Have you tried looking at the IP address?
The service probably accesses the site from the same IP address (or range of addresses). If that's the case, then all you have to do is check the remote IP address of the request, which I believe is in $_SERVER['REMOTE_ADDR'] for PHP.
I should also mention that IP address ACLs are not quite perfect, though, because IP addresses can be spoofed. They probably should not be too heavily relied upon for security unless there is absolute control over (or guarantee of safety) of packets leaving and entering the network. That said, they are most likely sufficient for your "simple" security requirements.
The HTTP referer is pretty much trivial to circumvent. As such, it is not reliable enough for security and should be taken with a grain of salt.
I wouldn't go for any of the above mentioned advices. Basically they all bring down your security measures.
I'd use an API such as PDFmyURL's API, which allows you to login directly via a host of standard ways. This makes sure you don't have to build anything new.
Direct link to section on accessing secure area: PDFmyURL API documentation
Disclosure: I work for Kaiomi, which owns this service.
Related
I have built a simple read-only API for our database, so that users can retrieve data from our database.
For example, the URL "http://xxxxx/getAllProfiles" will return a JSON result containing all profiles stored in the database.
The API is read-only, it is only implemented with some 'select' SQL queries. Thus the user cannot modify any of the data in the database via the API.
My company worries the API will be exploited by some random bots online, and has been asking me to build a security mechanism for this API. (It is worried if there is no key or something that prevents anyone from accessing the URL, our server would be visited too much. It is a small server.)
What would be the simplest secure mechanism that I can implement, using PHP? (We are also using Slim for the API, Amazon EC2 server with Ubuntu and Apache running on it, if this helps.) Preferably it can be implemented without the use of any database on server or client side.
If there's anything not clear, please let me know, I'll clarify.
Thanks.
Add:
Thanks for the comments.
Is there a way to NOT use a database? Like a smart way to generate a key or something... I'm thinking I'll provide a page so that user can input the domain, and an algorithm will convert this domain to a key. Then, for each request, the user should include this key. The server will grab the domain from the request header and use the same algorithm to calculate again. If the two calculated key matches, the request is accepted. I think this, at a minimum level, ensures that at the beginning there must be someone to input the domain and get the key, thus filtering some random bots out?
I am not sure if this is secure (at all)? But it sounds to me like it can filter out something.
I posted this question when I know very little about web development.
There are many ways to secure a REST API, e.g. JWT, Cookie, Basic Auth, etc.
I am trying some stuff out with phonegap and I had a question concerning the security that I cant figure out.
So lets say I want to add something in a db. I let phonegap do an ajax post to a php file on a server with the vars and this php file will insert it in the db.
But anyone who would know where this php file is located and knows the data it wants can do an ajax post and insert data right?
I was reading about giving the php api a token. But I also was reading it is very easy to decompile a phonegap apk so it wouldnt be hard to get this token right?
So how can I make sure the php file on the server only accepts posts made from my phonegap app?
You can't. There is no way to guarantee they only come from your application. You can however ensure any calls come from a specific known user of your application.
You have an untrusted client with which it is impossible to embed a secret within without compromising the secret. You can make it harder, such as encrypting your JS and packaging it encrypted, then relying on Apple's DRM to secure your key, but for someone vaguely determined that will not stop them. Your AJAX end point exists and as the insecure client needs to communicate with it somehow there will always be a way to discover the client's secret.
However, typically this isn't an issue. What you can do, is exchange a secret with the client that is tied to a single user so that any calls to your API are on behalf of that user, and that user only (presuming that secret is kept secure - they don't lose their device etc). You can then use this secret to either encrypt or sign your outgoing AJAX call. This ensures someone can only affect their own account (e.g. only update their own account, only upload content tied to their account etc), and can't make arbitrary calls on behalf of other users.
This is enough for many types of application - though you haven't provided any detail about what your AJAX call does. No one is going to deliberately leak their own "personal" secret (though if theft is a concern, or you have higher security requirements then you could implement 2FA or more).
Personally, if this was anything non trivial, I wouldn't advise rolling your own system anyway. Security is difficult to get right, and there are many existing authentication systems out there (e.g. OAuth2) which have been tried and robustly tested in the wild.
Is there any way to validate that a request to my API is coming from a specific domain without the risk of someone tampering with it?
For instance, if I get a request to:
http://www.mydomain.com/api?request=something&key=12345
I can check to be sure that the API key 12345 has been assigned to a user before returning the results. However, I would like to confine that API key 12345 to a specific domain so that only a person from theirdomain.com would be able to send API requests using the key 12345.
I'm not asking how to program that part, I know that. I'm just asking if there's any way to do so (or any other ideas you may have) aside from using $_SERVER['HTTP_REFERER'] (something more secure)?
There is nothing built into HTTP that allows you to detect the "context" of a request, apart from voluntary (and therefore trivially spoofable) information from the client, such as the Referer header.
If this is a server-to-server API (rather than something which will be requested directly by a user's browser), you could check the source IP address, using $_SERVER['REMOTE_ADDR']. This is much trickier to fake, particularly if you're whitelisting rather than blacklisting IPs. (It's easy to find another IP, to avoid a blacklist, but near-impossible to choose your IP, to avoid a whitelist).
This is often used in e-commerce and e-payment APIs, where the owner of an account provides a list of IP addresses on setup, or in a customer control panel, to make it harder for third parties to use a stolen username and password.
I want to build an API for users to build applications that easily interact with a site, and I was wondering what the best way to authenticate users would be.
Taking a look at other API's a lot of them have the user send the username and password as a GET parameter over a HTTPS connection. Is this the best way to go about it? Or are there other methods that I should look into or consider?
I've seen OAuth been tossed around and it looks like a good solution, but just for a simple API is it overkill?
You can use API key's. Generate a unique hash tied to an account upon request. Then check that the key is a valid key. As long as the API doesn't have any major security issues with someone using someone else's key then Authorization isn't needed. If there is a problem with someone using someone else's key then Authentication would be justified.
This is usually achieved with cookies.
The client sends their username and password with a POST request to your API (do not use GET, that's insecure). If the credentials are acceptable, then generate a random, unique session key, store it on your side and send it in a cookie back to the client (see setcookie()).
When the client now makes further requests, they send the session key cookie with the request. Check $_COOKIE for the session key if it matches a stored key on your side; if yes, that means the user authenticated.
Take note that this minimal example is vulnerable to brute-force attacks trying to guess valid session keys. You need to log invalid keys that clients send in their cookies and block their IP address for some period of time to prevent this.
Username / password in a GET isn't a great way to do this because you're potentially exposing the whole user account for hijacking even if the API has more limited functionality than logging into the site. So it's good practice to separate concerns between Web-site login and API access.
I'm not sure which case you're in but:
If the users are business customers of somekind who are embedding some type of widget or code in another website then it's probably best to use an API key which is scoped to the referrer domain (much like Google Maps does).
If they are end-users who won't know anything about the API but are going to be using Apps built by third parties then oAuth is likely to be your best bet, otherwise your users might literally be giving their usernames/passwords to unknown third parties. It's more complex but likely to be worth it in the long run.
To get a bunch of this stuff out of the box you can use something like 3scale (http://www.3scale.net) and it'll handle most of it for you (disclaimer, I work there so adjust for bias!) or there are open source libraries for oAuth in most languages (in PHP Zend-OAuth component might do the job for you).
My requirement is i have a portion of the site that should allow user to access from only one system. He may used different IP's and different by if the system is same he should be able to get the access. My site is in PHP. Doing some R&D i found so JS which helps to get the MAC address if the visitor is using IE. My case is i cannot restrict user to use IE. He may use any browser. Is there any way to get the MAC address. If not possible how should i restrict the same user from accessing content from different computers.
No. MAC addresses are not useful beyond the local network, so they're not available in the upper layers (eg. Application layer). Using Javascript to get the the address isn't exactly foolproof either, since it's incredibly easy for someone to manipulate.
If you want to restrict the hosts that a user can access your site on, you'll need to use a method of storage persistence within the browser to store a key - something that uniquely identifies them. Some forums use this method to catch people attempting to bypass their bans.
You should generate some kind of random key (or encrypt a string), store it on the server-side along with the user you want to identify, then give the user the key to be stored in a cookie/localStorage.
Though, there is the obvious problem of a user clearing their cookies...
Hopefully that gives you a bit of head-start.
Daniel is correct, it's not practical to attempt to use MAC addresses.
For your purpose, you'll probably want to use a few layers. Cookies are a good place to start. As stated though, they can be cleared. The user also may have cookies turned off. Cookies are also stored in plain text on their computer, and they're really easy for the user to modify.
You could also implement sessions with PHP. Each session is unique for each system, and browser. If the user switches browsers or restarts their current browser, the session is re-created.
You could also check their user-agent string. It will be different for each browser, and "most likely" each system, but it can easily be spoofed.
You could also use a public/private key exchange, but that can be a pain to implement and manage.
There really is no one fool proof solution. The best bet is probably to use a combination of techniques to get it as "close to foolproof" as you can. Just try not to make it too inconvenient for the user.