Hi!
i upgraded my cakephp instance from 3.9 to 4.1 with the migration guide and switched from admad/cakephp-jwt-auth to this new solution.
issue
my cake app is basically my backend for a nuxtjs frontend and there the magic happens.
creating a user via json works fine on postman and frondend.
logging in the new user just works on postman - not on frontend.
using the fetched token to authentitfy actions works on boths ways.
api resonses
postman
http post request with credentials email & password
{
"success": true,
"status": "SUCCESS",
"errors": [],
"data": {
"email": "other@example.org",
"password": "password"
},
"result_data": {
"id": 3014,
"name": "TestUser",
"email": "other@example.org",
...
},
"message": "Welcome back!",
"payload": {
"sub": 3014,
"exp": 1598778817
},
"token": "eyJ0eXAiOiJKV1QiLCJhbG...Dt7h6NB5Gc"
}
nuxtjs frontend
http post request with credentials email & password
{
"success": false,
"status": "FAILURE_CREDENTIALS_INVALID",
"errors": [],
"data": {
"email": "other@example.org",
"password": "password"
},
"result_data": null,
"message": "Login failed! Check email or password.\n",
"payload": false
}
code fragments
application.php
public function middleware($middlewareQueue): MiddlewareQueue
{
$middlewareQueue
->add(new ErrorHandlerMiddleware(Configure::read('Error')))
->add(new AssetMiddleware([
'cacheTime' => Configure::read('Asset.cacheTime')
]))
->add(new CorsMiddleware([
'origin' => ['*'],
'methods' => ['GET', 'POST', 'PATCH', 'DELETE', 'OPTIONS'],
'headers.allow' => ['Authorization', 'Content-Type', 'Api-token'],
'headers.expose' => ['X-Auth-token'],
'credentials' => true,
'cache' => 0
]))
->add(new RoutingMiddleware($this))
// add Authentication after RoutingMiddleware
->add(new AuthenticationMiddleware($this))
->add(new BodyParserMiddleware())
;
return $middlewareQueue;
}
public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
{
$authenticationService = new AuthenticationService(
);
// Load identifiers, ensure we check email and password fields
$authenticationService->loadIdentifier('Authentication.Password', [
'fields' => [
'username' => 'email',
'password' => 'password',
],
'passwordHasher' => [
'className' => 'Authentication.Fallback',
'hashers' => [
'Authentication.Default',
[
'className' => 'Authentication.Legacy',
'hashType' => 'md5',
'salt' => false // turn off default usage of salt
],
]
]
]);
$authenticationService->loadIdentifier('Authentication.JwtSubject');
$authenticationService->loadAuthenticator('Authentication.Jwt', [
'secretKey' => file_get_contents(CONFIG . 'jwt/jwt.pem'),
'algorithms' => ['RS256'],
'returnPayload' => false
]);
$authenticationService->loadAuthenticator('Authentication.Form', [
'fields' => [
'username' => 'email',
'password' => 'password',
],
]);
return $authenticationService;
}
routes.php
Router::prefix('api', function (RouteBuilder $builder) {
$builder->setExtensions(['json']);
$builder->fallbacks(DashedRoute::class);
$builder->registerMiddleware('bodyparser', \Cake\Http\Middleware\BodyParserMiddleware::class);
$builder->applyMiddleware('bodyparser');
});
user controller
with a lot of debugging code
public function login ()
{
$user = false;
$token = "";
$success = false;
$message = __('Login failed! Check email or password.');
$authentication = $this->request->getAttribute('authentication');
// $result = $authentication->getResult();
$result = $this->Authentication->getResult();
$status = $result->getStatus();
$errors = $result->getErrors();
$payload = false;
$data = $this->request->getData();
$result_data = $result->getData();
if ($this->request->is('post')) {
if ($result->isValid()) {
// redirect to /articles after login success
if ($authentication->identifiers()->get('Password')->needsPasswordRehash()) {
// Rehash happens on save.
$authUser = $this->Authentication->getIdentity();
$user = $this->Users->get($authUser['id']);
$user->password = $this->request->getData('password');
$this->Users->save($user);
}
$privateKey = file_get_contents(CONFIG . '/jwt/jwt.key');
$user = $result->getData();
$payload = [
'sub' => $user['id'],
'exp' => time() + (60 * 24 * 365),
];
$token = JWT::encode($payload, $privateKey, 'RS256');
$message = __('Welcome back!');
$success = true;
$this->set([
'token' => $token
]);
} else {
$message = __('Login failed! Check email or password.') . "\n";
$message .= implode(',', $errors);
$token = false;
$this->response->withStatus(401);
// throw new UnauthenticatedException();
}
}
$this->set([
'success' => $success,
'status' => $status,
'errors' => $errors,
'data' => $data,
'result_data' => $result_data,
'message' => $message,
'payload' => $payload,
'_serialize' => true
]);
}