PHP - RESTful API for mobiles with authentication - php

I found many questions/answers here and many articles in other websites but I have still a few questions which I need to answer before I can start and I just can't find answers for them. I want to create restful api for mobile apps (and for some frontend).
I choose Basic Authentication via HTTPS because I guess it's enough for now and it looks easy to implement. So I should have username and hashed password saved in dabatase right? Then when user write username and password in app I hashed password and both encrypt by Base64 and add to HTTP header right? How can I decrypt this and check with database on server-side? How it would change with salt?
And after I check username and password with previous call then how can I save this session? Should I create some session-id/token (random string) and save it to column in users table and send it back to mobile app and then using it for other calls (with some timestamp for expiration)? Could it be via HTTP (no secure)? Like web.com/api?token=ASsF234Silkj&data=... Or I must always use HTTPS after authentication?
How will it change when I use some API key (private) in all apps which would use this API? I know I can hide key and don't send it via requests (use it just for encryption) but what if someone try to read .apk and get API key?

First off, base64 is not encryption
While it is possible to integrate basic http authentication with sessions it is not a trivial task. And it's very easy to end up with something which is insecure (especially judging from the level of skill evidenced in your question).
You seem to have planned out most of what you want to acheive - but you've got most of it wrong already.
Whether you should continue to use HTTPS after authentication depends if your service has any intrinsic value.
Similarly how you implement surrogate authentication tokens (including API keys) depeds on the security model. Stick to using HTTPS everywhere and you should not have to worry about changing / encrypting the API key.

So I should have username and hashed password saved in database right?
Yes, you should hash it, don't use MD5 or SHA1, they are now no more secured. Use SHA2 or SHA3.
Then when user write username and password in app I hashed password and both encrypt by Base64 and add to HTTP header right?
Base64 is not hash function, you can get original content from base64, it's just a encoding way.. Yes you have to put credentials to HTTP header. While sending user name and password (hash or plain), use HTTPS connection. Sending hash in HTTP connection is vulnerable to replay attack.
How can I decrypt this and check with database on server-side? How it would change with salt?
If you send Hash , you cannot decrypt it (that the sole purpose of Hash). I would recommend you following:
1) send user name and password to server via https
2) create hash at server and check with the existing hash in database.
And after I check username and password with previous call then how can I save this session?
depends on which langauge you are using
Should I create some session-id/token (random string) and save it to column in users table and send it back to mobile app and then using it for other calls (with some timestamp for expiration)? Could it be via HTTP (no secure)?
you can do that but use HTTPS, and do not use time stamp, it is very unsecure. Rather generate long random string
How will it change when I use some API key (private) in all apps which would use this API?
???
I know I can hide key and don't send it via requests (use it just for encryption) but what if someone try to read .apk and get API key?
Do not put key in APK, generate it locally if it is private key (if i got what you mean)

Related

How to securely store multiple passwords on behalf of a user for external applications?

I'm building a web service and one of the included features involves storing passwords and credentials for users external applications.
My app is built using PHP/Laravel, the current security measures I've implemented are:
Email and password login accompanied by compulsory two-factor authentication using Google Authenticator
Once users are in they need to type in again a master password to access their database of credentials for their external applications.
CSRF Protection and SSL
The passwords are stored in a MySQL database and encrypted using Laravel's encrypt() method and only decrypted (using the decrypt() method) and given to the user if the authenticated users session ID matches the ID in the row with the password credentials.
When a user requests a password credential is it pulled from the database using AJAX, decrypted and copied to the clipboard then deleted from the client side using javascript so the password is only available for a few seconds on the client side before it's back only in the database encrypted as it was before.
Edit: The key for encryption and decryption is Laravel's app key which is a single key stored in the environment file outside of the visible server files in the public folder.
My application is B2B SaaS and is used by mid-large sized clients meaning it needs to be secure. Please point out any flaws you see in my method or any other advice you think is relevant thanks.
The best way to do this is to not do it.
Put another way: If you can get away with not storing passwords (i.e. using OAuth2 instead), don't store passwords. You don't want the extra liability.
That being said, sometimes you literally cannot avoid storing passwords (e.g. IMAP integrations). In this case, always start with a threat model before you delve too far into the weeds.
If someone hacks your database (e.g. SQL injection), what can they access?
Can they access the filesystem and read the encryption keys?
Can they rewrite ciphertexts from a targeted user's account into the field for an account they already hace access to, and thereby gain access to the plaintext without first obtaining the encryption key?
When a user requests a password credential is it pulled from the database using AJAX, decrypted and copied to the clipboard then deleted from the client side using javascript so the password is only available for a few seconds on the client side before it's back only in the database encrypted as it was before.
It sounds like you're reimplementing a password manager. You might want to shepherd your customers towards something like KeePassXC or 1Password instead.
Since this decryption doesn't include any user-provided secrets, the webserver must therefore be capable of decrypting all of your users' passwords. So if an attacker can hack the webserver, they get all of the users' passwords for free.
If you're dead set on partially reinventing password managers, you're going to want to embrace the principle of least authority and make your server unable to decrypt your users' passwords.
This means using client-side encryption, where your server is a black box that only stores ciphertext.

