javascript - Authenticating Parse.com User and Session Server-side -
i'm exploring parse platform building sample client-side apps parse javascript sdk. i've decided abstract majority of parse-related logic away app , restful api running on vps. purpose make app back-end agnostic possible.
the restful api i've built express.js app uses node.js parse package.
my question is: when want make request rest api, best way validate user making request?
example: consider app users can have friends:
- user logs in on client-side using parse.user.login() method.
- client hits endpoint /users/me/friends on rest api, checks if user has valid session , returns list of user's friends.
so require server-side parse code determine:
- who user making request is, and
- if current user has valid session
i've considered using following approach:
- when user logs in client-side, s/he receives session token.
- attach session token header when making api requests.
- on server, use session token in combination parse.user.become() method set current user , execute required logic:
- so express app handle above example:
router.get("/users/me/friends", function(req, res) { var sessiontoken = req.headers["sessiontoken"]; parse.user.become(sessiontoken).then(function(user) { /* valid user , session: find , return users friends */ }, function(error) { /* invalid: return error status , error */ }); });
is valid way handle situation? there problems should aware of if continue way? thanks!
i've been asking myself same question , solution i've come similar explaining. i'm developing android app uses parse it's user & session pieces only, else either mysql, redis or whichever other datasources plan wrap in future. i've gone ahead , developed own rest api on vps using php , slim framework. i've utilized authentication piece in parse adding apikey column in users table generate myself , utilize sessiontoken created , managed each user. when user makes authenticated calls web service, provide both api key , session token in every request header , when server receives request makes sure apikey + sessiontoken pair valid verifying through parse on it's end. sessiontoken recreated every time user logs in, keeps secure extent. i'm using both parse android sdk client-side , parse php sdk server-side. i've been able make create user, login user , list users endpoints regarding parse. mention of 'become' ability helped me issue had user sending session token server , trying validate since current user can view own session info. couldn't find mention of in php docs, apparently it's available , below. if have thoughts or input think make better, i'm open ideas.
dbhandlerparse class excerpt:
/** * validating user api key * if api key there in db, valid key * @param string $api_key user api key * @return boolean */ public function isvalidapikey($api_key) { $query = parseuser::query(); $query->equalto("apikey",$api_key); $results = $query->find(); if(count($results) > 0){ return true; } else{ return false; } } /** * validating user session token * if session token matches api key user, valid token * @param string $session_token user session token * @param string $api_key user api key * @return boolean */ public function isvalidsessiontoken($session_token, $api_key) { // using validated $api_key, obtain corresponding user object $query = parseuser::query(); $query->equalto("apikey",$api_key); $results = $query->find(); if(count($results) > 0){ $userobj = $results[0]; } else{ return false; } try{ // become user has session token // way query user // if no user found token, parse error $thisuser = parseuser::become($session_token); $query = parsesession::query(); $query->equalto("user", $userobj); $results = $query->find(); if(count($results) > 0){ return true; } else{ return false; } } catch (parse\parseexception $error){ return false; } }
authentication middleware:
/** * adding middle layer authenticate every request * checking if request has valid api key in 'authorization' & 'token' header */ function authenticate(\slim\route $route) { // getting request headers $headers = apache_request_headers(); $response = array(); $app = \slim\slim::getinstance(); // verifying authorization header if (isset($headers['authorization']) && isset($headers['token'])) { $db = new dbhandlerparse(); // api key $api_key = $headers['authorization']; // session token $session_token = $headers['token']; // validating api key if (!$db->isvalidapikey($api_key)) { // api key not present in users table $response["result"] = "error"; $response["message"] = "access denied. invalid api key"; echorespnse(401, $response); $app->stop(); } else if(!$db->isvalidsessiontoken($session_token, $api_key)) { // session token not match api key or invalid $response["result"] = "error"; $response["message"] = "access denied. invalid token"; echorespnse(401, $response); $app->stop(); } else { global $user_id; // user primary key id $userid = $db->getuserid($api_key); if (null != $userid) $user_id = $userid; } } else if(!isset($headers['authorization'])){ // api key missing in header $response["result"] = "error"; $response["message"] = "api key misssing"; echorespnse(400, $response); $app->stop(); } else { // token missing in header $response["result"] = "error"; $response["message"] = "token misssing"; echorespnse(400, $response); $app->stop(); } }
example route:
/** * users list * url - /list * method - */ $app->get('/users/list', 'authenticate', function() use ($app) { $response = array(); $db = new dbhandlerparse(); $results = $db->getuserlist(); $records = array(); //echo "successfully retrieved " . count($results) . " scores.<br><br>"; // returned parseobject values ($i = 0; $i < count($results); $i++) { $object = $results[$i]; $record = array(); $records[$i]['userid'] = $object->getobjectid(); $records[$i]['firstname'] = $object->get('firstname'); $records[$i]['lastname'] = $object->get('lastname'); $records[$i]['username'] = $object->get('username'); $records[$i]['email'] = $object->get('email'); //echo $object->getobjectid() . ' - ' . $object->get('username') . '<br>'; } // check records returned if ($records) { $response["result"] = "success"; $response['message'] = count($records)." users found."; $response['items'] = $records; } else { // no records found $response['result'] = 'success'; $response['message'] = 'no users found'; } echorespnse(200, $response); });
Comments
Post a Comment