Laravel Define Session for Logged in Users - php

I'm using Google auth0 to authorize users on my server and after that I wanted to put the token in cookies in the user's browser. I achieve that but there's a problem I with initating the session. How can I just make a simple session for a client in Laravel? In PHP it's something like:
session_start();
$_SESSION['userid'] = $userID;
After successful authorization by Google, the server redirects to
client-side with cookies:
return redirect($url)
->withCookie(cookie()->forever('token', $access_token))
->withCookie(cookie()->forever('name', $name));

You can do that like so:
return response($content)
->header('Content-Type', $type)
->cookie('token', $access_token)
Or, you can use a session:
// Via a request instance
$request->session()->put('access_token');
// Get session value
$token = $request->session()->get('access_token');

Related

laravel login check is false after login

User login in app using JWT token then i want to create a link that user can open in browser and automatically login into his account so i send JWT token in query string.
I send JWT token to server then login user manually.
$jwt = request()->jwt;

$user = auth('api')->setToken($jwt)->user();
Auth::login($user);
Auth::check(); // true
but after this request in another route user is not logged in!
Auth::check() // false
Here I see some special characters
The problem was i didn't return response so it didn't set cookie and session was not creating. so i fixed it by returning a response like this:
return response();

Yii2 rest Api for mobile with session ip-address not working

I have worked on web-based rest API but this the first time I am creating Rest API for mobile apps. I am trying to send SMS code to user posted mobile number. SMS code is saved in session with user ip-address.
Next step, user send the SMS code. Rest API compare posted SMS code in the session.
Here is my code for sending SMS and validating SMS code:
//send sms code here
public function actionSendSms(){
$this->response['success'] = false;
$model = $this->loadPostData('step1phone');
$phone = str_replace('+','',Yii::$app->request->post('phone'));
$model->phone = urlencode(preg_replace('/[^\d\+]/', '', $phone));
if(Yii::$app->request->isPost && $model->validate()){
$code = Yii::$app->helper->generateRandomString(4);
Yii::$app->sms->setMessage($code);
$sms = Yii::$app->sms->send($model->phone);
if($sms->status){
$ipAddress = Yii::$app->request->getUserIP();
Yii::$app->session->set('phone-'.$ipAddress, $code);
$this->response['success'] = true;
}else{
$this->response['errorMessage'] = $sms->errorMessage;
}
}else{
$this->response['status'] = 'error';
$this->response['errors'] = $model->getErrors(); //#TODO
}
return $this->response;
}
//sms code validation here
public function actionSendSmsCode()
{
$ipAddress = Yii::$app->request->getUserIP();
\Yii::info('User IP - '.$ipAddress, 'mylog');
$model = $this->loadPostData('step1phoneVerify');
if($model->validate()){
$this->response['status'] = true;
$this->response['data'] = [
'code' => Yii::$app->session->get('phone-'.$ipAddress),
'postValue' => Yii::$app->request->post('phoneVerificationCode'),
];
\Yii::info('code - '.Yii::$app->session->get('phone-'.$ipAddress), 'mylog');
\Yii::info('postValue - '.Yii::$app->request->post('phoneVerificationCode'), 'mylog');
\Yii::info('User IP - '.Yii::$app->request->getUserIP(), 'mylog');
}
else
{
$this->response['status'] = 'error';
$this->response['error'] = $model->getErrors();
$this->response['data'] = [
'code' => Yii::$app->session->get('phone-'.Yii::$app->request->getUserIP()),
'postValue' => Yii::$app->request->post('phoneVerificationCode'),
];
\Yii::info('code - '.Yii::$app->session->get('phone-'.$ipAddress), 'mylog');
\Yii::info('postValue - '.Yii::$app->request->post('phoneVerificationCode'), 'mylog');
\Yii::info('User IP - '.Yii::$app->request->getUserIP(), 'mylog');
}
\Yii::info('Session - '. json_encode(Yii::$app->session) , 'mylog');
//$this->$this->response['session'] = Yii::$app->session->get('phone-'.$ipAddress);
return $this->response;
}
//Model used for validation.
public function validateSmsCode($attribute, $params)
{
$ipAddress = Yii::$app->request->getUserIP();
if(!empty($this->phoneVerificationCode) && $this->phoneVerificationCode != Yii::$app->session->get('phone-'.$ipAddress))
{
$this->addError('phoneVerificationCode', Yii::t('app', 'SMS code doesn`t match.'));
}
}
When I try testing my code from post Rest API service, everything works fine.
But from mobile apps, is never get validate even I post correct SMS code.
When I try to see in my log file." code -" is empty but "User IP -" get ip-address of the user.
Again here if I use post rest API service, in the log file I get the info as excepted. My frontend for my apps is Android.
What I am doing wrong here?
Your mistake that you used IP address as secure and static value which is wrong.
IP address: The user IP address is not unique per user as there are a limited number, so usually multiple user shared same IP, NAT public IP address, read more about NAT but keep in mind user IP is shared and can change and attacker can spoof it.
php session: are data that are usually stored on server (not true in all cases). So the server send a key to the client as secure token, and each time the client with send this token in cookies so the server can load the session. So you don't need the IP you Already have the secure token.
Saving data to session:
Yii::$app->session->set('phone', $model->phone);
Yii::$app->session->set('code', $code);
//Just use key (static string) to store in session as this session in unique per user
reading data from session:
$phone = Yii::$app->session->get('phone');
$code = Yii::$app->session->get('code');
//Just use key that you used to store the data
I advice to read more about Yii2 session YII2 session guide
Keep in mind that you should send session id in all requests using cookies. Also in APP development sessions are rarely used and they usually use rest authorization like auth2 and cache to store data on server.
Session Example: suppose we have this code
public function actionPageCount(){
if(Yii::$app->session->get('count'))
Yii::$app->session->set('count',Yii::$app->session->get('count')+1);
else
Yii::$app->session->set('count',1);
return Yii::$app->session->get('count');
}
First time the user call this action the if statement will be false because the user doesn't have a session id, so in else the web app will create a new session and will set count to 1. When the session is created the server will send to the browser or app this header.
Set-Cookie: PHPSESSID=rl721ac6h3vfgld5repf8pcjl6; path=/; HttpOnly
which mean create new cookie named PHPSESSID with value of rl721ac6h3vfgld5repf8pcjl6. So when the user call the action again. The server will load the session based on the session id. And if the user didn't include the session id the server will create new session. Call this method from a browser and see the behavior then open and new private tab and call it again and see that the server will manage the session for you. In app you have to save the session id and added as cookie in each request.