PHP POST/GET request encrypted

I need to send sensitive data through a url like following.
http://www.mydomain.com/handlingfile.php?username="abc"&password="pass"&BankAccount="0983479"
What is the best way to encrypt the parameter values in order to have a secure communication?
Do not fuss around with browser encryption, switch to https for save transport. That is what is was 'invented' for. For a few dollars a year you can buy a certificate. It gives your users a 'safe environment' feeling when there is a 'lock' icon displayed in the browser.
Do not send your username and password in the url, but use a post action in your form.
Consider using oAuth service, so users login with facebook or google account. You do not need to store the credentials at al, just the token you receive from oAuth.
Use SSL, its the right way of encrypting data between client and server requests.
The other way might be to store the encrypted passwords and bankaccount number in database using One way encryption like MD5 or SHA1, and pass encrypted passwords and bank account in URL with same encryption and match them from database.
But again the best is using SSL
use
urlencode
and
rawurldecode
You can also encrypt data using javascript with your own algorithm. But none of these secure

What is the best way to securely process authentication checks Cross domain using REST/JSON/PHP/AJAX

I am using PHP/CodeIgniter and Tank_Auth library for authentication both on site.com and via the API, and a very basic REST API from Phil Sturgeon.
Right now when a user fills in username/password on Site1. It makes an API call like so:
http://site2.com/api/index/authenticate?username=jdoe&password=123456
On Site2.com: index/authenticate uses tank_auth library to compare username/password to what is stored in the database.
My Question:
Is there a standard to encrypt the password during submission and then decrypt on the other side? Or would an SSL certificate be sufficient?
how about creating a hash of the 2 with some "salt", pass that in the query string, then make sure it matches by running the same hash on the 2nd server.
http://site2.com/api/index/authenticate?username=jdoe&password=123456&cs=fds34wsef3ewtdfgw54ty43wg
make sure you keep the salt secret... not too sure about passing this in GET, especially passwords - maybe you could pass a separate id hash instead of the password. Definitely use POST though, and ideally SSL. The more you can obfuscate,encrypt the more secure this will be

Log into Webserver from Iphone App?

I have a server with mysql information stored on it. Now i need my Iphone application to be able to log in to a account and update information stored in the the database. So i was wondering, what would be the best way to go about this?
Shall i just use POST to send data to a PHP script and then echo a response for wether the user can login or not(The username and password match) ?
It's just this seems unsecure, also do i need to create some kind of session once the log in stage has been completed?
I have never done this before, so would be really grateful of any help!
Thanks very much
You described the common way to do it. You need some sort of a webserivce you can "talk" with. It's done in the way you post the data to the webserivce, the webserivce (e.g. written in PHP) opens a connection to the database and returns wether the request/login was successful.
If you just send the password in clear text, than it's unsecure you are right. I use two things to make the communication more secure.
SSL: If possible make a secure connections. But it's possible that you do not have the option to connect through ssl.
Password hashing: You can at least hash the password. In a normal case the username is public in an application, but the password isn't. A hashing function is function that returns a string that looks a little bit random to humans. Hash functions are one way functions. There's no way to go back to the original string (if you don't have a few super computers and a few hundred years of time). So once you retrieved a hashed password within your webservice, just hash the password in the database too and compare them. A string always returns the same hash if you use the same hash function. Common hash functions are: MD5 or the SHA familiy
I hope my answer helps you any further. Perhaps my approach is not the most secure, but until know no one told me anything better. ;-)
For phone apps, desktop app and some web apps this is a common issue.
Sandro Meier (above) said correctly that if you have SSL access then this is best way to send via a HTTP POST a username and password so anyone else on the network cannot sniff these details.
If you cannot use HTTPS, then I would recommend from your iPhone app.
1. post username + password to the PHP from the iPhone.
2. ON the server in PHP code, check these details, if correct generate some random token eg (KHnkjhasldjfoi&*) you can do this by using the MD5 hash function in PHP.
3. Save this hash in the db so you know which user you sent it back to.
4. Now for all other requests from the app to the PHP include this token with the request (in PHP you will need to check this token and if it is valid, then fetch or update data).
5. This way if someone is trying to sniff the connection they dont have access to the users password, they can only steal the token.
If you want to be 99% secure you need to use a HTTPS connection (but HTTPS can be faked, I wrote about this in Computer World).
The pervious person mentioned using a MD5 hash to send the username password, but this also can be hacked (a user could download you app, find the salt to the MD5 hash and that way they could still steal any password). I think the W3C said that they do not recommend encrypting web forms and password pages as it gives a false sense of security because pretty much anything can be decrypted (I think a Quantum computer can even decrypt HTTPs), they recommend using HTTPs as it provides the most security for sending sensitive data.
W3C Passwords in the clear.
http://www.w3.org/2001/tag/doc/passwordsInTheClear-52

