IOS HTTPCookie not recognized in PHP API - php

I'm authenticating my users and then sending each of them a unique cookie which I will store server side and client side. In order to provide some level of security to my API, I'm sending every request to my api with that cookie.. I set the cookie on IOS like this
let cookie = HTTPCookie(properties: [HTTPCookiePropertyKey.originURL : apiURL, HTTPCookiePropertyKey.name :
cookie_name, HTTPCookiePropertyKey.value : cookie_value, HTTPCookiePropertyKey.path : "/"])
HTTPCookieStorage.shared.setCookie(cookie)
I'm 100% sure that the way I'm setting my cookie up is perfect. I've done it in previous apps... just never with a PHP API on the other end. The only issue is that my PHP API doesn't recognize the cookie...
I'm checking like this:
if($_COOKIE['cookie_name'] != ''){ }
When I try to call the API from Postman (a google chrome extension that allows to pass cookies), it works fine and my php script recognizes the cookie. When I try to make calls from my mobile device, I get unauthorized access everytime because the PHP API fails to recognize that the cookie was passed...
The reason why I'm confident that I'm creating and passing my cookie correctly is because I do it in all of my Ruby on Rails app the same way...
Any advice?

Check like this
let cookie = HTTPCookie(properties: [HTTPCookiePropertyKey.originURL : apiURL, HTTPCookiePropertyKey.name :
cookie_name, HTTPCookiePropertyKey.value : cookie_value, HTTPCookiePropertyKey.path : "/"])
HTTPCookieStorage.shared.setCookie(cookie)
if($_COOKIE['cookie'] != ''){ }
the name of the cookie is not cookie name it's cookie as the line below
// (cookie) = cookie name
HTTPCookieStorage.shared.setCookie(cookie)
so this is how you should check
if($_COOKIE['cookie'] != ''){ }

Related

How to implement authentication on a REST architecture with Parse

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

Laravel sanctum csrf cookie every request?

