I'm building a webapp that allows users to create, edit, and save documents. The database of user accounts is controlled separately and I've been provided a SOAP API that will tell me whether a given username/password is valid.
Assuming the username/password are valid, the API will give me back the following info:
• email address
• username
• login_number (unique id for the account, appears to be an auto-increment int)
I'll be storing data for my app in my own database so I'll probably be using the login_number to tie data to individual users.
My question is how I should keep track of a user once that user has successfully logged in. Storing the login_number as a cookie would work but seems like it'd be horribly insecure to me. I'm thinking something along the lines of a cookie storing some sort of random hash with a lookup table storing that hash and the associated login_number but I'm not really sure that's sufficient.
Tagged with PHP/MySQL as that's the back end I'm planning on working with, but not sure it really matters for this question.
This is very common case with any open authentication take Facebook oAuth 2.0 for example. Once user agrees on your terms, Facebook provides his userid, email and also a way to check, at any time when you want, whether the user is still logged-in or not.
So, there are a couple of ways:
Rely on the provider: If based on User-Id the SOAP API provides the information whether the user is logged in or not. You may just use this call before performing any task that require authentication.
Build your own Authentication on top of SOAP API: This is what you are planning to do, I guess. The approach is to use a encrypted/hashed and hard-to-recreate token. The idea goes like this(a)As soon as user logs in create a unique token, save this token in user's session or some permanent store. May be in memcache or somewhere mapped with the userId. Basically, wherever you may retrieve this token, you know which user is associated with it.(b) Store this token as cookie.(c) Whenever you want to authenticate, use the token from cookie to match against the token saved in the user's session (or pull out the userId matching the token and match the current userId with userId pulled using token for validation).(d) delete cookie on logout. Now, there are good chance of man-in-the middle attach with this approach. One approach, and it's expensive, is that to change token at the end of each request. This does not eliminate MITM attack, but chances of attack gets fairly slim.
Hope this helps.
Nonce The idea of nonce is simple and very solid. But I am unsure it will be applicable to your case. It's basically to protect SOAP calls. AWS uses similar thing.
Provide client with secretKey.
Whenever cient makes a request, he has to pass a hash of current time-stamp with secretKey (say it token) and the timestamp that it has used to create the token.
Server validates the token by comparing token with the hash that the server creates using timestamp passed in header and the secretKey stored else where on server-side, may be in database as password or secretKey.
If the tokens match, user is allowed access else not.
One more thing, the server may also disbar the access if timestamp is too off from server's current timestamp.
This approach is effectively free from MITM attack, but not sure if this is best suited approach for you.
The client server dialogue looks like this
client ----request timestamp --------> server
<---current timestamp -----------'
--- {ts: timestamp, token: Hash256(timestamp, secretKey)} --> isEqual(token, hash256(ts, secretKey))
| |
Access Denied<- false/ true --> ACCESS
#kramthegram thanks for reminding Nonce
You could try hashing the user number with a session based nonce. Set that cookie to expire on a login timeout length(say 30 minutes). The random per session nonce will help prevent playback attacks where a malicious user could copy your cookie to gain access since each session has a time sensitive hash.
Related
I have simple problem, I have js application (frontend) that uses my PHP REST api. I need to implement simple token based authentication and I'm not sure how that should work since i dont use sessions in REST. From my understaning it goes something like this:
User tries to login, if valid credentials, I generate token and return user object with token
I update user token in database
Client holds user object in cookies or local storage instead of session and with every request he passes token in header
I check if there's token in DB, if there is (I know which user is sending request)I proceed with request, otherwise I send him to login page
If token expires or user signs out, i update token field in DB with NULL or empty string (not sure if this is needed).
I just need confirmation if this is ok approach or i misunderstood something in protocol.
Thank you all in advance
Thank you
I don't think this approach is stateless. The existence of the token represents the logged in state. Which means that a part of the client state is maintained by the server. In other words the token count on the server increases by the client sessions.
each request from client to server must contain all of the information
necessary to understand the request, and cannot take advantage of any
stored context on the server. Session state is therefore kept entirely
on the client.
- Fielding - REST - stateless
I would rather do something like this:
Send the username and password at first auth and return a token with meta-data signed by the server.
Send the token by every other request, so the server will be able to verify the signature and use the meta-data, which can contain for example user id, expiration date, etc...
Update the token before it expires.
Update the private key of the signing mechanism regularly.
Cache the authentication and authorization data with an in-memory cache. I think db is too slow for that. Be aware that the whole process MUST work without cache. So if you clear the cache and send another request, and it does not work because the cache is lost, then it violates stateless constraint.
This way you will avoid storing the token (and so the client state) on the server. Not a perfect solution (e.g. the token can be used by others before it expires) but it is stateless. I am not sure whether you really need REST or token based auth. (Be aware that these applies on human to machine communication. Machine to machine communication is usually authorized differently.)
By stateless. it means that the in REST server does not store any state about the client in session or any other form.
I have personally used something like this for an app and this is the simplest form of security you can have.
When our system used to issue access token it create an expiry date/time also along with it. everytime you make a call with a specific access-token its expiry date/time updated +n hrs
I've been researching the best (and safest) ways to implement persistent logins on my website, and I've come up with the following:
When a user logs in, a cookie is created containing the user's ID/username, and a randomly generated number (token). The token is stored in a relational table along with the user ID/username. Every time a members-only page is loaded, this cookie is checked against the relational table, and if it exists and matches with the token, the login is valid and the page can load. If not, however, then the login is invalid, the cookie is destroyed, and the user is prompted to log in.
I was thinking... to save on database access every single time a page is loaded, I could also have a session variable that lasts, say, 10 minutes, and is destroyed automatically when the browser closes. If the session is alive, then it's refreshed and the user can proceed. If the session expires, but the cookie is still valid, check the cookie, reset the token, store that new token in the database (while eliminating the old token, or storing it in an archives table for future reference), and reset the cookie using the new token value.
However, what would the session contain? And how could the session not simply be faked with some JavaScript? Perhaps the session contains a one-way encrypted hash? What would be used to generate that hash (user ID, etc.)?
I'm kind of stuck on where to go from here. I get the cookie stuff, but using temporary sessions (to avoid repeated calls to the database every single time a page is loaded) eludes me. Any help? Thanks.
Cookies should be fine (an alternative would be to store it in the HTTP header), however I don't see the need to store the username/ID in the cookie. The token itself should be enough. You can use a UUID as a token. Store that along with the username and a last_access_timestamp in the database table. And only send the token (in a cookie or in the HTTP request header) on every request. That's enough for implementing sessions in my opinion.
A token is generated on a successful login of a user, stored in the database and passed to the user. Whenever a user accesses the webpage, the token is passen in the request and is validated. If valid the last_acces_timestamp is refreshed and the user can proceed. The lookup in the validation will be done by token and with the username you can do the authentication and authorizaton. If token is invalid or expired, forward the user to a login page.
Deleting expired sessions out of the db can be done periodically using a cron job or on creation of a new session.
For performance reason you might think about storing the session in a hashmap in memory. Since it might be costly to always update the database.
Also think about using HTTPS, to prevent people sniffing the token.
I have solved this the following way, few months ago:
https://stackoverflow.com/questions/12829994/java-custom-session-implementation-expired-sessions
Usage of UUID is not recommended according to RFC 4122 it is stated that
Do not assume that UUIDs are hard to guess; they should not be used as
security capabilities.
I would recommend combining and multiply all of the following information together into a hash with also encrypting it using a public key stored in your server.
UserId (Or User UUID that was generated for each user while registration)
Encrypted His/her password (considered as a private key for encryption per each user)
Time stamp
Client Operating System
Client User Agent (Browser name)
For storing tokens, you could use either memcache which is used heavily in big companies or redis if you are focusing on persistence.
Keep sure that your cookies have the following attributes, for more info about Cookies
HTTP Only cookie
Secure Cookie
I'm developing a web application using Codeigniter. When a user authenticates with my site I'm currently storing their 'user-identifier' in my session cookie (which I have enabled encryption on). Several of my model classes use the value in 'user-identifier' parameter of the session/cookie to make changes to properties of user accounts.
My concern is that I'm wondering if it's possible for someone to take a valid codeigniter-session cookie with a user-identifier that I've set, change the user-identifier's value to the value of a different user, and make changes to another user's account. Would codeigniter/php sessions create an error if someone attempted to change a property of a session cookie?
Open your /application/config/config.php, locate "sess_use_database" and change it to "TRUE" if you haven't already. This way all session variables will be stored in a database table and session cookie will only contain session id string.
For added security, you can also change "sess_match_ip" to TRUE. This way if someone steals your user's cookie and tries to pass it as their own, session will be destroyed.
"if
it's possible to take a
valid codeigniter-session cookie
change the user-identifier's value to
the value of a different user, and
make changes to another user's
account."
My answer is not really CI related, so please bear that in mind.
When you auth the user "username1" what should be sent back to the client, for auth purposes, should be a hash that the server correlates to that user. All communication between the client and the server will rely on that hash.
The server will generate a unique hash per user and the hash should have a short time to live. Can someone capture a hash and pass as that user? Certainly. That's why you should also check for the user's Agent and IP to check if they match the hash in order to prevent session hijacking.
NEVER DO THIS:
If seen some new developers storing the username in a cookie and reliing on that client sent variable to update their databases. Never do this. Do not ever, ever trust the client. When the server gets the client's hash it should check if it belongs to an authenticated user and grab the user_id (variable to update the user data) from the server. NEVER from the client.
I'm not sure what your "user identifier" is exactly. The general rule is, don't store anything in the session cookie but the session ID. Store everything else (like a user ID) internally on server side, and retrieve it using the session ID.
If the user changes the session ID (which is a random string), a new session will start. The idea behind the session ID is that it's impossible to guess other user's IDs - that's why it's random, and so long.
I am making a registration/login system with php. I think I have all the initial login stuff worked out(hashing password with salt, store in db...).
My question is in regard to keeping a user logged in between pages after their initial login. The way I understand it is that one method is to have a table of sessions on your server that stores a random unique id for each user and to store that id in a cookie on the user's computer. This way for each page they load all you do is lookup their session id in your database.
What I don't understand is how is that is secure? Couldn't somebody just sniff the ID and then fake being that user. Someone could even just try guess IDs.
I also read that it is better if the ID changes on each page visit. How does this increase security? It seems it just would decrease the amount of time any ID could be used.
Also how would any of this change with a "Remember Me" feature that would be stored for long time?
The ID you are describing is precisely what the session ID is, except it's handled for you transparently by php (browsers pass along this session ID with the cookie).
The security flaw you are describing is precisely what firesheep takes advantage of. You can prevent the session ID from being sniffed by making sure that all authenticated requests to your site take place over ssl. This not only includes logging in, it also includes any time an authenticated user tries to access a page (which means the browser will be passing along an authenticated session id).
If a user tries to access a page not via SSL, you should ideally redirect them to an SSL page and give them a new session ID, because the old one could have been compromised.
The key to such a system is that you don't randomly generate the key--you generate it using facts about the user, ones that another client wouldn't have knowledge of--like the user's IP address, user-agent, and session id. Then you make the user authenticate using that key and their session id (which is transparently handled by PHP).
So I'm trying to write a php SOAP client that requires the user to pass their login credentials for the remote SOAP server. Here is the set-up/dilemma:
User logs into local site using local credentials and goes to page with SOAP client.
User is now prompted for credentials for remote Soap server, which, by the way, are the same as the ones used to get into local site (9 times out of 10) via POST form.
Client passes credentials in the SOAP header along with the SOAP request, client outputs SOAP server response.
Script ends, user sees output data.
Now the user wants some other bit of data related to the original output. Problem is, that $_POST variable is now long gone. User must include credentials along with the next request. Repeat until user decides that it's easier to look up the data via another method and gives up on cool SOAP client.
The server hosting the Web Service can be accessed directly via a web client, and authentication is maintained via a cookie. However, when the server is queried via the WDSL, it doesn't look for any cookies or other browser-side session; it just checks that the SOAP request contains the credentials in the header.
So there are two versions of this question:
1) Is there a way for the local-session credentials to get passed to the SOAP request, thus keeping the logins down to one? (Be aware, I have no control over the authentication method even on the local side. This is handled by a home-grown Apache mod that controls authentication for any and every user throughout the system, covering dozens of departments I have no jurisdiction over. I have looked through the Global Variables and see no hint of the credentials, but I could just be daft about some basic security features of PHP/Apache).
2) Is there a safe and secure way for PHP to handle the credentials after the secondary login so that these credentials can be used for some set amount of time (say, a 30 minute session?). Keep in mind that, based on the first point, these credentials are very confidential, therefor there should be no simple way for someone to poke around and get these credentials to echo out (or get into some DB to see them, etc.)
Sorry if this sounds paranoid. I'm not used to handling security credentials beyond a simple "This is where you put in your password...Good, now that everybody knows each other for the rest of the session, I can get back to outputting useful stuff."
Even a link to any basic security features would be a helpful start.
Create your own expiration session. Create a database table which is:
CREATE TABLE session (
ID int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
Hash binary(16) NOT NULL,
User int unsigned NOT NULL,
Created timestamp
);
When the user authenticates the first time, create the session and return the hex form of the Hash.
Subsequent calls do not require the user name and password, just the hash. After, say, 5 minutes of inactivity, the Hash is deleted. User name and password are passed just once, the hash is used as authentication thereafter, and expires after a period of non-use.
Why don't you set a cookie yourself that has the username/password in it after the first soap request? You ask just one time then store in a cookie. You can then set a time out and query it while the user is logged in. You will probably want to delete the cookie on logout.
The cookie would contain the soap user/pass only. This way you would not have to worry about someone poking on the server and finding others credentials. This effectively does the same thing as having the user entering it every time since it is sent in clear text anyway. You could obfuscate the username and password in the cookie with a reversible hash or simple 2 way encryption.