PHP Session doesn't work in Angular 6 project - php

I am using angular 6 for frontend and PHP for backend (WAMP) and I want to make a login system. When someone enters valid credentials I want him to get redirected to http://localhost:4200/home
I have auth.php which sets the session variables when someone enters valid username/password and verify.php to check if the session variables are set.
Although the app redirects me to home, verify.php can not see the session variables.
Those are my files:
login-form.component.ts
loginUser(event) {
const target = event.target;
const username = target.querySelector('#username').value;
const password = target.querySelector('#password').value;
this.Auth.login(username, password).subscribe(data => {
if(data.success) {
this.router.navigate(['/home']);
}
else {
window.alert(data.message);
}
});
}
which takes the username and password from html and sends it to the service
auth.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http'
interface myData {
success: boolean,
message: string
}
#Injectable({
providedIn: 'root'
})
export class AuthService {
constructor(private http: HttpClient) { }
login(username, password) {
return this.http.post<myData>('http://localhost/angular6-app/api/auth.php', {username, password},
{
headers : {
'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8'
}
})
}
auth.php
include 'config.php';
header('Access-Control-Allow-Origin: http://localhost:4200');
$postdata = file_get_contents("php://input");
if(isset($postdata) && !empty($postdata)) {
$request = json_decode($postdata);
$username = $request->username;
$password = $request->password;
$sql = "select * from user where username = '$username'";
$result = $conn->query($sql);
$row = $result->fetch_assoc();
if($row['username'] == $username && password_verify($password, $row['password'])) //kanei verify me to hash pou exei ginei
{
$_SESSION['username'] = $username;
$_SESSION['loggedin'] = true;
?>
{
"success": true,
"message": "You have logged in"
}
<?php
}
else {
?>
{
"success": false,
"message": "Invalid credentials"
}
<?php
}
}
?>
and finally verify.php
<?php
session_start();
header('Access-Control-Allow-Origin: http://localhost:4200');
if (isset($_SESSION['loggedin'])) {
?>
{
"success": true,
"message": "You have the right."
}
<?php
}
else {
?>
{
"success": false,
"message": "You DONT have the right."
}
<?php
}
?>
My home.component.ts has this class and I want to display in html "You have the right" but it displays "You DONT have the right" because the variable loggedin is undefined.
export class HomeComponent implements OnInit {
message = "Loading..."
constructor(private user: UserService) { }
ngOnInit() {
this.user.getSomeData().subscribe(data => {
this.message = data.message;
})
}
getSomeData() is implemented in user.service.ts
getSomeData() {
return this.http.get<myData>('http://localhost/angular6-app/api/verify.php');
}
Is there a way to fix this problem with session or do I have to use another method of checking in angular?
Thank you.

You can't set SESSION on one domain and use on other domain, From your code it's clear you are using two different port, if you want to use sessions javascript and PHP must be on the same Domain/ports.
If you want to use different domains/ports then you have to find other ways like token based auth, i.e in auth.php after successful login create a token which will be saved in your database, send back that token in your successful response.
in your angular save that token to storage ( or wherever you prefer ) and retrieve use data from your PHP API using that token.
so when you do a call in user.service.ts your URL should contain the token
YOUR_TOKEN = '1234'//received after successfull login and saved in local storage
return this.http.get<myData>('http://localhost/angular6-app/api/verify.php?token='+YOUR_TOKEN);
in your verify.php
$token = $_GET['token'];
// check if token is valid in your database and send response
p.s when logout make sure to either expire or delete token from angulare storage and database.

You will get your session values once you build ngApp and make it live and keep your app and API in the same directory, you can use the same above method. Because you are going to access the API with same port/domain.

I had the same issue working on React and PHP locally, both using localhost but on different ports. This answer helped me.
PHP sessions are stored on cookies, and when making cross-domain (or in this case cross-port) requests those cookies are not shared.
In your first login call to PHP, you need to return the session ID using session_id() and store this somewhere on your app.
auth.php
//.....
{
"session_id": session_id(),//<- Return sid and store it on app
"success": true,
"message": "You have logged in"
}
//.....
Then, when making furter calls to PHP, make sure to pass it the same session id. You can then use session_id() again to set the id to the one you passed, which will keep the last session active:
verify.php
<?php
$postdata = file_get_contents("php://input");
if(isset($postdata) && !empty($postdata)) {
$request = json_decode($postdata);
if ($request->session_id) {
session_id($request->session_id);
}
}
session_start();
header('Access-Control-Allow-Origin: http://localhost:4200');
if (isset($_SESSION['loggedin'])) {
$json['session_id'] = session_id();//Return sid and store it on your app for future calls
$json['success'] = true;
$json['message'] = "You have the right.";
} else {
$json['success'] = false;
$json['message'] = "You DONT have the right.";
}
echo json_encode($json);

I recently ran into this issue when trying to use angular-cli and xampp together. I worked around it by using
ng build
instead of
ng serve
here is build command I used.
ng build --outputPath="C:\development\xampp\htdocs\cars" --watch
This works similar to ng serve the only difference being I am serving angular app out of the xampp server instead of the angular cli server.
One more item to keep in mind is that my angular app is running inside 'cars' folder so we need to update the 'baseref' inside the index.html file in the angular application. Here is the baseref code
<base href="./">
Otherwise when we navigate to
http://localhost/cars/
it tries to pick up all the css and js files from htdocs folder

Related

Keep session with cURL in codeigniter php

I have a external API where I want to GET some data, and I want to keep session id through all the request until I log out. Using cURL lib in codeigniter I have the following flow (myacc and mypass are just placeholders):
public function getCURL() {
echo $this->curl->simple_get('http://37.99.110.537:6001/webapi/auth.cgi?api=SYNO.API.Auth&method=login&version=2&account=myacc&passwd=mypassD&format=sid&session=SurveillanceStation');
}
This will output:
{"data":{"sid":"lH6WJCWMm5rkA14B0MPN570354"},"success":true}
I will have to keep that provided sid (session id) when making the next request:
http://37.99.110.537:6001/webapi/entry.cgi?api=SYNO.SurveillanceStation.Camera&method=GetSnapshot&version=1&cameraId=2&timestamp=1480512959&preview=true&_sid="lH6WJCWMm5rkA14B0MPN570354"
See at the end sid="lH6WJCWMm5rkA14B0MPN570354".
And then log out and kill that sid.
After each login I would get a new sid that I have to use it to get a picture (with that URL) and then logout.
I think that saving and using cookies from a file in my case isn't needed, I think something like:
public function getCURL() {
echo $this->curl->simple_get('http://37.99.210.237:6001/webapi/auth.cgi?api=SYNO.API.Auth&method=login&version=2&account=myacc&passwd=mypassD&format=sid&session=SurveillanceStation');
if ($this->form_validation->run()){
$data= array(
'sid'=> $this->input->post('sid'),
'is_logged_in' => true
);
$this->session->set_userdata($data);
if(false == $this->CI->session->userdata('is_logged_in')) {
echo $this->curl->simple_get('http://37.99.110.537:6001/webapi/entry.cgi?api=SYNO.SurveillanceStation.Camera&method=GetSnapshot&version=1&cameraId=2&timestamp=1480512959&preview=true&_sid="sid"');
}
}
}
^^ That syntax is messed up, but how I can make it in a proper way or how it's the best way to keep session id on the request chain ?
if you want to keep sid for long session, for multiple request etc, you can save this json to some json file and clear content of file while logging out.
wrap your $sid getter to some other function.
function getSid()
{
//try to read from json
if(is_file('path/to/sid.json'){
$sid = json_decode(file_get_contents('path/to/sid.json', true));
if(!isset($sid['logout'])){
return $sid['data']['sid'];
}
}
$sid = $this->curl->simple_get('http://37.99.110.537:6001/webapi/auth.cgi?api=SYNO.API.Auth&method=login&version=2&account=myacc&passwd=mypassD&format=sid&session=SurveillanceStation');
//check and save `$sid`
if(strlen($sid) > 20) {
file_put_contents('path/to/sid.json', $sid);
return json_decode($sid, true)['data']['sid'];
}
return false;
}
and update content of sid.json while logging out.
function logout()
{
file_put_contents('path/to/file', json_encode(['logout' => 'true']));
}
and call these methods.
for every request in one execution, it will use the same sid, and when you'll hit 'logout()' it will destroy the sid so that new generated and used on next execution.

JSON Login Authentification Zend Framework

I am creating a form login with ExtJS, and sending JSON data to do authentification within Zend Framework. The problem is, no matter what username and password I fill, login always succeed. Here's the related code :
Submit Function for Ext JS Form, where we send JSON data contained username and password.
var doLogin = function () {
if (formPanel.getForm().isValid()) {
formPanel.getForm().submit({
method: 'POST',
url: '/zend/public/auth/valid',
waitMsg: 'Processing Request',
success: function (form, action) {
document.location = '/zend/public/guestbook';
},
failure: function (form, action) {
if (action.failureType = 'server') {
obj = Ext.util.JSON.decode(action.response.responseText);
Ext.Msg.alert('Login Failed', obj.errors.reason);
} else {
Ext.Msg.alert('Warning!', 'Authentification server is uneachable : ' + action.response.responseText);
}
formPanel.getForm().reset
}
})
}
}
The Controller, we have ValidAction function to receive and send JSON data, and process to do the authentification.
public function validAction()
{
if(!isset($this->session->isLogin)){
$username = mysql_escape_string($_POST['username']);
$password = mysql_escape_string($_POST['password']);
$formdata = array('username'=>$username, 'password'=>$password);
if ($this->_process($formdata)) {
$this->session->setExpirationSeconds(3600);
$msg = '{success:true, result:{message:\'Welcome, '.$username.'!\'}}';
} else {
$msg = '{success:false, errors:{reason:\'Login failed, try again.\'}}';
}
}
protected function _process($values) {
// Get our authentication adapter and check credentials
$adapter = $this->_getAuthAdapter();
$adapter->setIdentity($values['username']);
$adapter->setCredential($values['password']);
$auth = Zend_Auth::getInstance();
$result = $auth->authenticate($adapter);
if ($result->isValid()) {
$user = $adapter->getResultRowObject();
$auth->getStorage()->write($user);
return true;
}
return false;
}
The problem lies in validAction, and weirdly I do var_dump to $this->process($formdata) and returns false, yet it always go to if function, message Success. Any ideas? Appreciated fellas.
UPDATE :
The var_dump :
Uncaught Error: You're trying to decode an invalid JSON String:
array(2) {
["username"]=>
string(2) "ad"
["password"]=>
string(4) "pass"
}
bool(false)
string(59) "{success:false, errors:{reason:'Login failed, try again.'}}"
Backend problem
You are outputting invalid JSON.
PHP provides json_encode to save you having to manually create json:
$response=array();
$response['success']=false;
$response['result']=array();
$response['message']='Welcome '.$username;
$msg = json_encode($response);
If you really don't want to use this you should add double quotes to your keys, and change to double quotes for your string properties too:
$msg = '{"success":true, "result":{"message":"Welcome, '.$username.'!"}}';
Front end problem
You are using success and failure methods, but I can't see anything in your back end code to send status headers.
The failure method will only get called when a response returns with a non 200 status code. So you may need to either add this to your back end code, and/or also decode the response inside your success method to make sure that you have sent success:true as part of your json before redirecting.
To send the header in PHP 5.4 or newer:
http_response_code(401);
in 5.3 or older you have to use header method instead - but if you are running this version you should upgrade immediately so I wont include an example.

PHP Login system hard coded username and password

I had to do a basic login system to protect a page, and I have no access to database so i store the username and password hard coded in php page.
My question is, can this login system hold againts an attack? I need it to hold about 1 month.
Any sugestions to improve will be helpefull.
The code is not in laravel, even if it might look like.
The username and password, will be changed to something stronger of course.
Thank you in advance.
<?php
class UserController {
private $username;
private $password;
private $isLoggedIn = false;
// Credentials
public function credentials() {
$credentials = array(
array(
"username" => "telekom",
"password" => "1234"
),
array(
"username" => "telekom2",
"password" => "1234"
)
);
return $credentials;
}
// Basic login
public function login() {
foreach ($this->credentials() as $credential) {
if ($this->username == $credential['username'] && $this->password == $credential['password']) {
Session::put('username', $this->username);
Session::put('password', $this->password);
$this->isLoggedIn = true;
}
}
}
// Get login status
public function isLoggedIn() {
return $this->isLoggedIn;
}
// Logout
public function logout() {
// Delete all sessions
Session::all();
redirect('/telekom/');
}
// Telekom
public function telekom() {
$form = new Form();
if (Input::get('logout') == 1) {
$this->logout();
}
// Post Data from login form
if (Input::has('username') || Input::has('password')) {
if (!$form->isCsrfValid()) {
$form->errors['CSRF'] = "CSRF Token";
} // CSRF protection is on, comment to disable
if (empty($form->errors)) {
$this->username = Input::get('username');
$this->password = Input::get('password');
// Check Login
$this->login();
if (!$this->isLoggedIn()) {
Session::put('login', 'Username and password do not match.');
} else {
redirect('/telekom/');
}
} else {
Session::put('login', '<p class="color-dark-red"><strong>Errors:</strong></p>
<p>' . $form->displayErrors($form->errors) . '</p>');
}
// Check if session has username and password
} elseif (Session::has('username') && Session::has('password')) {
$this->username = Session::get('username', false);
$this->password = Session::get('password', false);
// Check Login
$this->login();
}
}
}// EOF Class User
// Outside class
$user = new UserController();
// Outside class
if (!$user->isLoggedIn()) {
// display login form
} else {
// display protected content
}
?>
My comments are getting lengthy, so I'll just move them here. I would not recommend you put the username and password in the same file. If PHP ever fails to process the page, it will be dumped as plain text to the user. Even for database connections (where the un/pwd almost have to be stored plain text), most people don't put the information in the same file.
You have a couple options:
Make a separate PHP file that sets your UN/PWD variables, put it somewhere that isn't accessible from outside your server, and include it in index.php. In this case, I wouldn't include the file until right when you're going to compare the variables and let the local scope dump it as soon as possible.
Since this is such basic authentication, you could use Apache's built in password authentication module.
in my opinion, this solution is safe enough when you don't plan to use it forever.
What would I check is setting of your web server - some text editors makes backup copies of edited files, like index.php~, index.php.bkp or so. Make sure whether your web server do not serve those files, if any.
The problem with temporary solutions is that they've never temporary.
Never hard code passwords. Some of the reasons are:
It is harder to keep source code secret than it is a key.
Any vulnerabilities in your site that allow reading of source code may reveal the password.
Passwords from development will end up in production.
It is impossible to change passwords without redeploying.

PHP Tokens for Forms and Authentication

I have a question about tokens. I understand that they are random characters used for security purposes but just how do they work and what do they protect against?
Authentification mechanism creates a token when form displayed, and was stored it on server side.
Also auth mechanism adds token as hidden input to form. When you send it, auth system check is it in server-side storage.
If token found, authentification process will continue and token was removing.
It protects from spamming form action script.
Example using with logout url:
<?php
// Generate token
$logout_token = md5(microtime().random(100, 999));
session_start();
// Store token in session
if (!is_array($_SESSION['logout_tokens']) {
$_SESSION['logout_tokens'] = array();
}
$_SESSION['logout_tokens'][] = $logout_token;
?>
logout
Script, that processing logout:
<?php
$done = false;
if (!empty($_GET['logout_token'])) {
// Get token from url
$logout_token = $_GET['logout_token'];
session_start();
if (!is_array($_SESSION['logout_tokens']) {
$_SESSION['logout_tokens'] = array();
}
// Search get token in session (server-side storage)
if (($key = array_search($logout_token, $_SESSION['logout_tokens'], true)) !== false) {
// Remove used token from storage
unset($_SESSION['logout_tokens'][$key]);
// Do logout
$done = true;
}
}
if ($done === false) {
echo "Something went wrong.";
}

Session Security?

Is it secure to use
If ($_SESSION['authenticated'] == true) {
/////Show secure page
}
Can someone just go and change where the session variable is stored to make their $_SESSION['autheticated'] = to true?
Same thing with a user having $_SESSION['id'] = to their index id. How would I be able to make this securer?
Could someone just go and change the id value and impersonate another user?
Would the below method be the right way to make something securer?
$_SESSION['random_check'] = (random number)
and also store this in a column in my database and each time I would
If ($_SESSION['authenticated'] == true && $_SESSION['random_check'] == random_number ) {
/////Then show secure page
}
Thanks,
I'm pretty sure Session in most hosting is just an interface to your filesystem, i.e. all Session data is stored in the server's hard disk, if you look at phpinfo() output, you can have a look at where the actual path of Session data is.
With that said, unless you chmod your session path to 777 and the attacker happens to know where you are hosting your app and has the login, then I don't think it's much of an issue.
The bigger issue here is securing your cookie as it's the piece of information that's going back and forth through your server and client, which attackers can use to impersonate legit users.
Yes,Is it secure to use. I use this.
I do this:
-check login,if is an valid login , set $_SESSION['logged'] = 'yes' and generate um token $_SESSION['token'] = 'the token'
this token, I save in an input html element and check in each action.
something like:
<?php
class token {
public function generateToken() {
return $_SESSION['token'] = md5( microtime() );
}
function generateField($name = "token"){
return "<input type='hidden' value='{$_SESSION['token']}' name='{$name}'>";
}
public function getToken() {
return $_SESSION['token'];
}
public function getTokenFromFields($method = "GET") {
return strtoupper($method) == "GET" ? $_GET['token'] : $_POST['token'];
}
public function checkToken() {
return $this -> getToken() == $this -> getTokenFromFields();
}
public function updateToken() {
$_SESSION['token'] = md5( microtime() );
}
}
?>
<?php
//orther file
require 'class.token.php';
$token = new token();
$Atoken = $token -> generateToken();
echo "<script>
var data = {};
data['token'] = '{$Atoken}';
data['foo'] = 'baa';
</script>";
$token -> generateField();
?>
<script>
$.ajax({type:"GET", url:"process.php", "data=foo=baa&token=" + data.token, success:function(response) { } })
</script>
In process.php:
<?php
if($_SESSION['token'] == $_GET['token']) {
//do something
} else die('bad token');
?>

Categories