I'm using Laravel sanctum (former Airlock) and have a question about it. I read in the docs:
To authenticate your SPA, your SPA's login page should first make a
request to the /sanctum/csrf-cookie route to initialize CSRF
protection for the application:
axios.get('/sanctum/csrf-cookie').then(response => {
// Login... });
Once CSRF protection has been initialized, you should make a POST request to the typical Laravel /login route. This
/login route may be provided by the laravel/ui authentication
scaffolding package.
Does this mean that for every request I make, I should first check if the cookie has already been set? Because let's say I have a user that registers. Before making the POST request to register a user I should first make a GET request to get the CSRF-Cookie from my backend and then make the POST request to register the user.
Now the user gets redirected to the login webpage and is asked to login. Does the frontend then first have to check if there's a CSRF-Cookie, and if there isn't should it first again make the GET request to get the cookie?
This last bit also confuses me, because when calling the register method a user doesn't actually get logged in so the user has to be redirect to the login page to log in with the credentials the user just filled in to register which for me seems like a bad user experience, right?
I know it's been a while since this question was asked but just for anyone searching out there, No. You don't have to call /sanctum/csrf-cookie with every request. Before you make a post | put | delete... request, you can check to see if the XSRF-TOKEN cookie is set. If it is not, make a call to the /sanctum/csrf-cookie route (or whatever you have configured it to be). After the request has completed, (the XSRF-TOKEN cookie would have been set by your browser automatically) you can now proceed with the initial request.
The best place to do this is in an interceptor (if your http library supports it). I'm going to assume you are using axios.
// Install with 'npm i js-cookie'. A library that helps you manage cookies
// (or just build your own).
import Cookies from 'js-cookie';
// Create axios instance with base url and credentials support
export const axiosInstance = axios.create({
baseURL: '/api',
withCredentials: true,
});
// Request interceptor. Runs before your request reaches the server
const onRequest = (config) => {
// If http method is `post | put | delete` and XSRF-TOKEN cookie is
// not present, call '/sanctum/csrf-cookie' to set CSRF token, then
// proceed with the initial response
if ((
config.method == 'post' ||
config.method == 'put' ||
config.method == 'delete',
/* other methods you want to add here */
) &&
!Cookies.get('XSRF-TOKEN')) {
return setCSRFToken()
.then(response => config);
}
return config;
}
// A function that calls '/api/csrf-cookie' to set the CSRF cookies. The
// default is 'sanctum/csrf-cookie' but you can configure it to be anything.
const setCSRFToken = () => {
return axiosInstance.get('/csrf-cookie'); // resolves to '/api/csrf-cookie'.
}
// attach your interceptor
axiosInstance.interceptors.request.use(onRequest, null);
export default axiosInstance;
The XSRF-TOKEN cookie comes with a time of expiry. After that time, the browser deletes it. So as long as you can find the cookie, it is safe to make a request without calling /sanctum/csrf-cookie or whatever you have configured it to be.
When you get the csrf token, in the following request, laravel will update the token automatic, so you dont need focus this after axios.get('/sanctum/csrf-cookie').
Once you hit axios.get('/sanctum/csrf-cookie') API, after that you don't have to hit it again and again for every request, Because this/sanctum/csrf-cookie will save the XSRF token on browser and Axios will send it with the request.
You can learn about it in detail in this video: https://www.youtube.com/watch?v=8Uwn5M6WTe0

How to sign HTTP requests with user credentials for mobile app and backend server communication?

We have a pretty standard scenario - a mobile app communication with a backend PHP server API via HTTP POST and GET. A user must login in mobile app in order to do anything, so every request from mobile app to our server needs to be signed with user credentials. Userid and password are saved in mobile app internal settings after successful login, so a user does not need to reenter it again.
Previously, backend PHP webservices were developed by other guys, but now we need to implement it ourselves. When looking at previous projects, they required to pass user credentials for every request. I'm posting several request examples below. All data insert/update web services use POST, but userid and pwd are passed inside body with other data (Save Car). All data select services pass userid and its password via GET params.
Is it the best and secure way? Maybe we should put sha1(userid+password=salt) into HTTP authorization header and leave userid in body (because we need to select user pass from database in server)? Or maybe we could use OAuth 2 in mobile app for signing HTTP request (generating userid+pass+... to authorization header) and use OAuth 2 in backend to generate the same hash and check if it's the same? I could'n find any straightforward way how to use OAuth 2 for PHP just for signing request, so any help would be appreciated :) Also, related info about what libraries to use for iOS/Android development would be also appreciated.
LOGIN
HTTP method: POST
URL: http://mybackend.com/login
BODY:
{ "uid" : 123,
"pwd" : "3CB3E2E6AECA48C41000119767B561F5E9E66229" // contains sha1(pass+salt)
}
GET CAR LIST
HTTP method: GET
URL: http://mybackend.com/getCars?uid=123&pwd=3CB3E2E6AECA48C41000119767B561F5E9E66229
SAVE CAR
HTTP method: POST
URL: http://mybackend.com/saveCar
BODY:
{ "uid" : 123,
"pwd" : "3CB3E2E6AECA48C41000119767B561F5E9E66229",
"car" :
{ "id" : 111,
"name": "My car"
}
}
I may ask if user can change password in app then is it updating that password with the saved one in app code?
better way to post data as make a directory of access_token and use userid and password in it.
as for Example :
{
"access_token":{
"uid" : 123,
"pwd" : "3CB3E2E6AECA48C41000119767B561F5E9E66229"
},
"saveCar" : {
"id" : 111,
"name": "My car"
}
}
and at the sever side php code be easy to access your all url with this accesstoken by checking with database and allowing you access to do the saveCar in database.
else from sever side you will have error message as access failed to login try again with login.
and use it in post method with all requests.
will be good for security type.
POST method is one for PHP data security.
no other thing you need for this.
Instead of using GET HTTP request for car list, you can POST the access token to your url as
{
"access_token":{
"uid" : 123,
"pwd" : "3CB3E2E6AECA48C41000119767B561F5E9E66229",
}
}
to your URL for Carlist.
http://mybackend.com/getCars? from that post method, do the code for as in result of this post method returns the list of cars.
Thanks, Hope this description can help you.

HTTP sessions are removed after the app is closed (iPhone app)

In my iPhone app, I am using AFNetworking to make HTTP requests to a PHP API.
Every time I open the app, I have to login and the server will initiate the sessions.
After I log in, every time I will make an HTTP request to the API, the API knows that I have the session and will allow me to use every function of the API.
The problem is that after I close the app, I think that the sessions are destroyed and I am can't use any functionality from the API without having to login again.
I am talking about an iPhone app here which uses AFNetworking to make the HTTP request.
From my tests I know that the session is destroyed after the app is closed.
I want to know if this is true and I want to know what's the best way of making an authentication system. I think that session is not a solution anymore, since they are destroyed after the app is closed. My alternative was to create an auth_token every time someone logs in and store the token in the app, then every time someone open the app the first http request they will make it will contain the auth_token and if that token matches with the one from the database, then initialize the session as usual. I think that this can be a bit slower, providing that every time you open the app it will have to make an HTTPS request to initialize the connection between the client and the server.
So the question is: Is it true that you can keep the session alive after you close the app? Is it my alternative a good one?
This is the solution to my question.
If you are using AFNetworking the cookies are removed after you close the app. So to fix this you can save the cookies in user defaults and then load them when the app is open.
Save the cookies (you should check the name of the cookie first, mine was PHPSESSID, because you don't want to save unuseful cookies):
NSArray * all = [NSHTTPCookie cookiesWithResponseHeaderFields:[self.response allHeaderFields] forURL:[NSURL URLWithString:#"http://link.to.api" ]];
for (NSHTTPCookie *cookie in all)
{
if([cookie.name compare:#"PHPSESSID"] == NSOrderedSame)
{
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:cookie];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:#"MySavedCookies"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
Then when you load the app in "application didFinishLaunchingWithOptions" for example:
NSData *cookiesdata = [[NSUserDefaults standardUserDefaults] objectForKey:#"MySavedCookies"];
if([cookiesdata length])
{
NSHTTPCookie *cookie = [NSKeyedUnarchiver unarchiveObjectWithData:cookiesdata];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
}
NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL: networkServerAddress];
for (NSHTTPCookie *cookie in cookies)
{
[[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie];
}

Deauthorise Facebook app using the API

Is it possible to deauthorise my own app using the API [assuming I have sufficient permissions]?
I'm writing some unit tests and want to be able to register/unregister the app programatically (I'm aware the register step requires user input)
I'm working in PHP so calls are being made to the various URLs eg to logout:
header("Location: https://www.facebook.com/logout.php?next=" . urlencode($ReturnUrl) . "&access_token=" . $Params['access_token']);
For calls that return data, I'm using file_get_contents().
I'm already handling all the OAuth tokens.
I need a solution I can use server-side not JavaScript / browser automation.
Make a HTTP DELETE request to /PROFILE_ID/permissions with your user's access token (I think the App Access Token will work here too)
e.g. in PHP using the SDK it may look like :
$user_id = 'user id here';
$facebook->api($user.'/permissions','DELETE');

Categories