I'm trying to use JWT to create a authentication system using AngularJs and PHP. I understood the concept of JWT, I can modify the headers and send my access token, etc... My doubt is on the logic to elaborate this since I have a lot of different functions.
For example, I have a file called client.php where I have client related functions, such as getClient, updateClient, insertClient, etc.. The same applies for other files, product.php, category.php, filter.php and so on.
So, how am i supposed to do this token validation before actually running any of these functions?
I tought of creating a common function and use it inside each function, for example:
function.php
function checkToken($token) {
$serverToken = //getting server token;
if($token !== $serverToken) {
return false;
}
}
client.php
require_once 'function.php';
$tokenError = array('status' => 'Unauthorized');
function insertClient() {
global $tokenError;
$accessToken = $_SERVER['HTTP_TOKEN'];
if(!checkToken($accessToken)) {
return $tokenError;
} else {
//Proceed with the function
}
}
function getClient() {
//Repeat samething as insertClient
//...
}
But it doesn't feel like the proper way to do this. So, is there a better, or a correct way, to do headers validation/authorization on each http request the user make?
Related
I made a controller.php file to handle ajax requests, with $_POST parameters action and module
if (isset($_POST["action"])) {
$action = strtolower($_POST["action"]);
if ($action === "get_notification") {
// return session notification messages
//...
} elseif (isset($_POST["module"])) {
require_once("libraries/class.module.php");
$module = new Module;
$moduleName = strtolower($_POST["module"]);
// check if module-name is valid
if ($module->verify($moduleName)) {
// load $modulename class
require_once("libraries/class.".$moduleName.".php");
// factory used to create instance of $moduleName
require_once("libraries/class.factory.php");
// note: moduleName class extends Module class
$module = $Factory->create($moduleName);
// verify method of $moduleName verifies action/method parameter
// using method_exists and cross-checking against a permitted methods list
if ($module->verify($action)) {
$message = $module->$action();
echo json_encode($message);
} else {
// handle invalid requests
echo json_encode(["0", "Invalid request received"]);
}
} else {
// handle invalid requests
echo json_encode(["0", "Invalid request received"]);
}
} else {
// handle invalid requests
echo json_encode(["0", "Invalid request received"]);
}
} else {
// handle invalid requests
echo json_encode(["0", "No request received"]);
}
But I read this post on Stack Overflow which advises against using variable methods. Should I opt for a switch case that checks each $action and calls corresponding method. That will result in a lot more code which was the initial reason I opted for this variable method solution.
It looks like what you really need is a proper routing system. You could make it yourself (as described here). Or use an existing solution, like FastRoute.
As for actually using "variable methods", in general it is a bad idea. But, if those methods are at the beginning of your call-stack (executed from the bootstrap-file), they are a really practical option.
When it comes to security concerns, the only public method in your controller classes should be ones, that you expect to be called. Which mean that you can simply do:
if (method_exists($controller, $action)) {
P.S. You don't have to do strtolower() there, because in PHP the class methods are not case-sensitive (and neither are the class names themselves).
P.P.S. Look into using composer as PSR-4 autoloader
I have some php codes, and there is a condition which declare type of ajax. Now I want to know, should I write all php codes for each request separately? In other word, should I write all php codes twice (almost repeatedly) for both methods?
if(!empty($_SERVER["HTTP_X_REQUESTED_WITH"]) && strtolower($_SERVER["HTTP_X_REQUESTED_WITH"]) === "xmlhttprequest")
{
// I'm ajax
$arr = array('key1'=>'value1', 'key2'=>'value2');
echo json_encode($arr);
} else {
// I'm not ajax
$arr = array('key1'=>'value1', 'key2'=>'value2');
$_SESSION["arr"] = arr;
header('Location: '.$_SERVER['HTTP_REFERER']); // redirect to previous page
}
So, as you see, I have to write all PHP code twice. One time for regular request and one time for ajax request. In reality there is a lot of codes, Maybe 1000 lines of code that I have two write them again for ajax requests (while they are almost identical). Is this a normal way?
Also I want to know, is there any succinct approach? Actually I like to use a approach which needs to php code just one time for both requests ...!
I would create a class to handle those request and put common code right into a method used by both contexts:
// file: class.handler.php
class contextHandler() {
public function handleHttp() {
$this->handleGeneral();
// What ever has to be done in this context
$_SESSION["arr"] = arr;
header('Location: '.$_SERVER['HTTP_REFERER']);
}
public function handleAjax() {
$this->handleGeneral();
// What ever has to be done in this context
echo json_encode($arr);
}
private function handleGeneral() {
// put common code here
$arr = array('key1'=>'value1', 'key2'=>'value2');
}
}
In your code you could then use that class:
include 'class.handler.php';
$handler = new contextHandler();
if(
!empty($_SERVER["HTTP_X_REQUESTED_WITH"]) &&
strtolower($_SERVER["HTTP_X_REQUESTED_WITH"]) === "xmlhttprequest"
)
{
$handler->handleAjax();
} else {
$handler->handleHttp();
}
This has of course to be adjusted to your concrete needs but offers a nice and clean way of reusing code and generating small and readable code.
I need to use an ajax request to perform login. Here's the function that request goes to:
function loginAdmin() {
$app = \Slim\Slim::getInstance();
if (auth()) {
$app->setCookie('admin', TRUE);
exit(TRUE);
}
exit(NULL);
}
And I will process the ajax response to see if it's true. But the cookie wouldn't be set. If I remove exit(TRUE) the cookie can be set.
I've read the source code of Slim, the setCookie() function calls \Slim\Http\Cookies::setCookie(), which set the key and value into $data member. But I'm not sure when the cookies are sent.
But I still don't know how does exit function affect setCookie function.
You cannot send response using exit(). You should echo() the response in the route. For example something like:
function loginAdmin() {
$app = \Slim\Slim::getInstance();
if (auth()) {
$app->setCookie('admin', TRUE);
return 1;
}
return 0;
}
$app->get('/foo', function {
echo loginAdmin();
});
Above code is not a good way to do authentication, but it shows the point.
I have a set of soap APIs which can perform actions like login,logout,keepalive,access other several resources.Inorder to access the other resources,I have to pass a session id which I got from the login api.The session gets time out in 5minutes.
I am confused on how to make this working.
I am using codeigniter for my project,and I have built one library with the set of soap api requests defined in it.
class Soap_api
{
function __construct()
{
define("UID", "myuser");
define("PWD", "34rf3a45575");
define("API_ENDPOINT", "http://uat-api.testingsoapapi.in/services/smp");
define("PRODUCT_CODE", "24");
$resp = $this->keepAliveLib();
if($resp['ResponseCode'] == '0')
{
define("SessionID",$resp['SessionID']);
}
}
function keepAliveLib()
{
$resp = $this->login();
return $resp;
}
function one
{
//This function needs the sessionID receieved from login function
}
function two
{
//This function needs the sessionID receieved from login function
}
So when ever any of the functions from this class is accessed,the constructor calls the keepAliveLib which calls the login function residing in this class and return the session id to the constructor function and set it as global constant sessionID .So the function which I called will be using the that session ID which is made as a constant.
Is this the standard way of calling APIs which relay on sessions?The login function is called when ever a function is called and creates a different session ID.There is a function keepAlive in the library which can be used to maintaining the session,but instead of using keepAlive , Im logging each time a function in this is accessed.
Is there anything wrong in this flow?Can this be done in some other ways?
ok i'm probably not understanding this fully but would this work?
$resp = $this->keepAliveLib();
if($resp['ResponseCode'] == '0') {
$this->sessionid = $resp['SessionID']); }
else { // fail gracefully }
$this->sessionid is now available to any method in the controller.
I'm trying to convert my PHP app into more of an MVC app. I don't have much experience with MVC and I don't fully understand some of/all of the concepts or how to do it with PHP, so I need some help understanding where a particular function goes.
This function returns some HTML depending on if the user is logged in.
public function buildLoggedInMessage() {
if ($this->User->isLoggedIn()) {
return ' You are logged in as <strong>'.$this->User->getUsername().'</strong> (logout)';
} else {
return ' Login';
}
}
My initial thought was to place this function in my "controller" because it asks the User model if they are logged in (which checks the database record), however it "builds" some HTML, so maybe it should be in the view. Should I move it?
I will eventually move the HTML from the function into a template, so ignore the inline HTML.
Would the function be more suitable in the view if it was like this:
public function buildLoggedInMessage() {
if ($this->Controller->isLoggedIn()) {
return ' You are logged in as <strong>'.$this->User->getUsername().'</strong> (logout)';
} else {
return ' Login';
}
}
and the controller asks the model if the user is logged in?
Thanks.
I think view should not contain any business logic. Views should focus on presenting stuff, so your second solution is bad practice.
More than that, since views focus on the presentation and models handle most of the business logic, controllers should do only the necessary things to link views and models, which means fetch data from model and just insert the data into the view.
so this line of code make no sense because it means you implement business logic in controller:
$this->Controller->isLoggedIn()
Now let's see your first solution.
public function buildLoggedInMessage() {
if ($this->User->isLoggedIn()) {
return ' You are logged in as <strong>'.$this->User->getUsername().'</strong> (logout)';
} else {
return ' Login';
}
}
This function 'return' htmls rather than 'echo' htmls. So who is calling this function? and who will 'echo' the string from this function? I would say this is not a complete controller.
In modern web MVC, there's always some kind of 'router' handle the http requests and execute some instructions related to that. Since you wanna implement MVC pattern, you need to implement that 'router' first.
For example, you can create a 'Member' class which has a 'check' method to achieve the functionality you want.
class Member{
public function check() {
if ($this->User->isLoggedIn()) {
echo ' You are logged in as <strong>'.$this->User->getUsername().'</strong> (logout)';
} else {
echo ' Login';
}
}
}
And you need to implement the router class to handle http requests like 'http://myweb.com/member/check'.
The router code would be something like this:
$url_segments = explode('/', $_SERVER['REQUEST_URI']);
if (count($url_segments) == 4){
$controller_name = $url_segments[2];
$method_name = $url_segments[3];
}
else if (count($url_segments) == 3){
$controller_name = $url_segments[2];
$method_name = $this->default_method;
}
else if (count($url_segments) == 2){
$controller_name = $this->default_controller;
$method_name = $this->default_method;
}
$this->current_controller = $controller_name;
$this->current_method = $method_name;
require BASEPATH . '/controller/' . $controller_name . '.php';
$class_name = ucfirst($controller_name);
$controller = new $class_name($method_name);
call_user_func( array( $controller, $method_name ) );
Create a MVC framework is not an easy work.
I create a simple MVC framework for educational purpose.
https://github.com/howtomakeaturn/PigFramework
Check the index.php file, and you will know what I mean router and controller.
I don't think that the point of MVC is to put HTML in a controller, if I were you I'd send some data back and make an if else statement in my view based on the send data. To make good use of an MVC you first need to understand what it is or does, so I'd recommend searching for a tutorial.
put this function in the controller from where you are calling a login function after if a user authenticated then it will set the session or flash data i.e $this->session->set_flashdata('success', 'you are loged in as $username');
else
redirect('login');