How to keep a session or cookie alive after visiting and leaving a page?

I am trying to build a referral system using the OAuth system, am working with the Laravel framework. So when a user visit the registration page with a referral link it create a cookie and a session. For to register all that is provided is the social button, so whenever the user clicks on the register with Google or Facebook.
Once the user comes back to the site the session and cookie disappear. Why is that? Below are the files I think may be helpful.
Where I created the session and cookie base on the ref
if ($request->has('ref')){
$referral = ReferralLink::whereCode($request->get('ref'))->first();
$response->cookie('ref', $referral->user_id, $referral->program->lifetime_minutes);
$_SESSION['ref'] = $referral->user_id;
request()->session()->put('ref', $referral->user_id);
}
Where I retrieve the session and cookie base on the ref
$session = request()->session()->get('ref');
dd(request());
$referral = \App\User\ReferralLink::where('user_id', $event->referralId)->orWhere('user_id', $session)->first();
// dd($event->user, $event->referralId, $referral);
if (!is_null($referral)){
$provider = $referral->user;
\App\User\ReferralRelationship::create([
'referral_link_id' => $referral->id,
'user_id' => $event->user->id,
'referree_user_id' => $provider->id,
'reward' => 'no',
]);
}
A solution is to use the state parameter of the OAuth2 protocol to pass additional parameters. Then, when the user click on any "loggin", and you receive the OAuth2 response, you will get your state back.
The idea would be:
Session is on, user have some sessions data
We encoded the session id and we ship it on the OAuth request
The session will be lost when the user finishes to authenticate him/herself
OAuth2 response arrives, session id too
Session id is extracted from response, decoded, and we restore the session back
First, get the Session id and encode it:
use Session;
// ...
$session_id = Session::getid();
$session_id = base64_encode($session_id);
I did not see your OAuth2 request, so we take a dummy example to show how to ship the state (= the encoded session id):
$request = "https://authorization-server.com/auth?response_type=code&
client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=photos&state=$session_id";
(the best is to use at least http_build_query() or better GuzzleHttp)
Then, the user is authenticated and we get our response back:
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
"token_type":"bearer",
"expires_in":3600,
"refresh_token":"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk",
"scope":"photos",
"state":"aGVsbG8gd29ybGQ="
}
And then we will decode it to get back our session id:
$response = /* ... */
$state = $response['state'];
$session_id = base64_decode($state);
And finally, restore your session:
Session::setId($session_id);
Session::start();

Caching API user credentials

I have this code running on every HTTP request:
if ($request->header('Authorization')) {
$token = $request->header('Authorization');
$user = User::where('api_token', $token)->whereRaw("`api_token_expires` >= CURDATE()")->active()->first();
if ($user) {
$GLOBALS['user_id'] = $user->id;
$GLOBALS['is_admin'] = $user->admin;
return $next($request);
}
}
As you can see, I'm hitting the database for every request looking for a valid API token.
What's a more efficient - but safe, best practice - way of handling this? Should I be looking at MySQL caching? Redis or something else?
EDIT: I'm not using sessions, this is a stateless API.
You can make api-users authorize first and respond with a session token.
Then they can use this session token for each next request.
You can store these sessions in the $_SESSION variable, on disk in a file or on a fast database like Redis.
To do this securely I would remove old sessions automatically, check the session token against it's origin IP, and force https for the api.

Codeigniter API session

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?

Categories