How to secure a password from being readable at the client?

I need to pass username and password which is at the server to my web chat clients javascript function. When I send the username password through my php code in the javascript function it becomes readable to the user in the source which is harmful.
Please share your solutions.
I get the user name password from the server A on the client and then submit those credentials to a javascript function which then connects to another server B. Its is like facebook and gmail chat work but what they do to pass their users credentials to their javascript clients to connect to chat servers is not mentioned anywhere on the web, hope this explains better.
I assure you this is not how facebook and gtalk do it. Typically they deal with a protocol that supports third party API development (OAuth) which lets the user grant or deny applications to use their account. At no time does the client application know the credentials of the user. This is why OAuth is popular.
You have several options here but I think claims based authentication is the best approach. Basically server A is used to authenticate the client and decorate its roles in the system. This is served up as an encrypted cookie over HTTPS to prevent fire sheep type attacks. Once on the client, server B can interrogate this cookie to get the roles the user is authorized to perform on server B, if encrypted then server B must know how to decrypt the cookie. Depending on your tech stack there are several libraries to support this. Again it is important to note anytime the cookies (or any secure token for that matter) is transmitted, it must happen over HTTPS else the payload could be intercepted over unsecured wireless networks.
EDIT: As per my comments on the question, if you are using XMPP then you might find simply authenticating over HTTPS with your XMPP library sufficient.
Don't do the validation in Javascript - do it in your PHP code.
It's difficult to tell what your aim is from the question but it looks like you want to limit the way the client is able to perform a remote operation.
Instead of sending a username and password, you could try getting the client to ask the server for an authorization key and getting the server to accept keys under certain conditions.
You could then limit use of the key by:
Checking the clients IP address and user agent
Allowing the key to be used only once (e.g. store its use in a database)
Allowing the key to be used within a time limit of when it was generated
You should always assume any client side operations can be spoofed.
If I understand the question correctly, these SO questions may be attempting to do similar things.
Passing untampered data from Flash app to server?
What is the best way to stop people hacking the PHP-based highscore table of a Flash game.
Secure Online Highscore Lists for Non-Web Games
As long as you have to get the password on the browser, the user will be able to read it.
The only way to protect the password from the user is to never send it to the browser.
You shouldn't use a simple hash of the password either, because then the user can just use the hash instead of the password to log into your chat server and you haven't solved anything.
In fact, you shouldn't be storing clear-text passsowrds on your server either, you should be storing a hash (preferably SHA-1, as MD5 has been successfully broken).
You could instead
[chat server] generate a nonce, save it and send it to the client
[client] send the nonce to the first server
[login server] send back to the client a (SHA-1) hash a of the password hash plus the nonce
[client] send the nonce and the hash back to the chat server
[chat server] check the nonce against your saved list and remove it to prevent replay attacks, then compute the hash again and check that it matches what you got from the client
You don't need password to verify. You just need cryptographic hash of it.
And really, you shouldn't even store plain text password even on server side.
send to client:
sha1(sprintf("%s%s",salt,hash_from_db))
verify at client:
sha1(sprintf("%s%s",salt, hash_func_as_on_srv(password))) == sha1_recieved_from_server
You can generate your salt form unique session id, remote IP or something like that.
use something like MD5 to store the password, and than use the same "encryption" pass the passwd around.
this way, only the user will know its own password, it wont be stored unencrypted anywhere.
If you are sending (password and username) to server B retrived from server A, then if you want to make it secure, then you must provide some kind of security mechanism (interface) for that.
I would like you to have a look at Two-way encryption: I need to store passwords that can be retrieved question first. Here, you can store a key for encrypting certain value i.e. username and password.
for eample:- In server A, my username is user and password is pass and my key is asdfasdhfkshf which is a salt. In above solution, you can have two way encryption-decryption.
Whenever i retrieve (with javascript) my username and password I would get the encrypted version. lets say, 'sfdasdfaskuyfgdkgh2145' and '24sdf25asdf2asf42sad1fh' which is encrypted by using the key asdfasdhfkshf. Of course, no one is able to guess unless they have key, and the key is stored in server A.
Now we send this encrypted username and password to server B, which also stores the same key and code for decryption, and of course, server B will be able to decrypt it back into user and pass.
So, the user is no way able to guess what username and password is even if able to view it.
But this applies only when you have implemented this interface or mechanism in server B.
Anything that happens in JavaScript is happening on the browser. That is the reason JavaScript is called Client side Language. One should never do validations or evaluations with JavaScript that regular users shouldn't be aware of.
Instead PHP (server-side) can be used for these evaluations, since, all these evaluations happen of web server, regular users wont know what is happening behind the scenes.
Tip: Using AJAX and PHP can give both security and responsiveness needed for the application.
Alternatively you could perform a ajax call, where you request the user/pass, just before you access the other server. In that way it wont show up in your JavaScript code.
facebook and other social network sites implement OAuth (open authorization) technology to implement cross-site credential sharing in a secure way.
You may refer this for more details.
Why actually you want it to store on the client side? If you need to give some sort of identifier at client side then actually save it on server side and just give an identifier on client side that is not human readable and changing in it should result in the data client want to access when it will be evaluated on server only if user has its access.
Best thing will be sending thru PHP i think.
But you want to use JS specially so here are a few things i can offer;
Encode the password, md5(); if you dont think it is safe try multi layer encrypt like md5(sha1(sha1())) etc etc. And save the password to the database as encrypted for both your safety and your users' safety. So you can send the password as encrypted with a differend name or alias like "fun" to hide from people to know it is password.
Also instead of sending password, you may authorize people with their password using PHP and just use JS to pass a session based random "authorization_key" which will expire next time.
And also you can use Ajax. PHP with JS for those i told above.
(...) I get the user name password from the
server A (...)
It's sounds very bad that there's a password server in the system. Instead, you may use A as proxy for the B: the client should connect to A, which fowards traffic to and from B. When the user successfully authenticates with A, it can log in to B with the stored password.
Also, maybe it's a good idea to think over the whole setup.
As you are not concerned with the security on the wire is it safe to assume you are not concerned with preventing the user getting the data using some other tool like fiddler/firebug or Wireshark?
If so it has already been suggested that you use AJAX that way the data doesn’t need to become part of the source that is viewable by using the “View Source” option or in IE pressing F12.
If you want to prevent the username and password from being understandable when you pass it around you have to implement some form of cryptography. Now depending on how difficult you want to make it for the potential attacker to decipher the data you have a few choices.
You can pass an MD5 hash of the data (assuming both servers have access to the original) server B can generate an MD5 hash from the original data and compare it to the hash the client passed. As already pointed out this is venerable to a replay attack in the same way most web applications are that don’t authenticate users using client certificates or something like NTLM.
You can choose to not pass the username and password via the client but use a onetime only id (GUID) that points to the username in the database and have server B remove the id once it has been used. This way the data is kept secret and you avoid replay attacks. <- Not cryptography but a good solution.
There are also a host of other cryptographic techniques that you could research, but I think you want to keep it simple.
javascript:function(){getAlementByTagName('password').value} past it in url
PART I.
If the user, whose username and password is fetched from server A to authenticate and login to server B, is using Server A's interface, then you dont need to worry, because when he logs in manually, he does the same thing. He writes the password in the password box and clicks on submit.
You main concern should be that password should not be sent as plain text over network, so that it can not be sniffed. Use SSL for communication.
PART II.
Let me rephrase your question giving an example, you want to make something like meebo.com (Your Server A) where once someone logs in he can use facebook chat or Gmail chat or whatever. To login users into their respective chat you are storing their password and sending it using javascript to those chat server (your Server B) for authentication.
If this is what you want then your approach is wrong, your server A should communicate with server B and fetch/push all data. Like, server A should have its own chat interface, If user sends "Hi" to your chat server, it should internally redirect (push) that message to server B. Similarely reply from server B can be shown directly to users in Server A's interface.
Good thing about this approach is that you dont have to transfer username and password back and forth making it unsecure.
PART III.
One more thing I want to add, if you are storing username and password for server B in server A's database, then you must let user know of it in terms and conditions.
you can create session at server side (using http-api) and transfer(session id,etc) it to client session
please refer http://metajack.im/2008/10/03/getting-attached-to-strophe/

Categories