Am writing an api for IOS application
I have some concerns about handling session for the IOS application
When a user login from iphone, I need to pass the session id as login response and use that session id
in further api calls for validating the user,
What I have done in my api controller is get the session id and save it to session array along with user details and pass the session id as response
$session = $this->session->userdata('session_id');
$user_array = array(
'email' => $user->email,
'session_id'=>$session
);
$this->session->set_userdata('logged_in', $user_array);
$output = array(
'code'=>200,
'user'=>$user,
'session_id'=>$session
);
$this->output
->set_content_type('application/json')
->set_output(json_encode($output));
For the further api calls, I will get the session_id as a parameter,
I checked its a valid section or not using the following. code
$session_id = $this->input->get('session_id', TRUE);
if($session_id){
if($this->session->userdata('logged_in')){
$user = $this->session->userdata('logged_in');
if($user['session_id'] == $session_id){
// valid session
}
This worked well when tested with postman.
But am not sure , this is the correct way to handle session with API calls.
Will the same work when run from the IOS application?
thanks in advance
You are using a REST api method which is stateless, So session will not get maintained while calling from IOS application. Every call you make from the app will have a new session.
You have to use SOAP as a web service if you really need session to be maintained while API call.
For more information please check on If REST applications are supposed to be stateless, how do you manage sessions?
Related
I am currently redoing a legacy web application that uses the PHP Parse SDK, and I am in the login authentication part. In the old application, we used $ _SESSION and ParseToken when doing ParseUser::signIn() and ParseUser::currentUser() to check if you have a session with a valid token, however the new application is being made using the REST architecture, where one of the REST concepts is that the server must not keep state, that is, be stateless, and in that case it would be the client that would have to send the necessary data.
When searching the internet and forums, I saw that it is common for developers to authenticate with JWT, where the client would make a request for a server's route and the server would return a token, and through that token authentication would take place.
I even implemented something using Firebase / jwt-php, where the client [Postman] makes a request for the route /login sending via body [username, password] and in case of success, returns the token to be used in secure route requests.
NOTE: Code is as simple as possible, without validation and cleaning just to show the example.
Action /login
$username = $request->getParsedBody()['username'];
$password = $request->getParsedBody()['password'];
$userAuthenticated = ParseUser::logIn($username, $password);
$payload = [
'data' => $userAuthenticated,
'exp' => time() + 3600
];
$token = JWT::encode($payload, $_ENV['JWT_SECRET_KEY']);
echo json_encode(['token' => $token]);
And the protected routes have a middleware that checks if the time has expired, and if this has happened, an exception with a 401 code is launched.
So far so good, authentication works, the problem I don't know if it's right to do it this way, since I need to give a ParseUser::logIn(), just to generate a session in the database and I don't even use it this session to do some authentication, with the exception of operations in the bank, because from what I saw in the documentation, if there is no valid session in the database, the application will return invalid session token error and also when making the request for another route ParseUser::currentUser() returns null, and this may be a problem in the future.
Does anyone have any idea how I can implement authentication for a REST application made in PHP? I appreciate the help !!
I believe the easiest way would be just replacing the default session storage (which uses $_SESSION) to something else that stores the session in, for example, Redis. Reference: https://docs.parseplatform.org/php/guide/#session-storage-interface
But the way you are doing should also work. You will only have to make sure that, every time that a request comes, you will decode the JWT, get the Parse Session token from there, and use ParseUser::become to set the current user: https://docs.parseplatform.org/php/guide/#setting-the-current-user
I requested authorization for a public application to be able to access store data via the Shopify API.
The store successfully authorized my application via an authorization request URL such as
https://some-store.myshopify.com/admin/oauth/authorize?client_id=123abc&scope=read_inventory%2Cread_products&redirect_uri=http%3A%2F%mysite.com%2Fauth.php&state=123456
and the response was passed back to my application. This response (containing the code that can be exchanged for a permanent access token) was mishandled by my application (an error on the page meant that the access token was not stored).
Everything I read regarding requesting these tokens involves authorization by the store - but given the store has already authorized my application, passed back the code and that code has already successfully been exchanged for a token: is there a way my application can request that same token or a fresh one using my API keys given that the application is already authorized?
The only method I currently can find for requesting a token requires starting back at the beginning and fetching a code for exchange etc.
I working in PHP and using Luke Towers' php shopify wrapper
This stage was completed successfully:
function check_authorization_attempt()
{
$data = $_GET;
$api = new Shopify($data['shop'], [
'api_key' => '123',
'secret' => '456',
]);
$storedAttempt = null;
$attempts = json_decode(file_get_contents('authattempts.json'));
foreach ($attempts as $attempt) {
if ($attempt->shop === $data['shop']) {
$storedAttempt = $attempt;
break;
}
}
return $api->authorizeApplication($storedAttempt->nonce, $data);
}
$response = check_authorization_attempt();
and I would have been able to read the access token from :
$access_token = $response->access_token;
But this was the stage at which my application hit an error in accessing a database in which to write said token.
I cannot repeat it without repeating the auth request because the data in $_GET that's passed to this function comes from Shopify's response to the shop owner authorizing the access, and includes amoung other things the code for exchange.
You have to re-ask for authorization. It is no one's fault but yours that your persistence layer code was incorrect. So there is nothing you can do to change that. Ensure your code works. Since the client has no token in your App persistence layer, your App will retry the authorization token exchange. They do not have to delete your App first. So basically, the next time your client tries to use the App, YES they will asked to approve it, but who cares, they will, and you'll get a good auth token to store. You have fixed your code (right), so that will work. You are one step closer to glory.
Shopify does return the Permanent Access Token, but the ACCESS_MODE must be "Offline" for the token to be permanent.
With ACCESS_MODE offline, your app receives the permanent access token
to make requests whenever you want, without the user's permission.
Documentation:
https://shopify.dev/tutorials/authenticate-with-oauth#step-2-ask-for-permission
https://shopify.dev/concepts/about-apis/authentication#api-access-modes
I am using the Lusitanian PHP Oauth library (https://github.com/Lusitanian/PHPoAuthLib).
After the user gets authorized in my application, i have received values of Access Token and Access Token Secret. Now with these values, i would like to make authenticated calls to API. How can i make the calls with the values of Access Token, Access Token Secret, along with the values of Consumer Key and Consumer Secret? I don't want to get the user authorized every time, to make API calls for him. Does anyone have an idea ?
My request goes like this:
$result = json_decode( $service->request( '/users/getDetails' ), true
);
I have tried the REST Client of Firefox and Advanced REST Client of Chrome, that perform OAuth calls successfully, with just the values of Access Token, Access Token Secret, Consumer Key and Consumer Secret.
Similarly, i would like to perform the OAuth calls from my PHP code. The library which i am using, depends on Session to store these values (which requires the user to login each time) and build the Authorization header and signature. Is there a way i can build the Signature and Authorization header from my end manually and make the OAuth calls ?
Finally, i have tweaked the functionality of reusing the access tokens.
I am fetching token from a config php file, after i store the token in it.
The token can also be stored in a local PHP session and read from it.
The code for storing token is in Service/AbstractService.php:
$this->storage->storeAccessToken($this->service(), $token);
You can modify it like the following, to store the token in a session variable:
if(!isset($_SESSION['access_token'])) {
$token = new StdOAuth1Token();
$token->setRequestToken($access_token);
$token->setRequestTokenSecret($access_token_secret);
$token->setAccessToken($access_token);
$token->setAccessTokenSecret($access_token_secret);
$token->setEndOfLife(StdOAuth1Token::EOL_NEVER_EXPIRES);
$_SESSION['access_token'] = serialize($token);
}
Then when making a request to API, you can modify the code in request() function to use token from your session:
Change:
$token = $this->storage->retrieveAccessToken($this->service());
To:
$token = unserialize($_SESSION['access_token']);
This way, i could use custom PHP sessions to store and retrieve access tokens. You can also use Database or a text file to store and retrieve the tokens. It works! Hope it would be useful for someone.
I'm working on building a small web app connecting into the instagram API. Currently using this library on GitHub which makes things a bit easier. I can connect and initially login fine, and the page will display all user data.
But once you refresh the page all the data is lost, and it appears the script can't find my access token anymore. I tried storing this into a PHP session variable - but maybe I'm doing the whole process incorrectly? I just want to keep the same user session throughout an entire website once the OAuth is performed.
You can check out the small app live here: http://spyrestudios.com/demos/instagram-api/index.php
Additionally my callback URL is http://spyrestudios.com/demos/instagram-api/instagammy.php - this is the script which will work right after you connect. But try refreshing the page and all the data is gone! Also here is my bit of code which *should use the library to store the current user's access token:
session_start();
require_once 'Instagram.php'; // the library code
$config = array(
'client_id' => 'f0d225aa955c4bd9ae563f87f831efab', // Your client id
'client_secret' => '377b77afc1274a89bd2df7d77e934689', // Your client secret
'grant_type' => 'authorization_code',
'redirect_uri' => 'http://spyrestudios.com/demos/instagram-api/instagammy.php', // The redirect URI you provided when signed up for the service
);
// Instantiate the API handler object
$instagram = new Instagram($config);
$accessToken = $instagram->getAccessToken();
$_SESSION['InstagramAccessToken'] = $accessToken;
Really struggling for a solution, so I'd appreciate any help I can get. Willing to post examples of my code if needed..
Thanks in advance!
What you have already looks fine (although I have no experience in Instagram), assuming that $accessToken is actually being stored correctly in the session.
But surely at some point you need to feed back in $accessToken so that it can be verified. Like I said, I've not used Instagram before, so I don't know how you would do this.
Just in case you still care..
The problem is that refreshing is hitting the oauth landing page again when you refresh or back, but there is no authorization for it to collect the information from. In theory you could just wrap your setting of the session variable around a check:
$instagram = new Instagram($config);
$accessToken = $instagram->getAccessToken();
if ($accessToken != '')
$_SESSION['InstagramAccessToken'] = $accessToken;
That would stop an unwanted to call to your oauth landing page from clearing the current session value.
But better still would be to have the landing page redirect to a different page for the display. ie have your instagammy.php end there and add a
header("Location: http://spyrestudios.com/demos/instagram-api/dosomethinghere.php");
die();
That way the user won't ever see the "instagammy.php" page in their history and won't be able to go back to it.
This work for me, instead the original file instagammy.php
$instagram = new Instagram($config);
if ($_SESSION['InstagramAccessToken'] == ''){
$accessToken = $instagram->getAccessToken();
$_SESSION['InstagramAccessToken'] = $accessToken;
}else{
$accessToken = $_SESSION['InstagramAccessToken'];
$instagram->setAccessToken($_SESSION['InstagramAccessToken']);
}
I'm using https://github.com/abraham/twitteroauth library. I already created my app on Twitter, the callbacks are working fine (even on localhost), but one thing that is bugging me is HOW the auto-login happens? I know there's "user_id" that is stored in the MYSQL database, along with oauth_token and oauth_token_secret, but how do I obtain user_id as soon as the user enters the site, so I can query the database to see if it already exists and what not, without having to popup the authorize twitter popup then reaching the callback, over and over again?
I've seen a lot of questions like this one, but no one ever answered it in a satisfying way.
The ones that should be saved to be used in verifying the user automatically are the oauth_access_token and oauth_access_secrete . Have you managed to get them from twitter?
The Oauth steos are:
Acquiring a request token
Sending the user to authorization
Exchanging a request token for an access token
Using out-of-band/PIN code mode for desktop & mobile applications
please refer to :
http://dev.twitter.com/pages/auth
actually, it needs to be a mix of PHP own $_SESSION with OAuth callbacks. After the callback, set the current user ID you inserted on the database or query for "user_id" from Twitter OAuth response (that you should ALSO store on the database, along with the username), then use that for future reference, and using $_SESSION containing the registered user data on your own database.
So, for a quick example
function action_login()
{
if ( ! $this->user->is_logged())
{
// Create TwitterOAuth object with our Twitter provided keys
$tOAuth = new TwitterOAuth($this->config->get('consumer_key'), $this->config->get('consumer_secret'));
// Generate request tokens
$requestToken = $tOAuth->getRequestToken(url::site('auth/twitter','http'));
$_SESSION["oauth_token"] = $requestToken["oauth_token"];
$_SESSION["oauth_token_secret"] = $requestToken["oauth_token_secret"];
// Display Twitter log in button with encoded link
$this->view->set('url', $tOAuth->getAuthorizeURL($requestToken["oauth_token"]));
$_SESSION['current_url'] = Request::detect_uri();
}
echo $this->view->render();
}
public function action_twitter()
{
if ( empty($_GET["denied"]) && isset($_GET["oauth_token"]))
{
if ($_GET["oauth_token"] == #$_SESSION["oauth_token"])
{
// Use generated request tokens (from session) to construct object
$tOAuth = new TwitterOAuth($this->config->get('consumer_key'), $this->config->get('consumer_secret'), $_SESSION["oauth_token"], $_SESSION["oauth_token_secret"]);
// Retrieve access token from Twitter
$accessToken = $tOAuth->getAccessToken();
// Check we have valid response
if(is_numeric($accessToken["user_id"])) {
// Remove request token session variables
if ($this->user->loaded() || $this->user->where('user_id', '=', $accessToken['user_id'])->find()->loaded())
{
$this->user->values(array(
'oauth_token' => $accessToken['oauth_token'],
'oauth_token_secret' => $accessToken['oauth_token_secret'],
'screen_name' => $accessToken['screen_name'],
))->update();
}
else
{
$this->user->values(array(
'user_id' => $accessToken['user_id'],
'oauth_token' => $accessToken['oauth_token'],
'oauth_token_secret' => $accessToken['oauth_token_secret'],
'screen_name' => $accessToken['screen_name'],
))->create();
}
unset($_SESSION["oauth_token"]);
unset($_SESSION["oauth_token_secret"]);
echo $this->view->render();
// Redirect to main page
}
}
}
$this->request->redirect($_SESSION['current_url']);
}
so basically, the AUTO LOGIN (like the user is already logged to twitter, and already registered to your website) can't be done without him clicking the LOGIN WITH TWITTER button, unless you set the lifetime of your $_SESSION pretty high (like it happens with twitpic for example).
$this->user->is_logged() is checking for $_SESSION['id'] (auto increment on MYSQL) and $_SESSION['twitter']['user_id'] from twitter info
EDIT: Also, the quickest and cleanest way to do it, is to make an AJAX call on the page load with the Twitter credentials using the Javascript SDK, then set the $_SESSION variables with the info the SDK provided.