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
Related
I have an Android app that interacts with my server written in PHP. I have done several requests that will be called via POST from the android app and will be answerd in JSON format.
I have a login request, the android application will send the credential (password and username) to the server. If login in sucessful the session_ID will be send as an answer. For every other request that needs user authentification the session_ID will be required. If that session_ID is not set, I will asume that the user is not logged. Otherwise, if the session_ID exists I will answer the request with the requested data
I'm going to check the authentification with the following code.
if(!isset($_POST['session_ID']))
{
$json[] = array(
'return' => $errors_authentification,
'error_msg' => "User not authenticated"
);
echo json_encode($json);
return;
}
session_id($_POST['session_ID']);
session_start();
Do you think this a good approach? I've seen post talking about tokens instead of session_ID to deal with android - php interactions that need authentification, which is the difference?
#chsharper, #pasi
I don't think JWT on its own is secure enough. Yes, it is signed by the server and is guaranteed to be tamper free. However, if someone knows the JWT (if saved in a Local storage), the same JWT can be used multiple times within the Ttl period (a hacker might use the JWT and use to impersonate within the Ttl period). If we save the JWT in a cookie and send it back to server with every request using HTTPS , I know the scenario is a bit tight, but is it completely non repeatable? I would recommend using one time token with a JWT, so it prevents repetitive requests.
Do you think this is a good approach? Any ideas on this will be greatly appreciated.
Thank you,
There's numerous approaches to solving user authentication after login, which of newest and hottest is JWT, JSON Web Tokens, which is a simple approach of storing session in the client side in a such manner that its secure to use from server end.
JWT ensures that user can't tamper the data it sends to the server, as they originate from the server(such as user id) and are signed by the server.
This way you don't have to perform any database queries or so in the server end to fetch the account id or related data, you just check whether or not the data sent by client is signed by you, after that you're good and can save some server CPU cycles.. However there's a small overhead included, sending the JWT requires some data exchange, but you can keep it as tiny as you need.
I for one like to 'cache' some data in the client side, as the token can also be used in client to use these ids.
To answer your question, your approach is simple, and requires little to no effort, also its as secure as cookies, as long as one can't grab the id in a MITM scenario, you're good.
I have ServiceSite.com (SS) and multiple GameSite.com's. All games authenticate through SS and then log in with their own personal databases. That's all done with a simple JSON API, no need to log into SS to get into a game.
I have the one goal of logging into a game and accessing the features of SS through the game, such as accessing a player's Contact List and Profile, both of which are shared between all games. While in GameSite.com/play, they'll hit a link to ServiceSite.com/contacts and get the response as if they were opening it from ServiceSite.com. I use JSON Web Tokens to manually log the user into SS, to simulate a real login to ServiceSite.com.
This works... so long as they're on the same domain. Meaning, as I'm developing a game, I'll use ServiceSite.com/tempgameurl and any call to ServiceSite.com has no problem establishing and keeping a session. But once the game gets its own domain, or if I'm working on my localhost, I cannot get it to recognize the session on subsequent requests. If I want a response, I will always have to pass the JWT token, which is not suitable for what I'm doing. The goal is to load a game, "poke" SS to create a log in, and then if a player were to visit ServiceSite.com, they would have the session as if they'd logged into ServiceSite.com's front page with their login manually.
In short, I expect that once I hit my first JWT request and make a session on ServiceSite.com from a GameSite.com, that's it, the session is made. But it seems to only actually make a session if I'm requesting from the same domain. I do see it create a session properly, filling in $_SESSION, but that data simply does not persist if the request originates from a non-ServiceSite.com URL.
Sessions and Cookies are domain dependent, it is a browser security issue. You cannot cheat this. However, there is a "trick" you can try, even though it is a bit more complex:
You need to set a cookie for each domain:
authenticate the user, emit a JWT code and create a key=>value type of record in a shared storage (database most likely). The key should be unique, the value should be JWT code and also set an expire time of 20-30 seconds.
in the response HTML you need to make the browser set cookies for the other domains. That can only be done on those domains. So you need to fool it with something like:
<img src="http://anotherDomain/setCookie.php?key=keyFromSharedStorage" style="display:none;" />
in the setCookie.php, check the shared storage and retrieve the JWT based on the $_GET['key']. Then set a cookie with that JWT.
You could pass the JWT directly, but passing a key that expires fast should be more secure. Add an image for every domain.
Instead of a cookie you can create a session on each domain. Same principle really.
Well try saving your needed data and sessions in database itself. It seems to be small amounts of data and logs.
After a game save the sessions on the database and open from whichever place you are at.
I'm new to Android/Java programming and I came across an issue where I have to use PHP session to keep the user logged in (persistant login), this has a set of methods form using httpclient cookie or using SharedPreferences and it made think of this solution instead of using session,
1- Login the user with backend with HTTPs, this will happen only the first time the user login, the app I'm working on requires one time login and no logout mechanism. the user name and password will be sent by SMS after installing the app.
2- If user exist save the save the user/pass(could be token here) in SharedPreferences
3- Whenever the user needs something from the backend send the user/pass over HTTPs and the backend will reply if the user/pass(could be token here) is correct.
My question is, do you think the overhead of checking the user/pass or token with every request is a bad idea?
The reason I'm asking this is that PHP session ID use the same method by checking the file that has the session variables which looks like the same overhead caused by checking the user/pass or token against DB.
I don't think there's much diference, what I actually do is create a token which contains the user identifier encripted with a salt, that way you can just verify credentials at the login and then use that token during the session, you can then easily retrieve the user on the PHP and do whatever needs to be done. I woulnd't recommend passing the user/pass every time, more query complexity and risk of credentials steal. About the session... I've never messed with it for a REST based service called by a mobile device client just because I don't see the need, guess it depends on what does the service do.
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.
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.