CakePHP 2 JWT Auth Plugin not receiving header in CakeRequest - cakephp

I am using the CakePHP plugin (https://github.com/t73biz/cakephp2-jwt-auth). My CakePHP app is version 2.6.2. I have added this to my Auth Component in the AppController.
'JwtAuth.JwtToken' => array(
'fields' => array(
'username' => 'email',
'password' => 'password',
'token' => '_token'
),
'parameter' => '_token',
'contain' => array(
'Organization'
),
'scope' => array(
'User.status' => 'A',
//'User.frozen' => 0,
'User.locked_out' => 0,
'Organization.status' => 'A',
//'User.failed_sign_ins < 4'
),
'header' => 'X_JSON_WEB_TOKEN',
'pepper' => 'pepper' // Says pepper because I do not want to show the pepper key I used for my code
),
I know that the plugin runs because I add a die statement in the getUser function in the plugin and it shows up when I do the API request.
public function getUser(CakeRequest $request) {
$token = $this->_getToken($request);
if ($token) {
return $this->_findUser($token);
}
return false;
}
This is the function that is part of the JwtTokenAuthenticate.php in the Component directory in the Controller directory of the plugin. When I debug $request, I do not get the header as part of the request. I am using Postman for testing the API and Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7ImlkIjoiMTIiLCJzdWIiOiIxMiJ9LCJpYXQiOjE0ODcyNTUxMjYsImV4cCI6MTQ4NzI1ODcyNn0.5hoyXltPmEXIA3eVtJnnn3Dor2lhviej31eZNbaMbow

If I understand you correctly you're trying to pass auth token via Authorization header? But according to the plugin docs you should be doing it either via X_JSON_WEB_TOKEN header or _token query param.

Please add below code inside your .htaccess file, it will work
<IfModule mod_rewrite.c>
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
</IfModule>

Related

Cakephp 3 HTTP Basic Authentication login issue

I am using basic authentication in my project to access Api. In ApiController, I added below code in beforeFilter:
$this->Auth->config('authenticate', [
'Basic' => [
'fields' => ['username' => 'username', 'password' => 'api_key'],
'userModel' => 'Users'
]
]);
So from chrome postman application, I am sending post request with basic auth credentials. for example like below:
So when I send a request, I get unauthorized error back.
you are sending a post request with a 'password' field
Your application is expecting a 'api_key' field that would contain the password.
I think you missed this one script in your model entity.
use Cake\Auth\DefaultPasswordHasher;
protected function _setPassword($password)
{
if (strlen($password) > 0) {
return (new DefaultPasswordHasher)->hash($password);
}
}
Put this one in Model/Entity/User.php

Cakephp v3.0.5 use different model in Component Auth

I read all the cakephp component Auth documentation in http://book.cakephp.org/3.0/en/controllers/components/authentication.html but I cant find a solution :-(
I'm trying to use different model called "Usuarios" in component Auth and change the field "username" by "cedula". This is my configuration in AppController.php:
public function initialize() {
parent::initialize();
$this->loadComponent('Flash');
$this->loadComponent('Auth');
$this->Auth->config('authenticate', [
'Basic' => [
'userModel' => 'Usuarios',
'fields' => [
'username' => 'cedula',
'password' => 'password']],
'Form' => ['userModel' => 'Usuarios',
'fields' => [
'username' => 'cedula',
'password' => 'password']]
]);
But nothing happend. No appear login form and session is open.
What i'm doing wrong?
Match the controller name to the template directory, and the method to the template.
If your controller is src/Controllers/Usuarios, method login(), then in src/Templates/Usuarios/ you need to have login.ctp as your view file.
If you have all that, it should work. By the way, if you are using 'password' as your password field, you don't need to specify that when you configure Auth; You only need to set 'username' => 'cedula' because you are changing the default.
Also, have you set anything in $this->Auth->allow() in the beforeFilter() method?

DC User Plugin: re-login with Cookie fails

I am using DC User Plugin with activated "RememberMe" Cookie. If the session is expired and I reload a public page, it works fine (it gets the cookie and renews the session).
But if I reload a page (after session has expired) which is only allowed for logged-in users, it does not check the cookie and redirects me instead to the login page. But if I then click another (public) page and then go back to the user-only page - it works, too, without to have to login again.
So the RememberMe/Cookie Component itself seems to work fine.
My Code for the Auth check for the problematic user-only page is simple:
public function view() {
if (!$this->Auth->user()) {
$this->redirect('/users/login');
} else {
//do stuff
}
}
What do I have to add/change, so that it checks the User Cookie here, too, when the Session is expired? In the documentation of that Plugin I couldn't find that unfortunately.
Thank you so much for your help and sorry for my bad English.
Well I resolved by myself. Allthough I had added
$this->RememberMe->restoreLoginFromCookie();
to beforeFilter() function in Controller, the function always returned false, because the Cookie saves email+password, but Standard Auth expects username+password.
I added
public $components = array(
...
'Auth' => array(
'authenticate' => array(
'Form' => array(
'userModel' => 'User',
'fields' => array(
'username' => 'email',
'password' => 'password'
)
)
),
...
so it will check for the needed email field, and now it works.

Enabling CORS in laravel using barryvdh/laravel-cors package?

I am working on a simple Angular application and I wish to have my back end data from an API I created myself in Laravel. The API is sending back data just fine. But since I am developing my Angular application separately, I have an error when I use a service in Angular to fetch my resource.
Error
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8001/airports. This can be fixed by moving the resource to the same domain or enabling CORS.
So now I have installed a package in Laravel which is supposed to solve the issue but I am not sure how to use it. The cofig file of the package looks like:
'defaults' => array(
'supportsCredentials' => false,
'allowedOrigins' => array(),
'allowedHeaders' => array(),
'allowedMethods' => array(),
'exposedHeaders' => array(),
'maxAge' => 0,
'hosts' => array(),
),
'paths' => array(
'api/*' => array(
'allowedOrigins' => array('*'),
'allowedHeaders' => array('*'),
'allowedMethods' => array('*'),
'maxAge' => 3600,
),
'*' => array(
'allowedOrigins' => array('*'),
'allowedHeaders' => array('Content-Type'),
'allowedMethods' => array('POST', 'PUT', 'GET', 'DELETE'),
'maxAge' => 3600,
'hosts' => array('api.*'),
),
),
I am still getting the same error. Now what is it that I have to different in order to allow CORS?
Note: I have WAMP installed. I am developing both my Angular application and Laravel API on the same local server.
I ran into something similar with EmberJS instead of Angular. Laravel setup looks correct but I think you need to enable CORS support in Angular.
From a Chrome developer tutorial:
A word on Content Security Policy
Unlike many other JS MVC frameworks,
Angular v1.1.0+ requires no tweaks to work within a strict CSP. It
just works, out of the box!
However, if you're using an older version of Angular between v1.0.1
and v1.1.0, you'll need tell Angular to run in a "content security
mode". This is done by including the ngCsp directive alongside ngApp:
<html data-ng-app data-ng-csp>
You can find the whole article here.

How to connect a post rest request to the add controller action using prefixes in cakephp

I code a client/server application.
Server side is powered by CakePHP 2.4.7.
Client side run with angularjs and cordova on mobile devices
I use several cakephp route prefixes whose 'admin' and 'mobile'.
(And I use $resource and $httpInterceptor angularjs factories to setup my REST requests.)
I want to call /website/mobile/posts/add.json with json data posting.
So I call /website/mobile/posts.json with a POST ajax query:
The problem is here: the called controller action is 'index', not 'add';
On top of my PostsController, I added this:
echo $this->request->params['action'] . "\n";
echo ($this->request->isPost())? "post" . "\n" : "not post";
die;
and the response is always:
mobile_index
post
So the ajax request seems correct but cakephp don't map it to the add action, but index one.
However my configuration seems good too; here is a fragment of my routes.php
Router::mapResources(array('users','posts'));
Router::parseExtensions('json');
Any idea ?
Prefix routing doesn't work with REST routing out of the box
REST routing works by automatically creating routes for the controllers passed to Router::mapResources(). Prefix routing pretty much does the same, it creates default routes including the prefixes defined in Routing.prefixes.
However both functionalities don't know about each other, they both create separte routes, so Router::mapResources() will connect to URLs without prefixes (the prefix option for this method is not using actual prefix routing, it will just add the value of that option to the beginning of the URL to connect to!), and therefore your request to /mobile/... doesn't actually use REST routing but only prefix routing.
Defining prefixed REST routes manually
There is no simple fix for this problem like using an option or something, instead you'll have to define the REST routes manually so that the prefix option is included, simple enough though.
See Modifying the default REST routes and Custom REST Routing.
A sample Route could look like this:
Router::connect(
'/mobile/users',
array(
'prefix' => 'mobile',
'mobile' => true,
'controller' => 'users',
'action' => 'add',
'[method]' => 'POST'
)
);
This would connect POST requests to /mobile/users to UsersController::mobile_add(). Similary you'll have to do this for all other methods like GET and PUT, with and without passing an id, etc.
Note that when connecting manually you can ditch the Routing.prefixes option and of course the call to Router::mapResources().
Automated mapping
Defining all those routes by hand is kinda exhausting, you're better of automating it with respect to the Router::resourceMap() configuration.
Here's an example on how to do that, it's somewhat similar to Router::mapResources(), but it accepts a prefix option that actually makes use of prefix routing:
function mapResources(array $controllers) {
$resourceMap = Router::resourceMap();
foreach($controllers as $controller => $options) {
if(!is_array($options)) {
$controller = $options;
$options = array();
}
$options += array(
'prefix' => null,
'plugin' => null,
'id' => Router::ID . '|' . Router::UUID
);
foreach($resourceMap as $params) {
$url = '';
if($options['prefix']) {
$url .= '/' . $options['prefix'];
}
if($options['plugin']) {
$url .= '/' . $options['plugin'];
}
$url .= '/' . $controller;
if($params['id']) {
$url .= '/:id';
}
Router::connect(
$url,
array(
'prefix' => $options['prefix'],
$options['prefix'] => !!$options['prefix'],
'plugin' => $options['plugin'],
'controller' => $controller,
'action' => $params['action'],
'[method]' => $params['method']
),
array(
'id' => $options['id'],
'pass' => array('id')
)
);
}
}
}
You would call it like this:
mapResources(array(
'books' => array(
'prefix' => 'mobile'
)
));
and it would map all the REST routes for your books controller using the mobile prefix.

Resources