I try to protect my restAPI with credentials and reading about basic-auth laravel I try to implement a basic authentication sytem
User tabel already exists and populated with data
in filter.php I set
Route::filter('auth.basic', function() {
return Auth::basic(); });
than in api Route
// =============================================
// API ROUTES ==================================
// =============================================
Route::group(array('prefix' => 'api', 'before' => 'auth.basic'), function() {
Route::resource('products', 'ProductController', array('only' => array('index', 'store', 'destroy', 'update', 'show', 'edit')));
Route::get('products/{id}', 'ProductController#get', array('only' => array('show')));
});
the controller is quite simple
<?php
use App\Models\Product;
class ProductController extends \BaseController {
private $model;
function __construct() {
$this->model = new Product();
}
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index() {
$model = new Product();
$page = Input::get('pageNumber');
$limit = Input::get('pageNumber');
$ram = Input::get('limit');
$cpu = Input::get('cpu');
$price_range = Input::get('price_range');
$keyword = Input::get('keyword');
return Response::json($model->getProducts($page));
}
/**
* Store a newly created resource in storage.
*
* #return Response
*/
public function store() {
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return Response
*/
public function destroy($id) {
}
public function get($id) {
$model = new Product();
return Response::json($model->getProduct($id));
}
public function show($id) {
return Response::json($this->model->getProduct($id));
}
public function update($id) {
return Response::json($this->model->getProduct($id));
}
public function pause($id) {
var_dump('pause');
}
public function create(){
}
public function edit(){
var_dump('test_edit');
}
}
calling domain.com/api/products pop up login window. populating fields and submit datas can't log in
How do I check Users credentials?
For backend I use Sentry and it's working
filter.php
Route::filter('auth.admin', function() {
if (!Sentry::check()) {
return Redirect::route('admin.login');
}
});
Route
Route::get('admin/login', array('as' => 'admin.login', 'uses'
=> 'App\Controllers\Admin\AuthController#getLogin'));
Controller
<?php namespace App\Controllers\Admin;
use Auth, BaseController, Form, Input, Redirect, Sentry, View;
class AuthController extends BaseController {
/**
* Display the login page
* #return View
*/
public function getLogin()
{
return View::make('admin.auth.login');
}
/**
* Login action
* #return Redirect
*/
public function postLogin()
{
$credentials = array(
'email' => Input::get('email'),
'password' => Input::get('password')
);
try
{
$user = Sentry::authenticate($credentials, false);
if ($user)
{
return Redirect::route('admin.pages.index');
}
}
catch(\Exception $e)
{
return Redirect::route('admin.login')->withErrors(array('login' => $e->getMessage()));
}
}
/**
* Logout action
* #return Redirect
*/
public function getLogout()
{
Sentry::logout();
return Redirect::route('admin.login');
}
}
It seems that you don't have a login function defined.
by the way, you should change:
Route::group(array('prefix' => 'api', 'before' => 'auth.basic'), function() {
Route::resource('products', 'ProductController', array('only' => array('index', 'store', 'destroy', 'update', 'show', 'edit')));
Route::get('products/{id}', 'ProductController#get', array('only' => array('show')));
});
to:
Route::group(array('prefix' => 'api', 'before' => 'auth.basic'), function(){
Route::get('products/{id}', 'ProductController#get'));
Route::resource('products', 'ProductController', array('except' => array('show')));
});
Related
I have tried to implement JWT based authentication in my CakePHP 4 application. Token is successfully generated and I have verified it on jwt.io as well. But while doing request for the route which should validate token it's giving following error "Authentication is required to continue".
While investigation the issue I the dd($this->Authentication); in the Controller's initialize function I see following reason In the object. "Signature verification failed" response.
Any help in this case?
Thanks,
Following is my code
routes.php
web related routes....
here are API related routes.
$routes->prefix('api', ['path' => '/api'], function ($routes) {
$routes->setExtensions(['json']);
// $routes->resources('register');
$routes->post('/user/add', ['controller' => 'User', 'action' => 'add']);
$routes->post('/user/login', ['controller' => 'User', 'action' => 'login']);
$routes->post('/user/index', ['controller' => 'User', 'action' => 'index']);
$routes->get('/user/logout', ['controller' => 'User', 'action' => 'logout']);
$routes->fallbacks(DashedRoute::class);
});
src/Application.php code
<?php
declare(strict_types=1);
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* #copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* #link https://cakephp.org CakePHP(tm) Project
* #since 3.3.0
* #license https://opensource.org/licenses/mit-license.php MIT License
*/
namespace App;
use Cake\Core\Configure;
use Cake\Core\ContainerInterface;
use Cake\Core\Exception\MissingPluginException;
use Cake\Datasource\FactoryLocator;
use Cake\Error\Middleware\ErrorHandlerMiddleware;
use Cake\Http\BaseApplication;
use Cake\Http\Middleware\BodyParserMiddleware;
use Cake\Http\Middleware\CsrfProtectionMiddleware;
use Cake\Http\MiddlewareQueue;
use Cake\ORM\Locator\TableLocator;
use Cake\Routing\Middleware\AssetMiddleware;
use Cake\Routing\Middleware\RoutingMiddleware;
use Authentication\AuthenticationService;
use Authentication\AuthenticationServiceInterface;
use Authentication\AuthenticationServiceProviderInterface;
use Authentication\Identifier\IdentifierInterface;
use Authentication\Middleware\AuthenticationMiddleware;
// use Cake\Http\MiddlewareQueue;
use Cake\Routing\Router;
use Psr\Http\Message\ServerRequestInterface;
/**
* Application setup class.
*
* This defines the bootstrapping logic and middleware layers you
* want to use in your application.
*/
class Application extends BaseApplication implements AuthenticationServiceProviderInterface
{
/**
* Load all the application configuration and bootstrap logic.
*
* #return void
*/
public function bootstrap(): void
{
$this->addPlugin('Migrations');
// Call parent to load bootstrap from files.
parent::bootstrap();
if (PHP_SAPI === 'cli') {
$this->bootstrapCli();
} else {
FactoryLocator::add(
'Table',
(new TableLocator())->allowFallbackClass(false)
);
}
/*
* Only try to load DebugKit in development mode
* Debug Kit should not be installed on a production system
*/
if (\Cake\Core\Configure::read('debug')) {
$this->addPlugin('DebugKit');
}
$this->addPlugin('Authentication');
// Load more plugins here
}
/**
* Setup the middleware queue your application will use.
*
* #param \Cake\Http\MiddlewareQueue $middlewareQueue The middleware queue to setup.
* #return \Cake\Http\MiddlewareQueue The updated middleware queue.
*/
public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
{
$csrf = new CsrfProtectionMiddleware(['httponly' => true]);
// Token check will be skipped when callback returns `true`.
$csrf->skipCheckCallback(function ($request) {
// Skip token check for API URLs.
// return $request->getPath() == '/dwolla_webhook';
return $request->getPath() == '/dwolla_webhook' || $request->getParam('prefix') == 'Api';
});
$middlewareQueue
// Catch any exceptions in the lower layers,
// and make an error page/response
->add(new ErrorHandlerMiddleware(\Cake\Core\Configure::read('Error')))
// Handle plugin/theme assets like CakePHP normally does.
->add(new AssetMiddleware([
'cacheTime' => \Cake\Core\Configure::read('Asset.cacheTime'),
]))
// ->add(function (
// \Psr\Http\Message\ServerRequestInterface $request,
// \Psr\Http\Server\RequestHandlerInterface $handler
// ) {
// try {
// // continue with the next middleware
// return $handler->handle($request);
// } catch (\Cake\Http\Exception\InvalidCsrfTokenException $exception) {
// // handle the catched exception
// $response = new \Cake\Http\Response();
// return $response->withStringBody('Oh noes, CSRF error!');
// }
// })
// Add routing middleware.
// If you have a large number of routes connected, turning on routes
// caching in production could improve performance. For that when
// creating the middleware instance specify the cache config name by
// using it's second constructor argument:
// `new RoutingMiddleware($this, '_cake_routes_')`
->add(new RoutingMiddleware($this))
// Parse various types of encoded request bodies so that they are
// available as array through $request->getData()
// https://book.cakephp.org/4/en/controllers/middleware.html#body-parser-middleware
->add(new BodyParserMiddleware())
// Cross Site Request Forgery (CSRF) Protection Middleware
// https://book.cakephp.org/4/en/controllers/middleware.html#cross-site-request-forgery-csrf-middleware
// ->add(new CsrfProtectionMiddleware([
// 'httponly' => true,
// ]));
->add($csrf)
->add(new AuthenticationMiddleware($this));
return $middlewareQueue;
}
/**
* Returns a service provider instance.
*
* #param \Psr\Http\Message\ServerRequestInterface $request Request
* #return \Authentication\AuthenticationServiceInterface
*/
public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
{
$service = new AuthenticationService();
// Load identifiers
$service->loadIdentifier('Authentication.Password', [
'fields' => [
'username' => 'username',
'password' => 'password',
],
// 'algorithm' => 'HS256',
'resolver' => [
'className' => 'Authentication.Orm',
// 'finder' => 'active',
'userModel' => 'User',
],
]);
// Load the authenticators
$service->loadAuthenticator('Authentication.Form', [
'fields' => [
'username' => 'username',
'password' => 'password',
],
'returnPayload' => false,
// 'loginUrl' => '/users/token.json'
]);
$service->loadAuthenticator('Authentication.Jwt', [
'secretKey' => file_get_contents(CONFIG . '/jwt.pem'),
'header' => 'Authorization',
// 'queryParam' => 'token',
'tokenPrefix' => 'Bearer',
'algorithm' => 'HS256',
'returnPayload' => false,
]);
$service->loadIdentifier('Authentication.JwtSubject', [
// 'tokenField' => 'id',
// 'dataField' => 'id',
'algorithm' => 'HS256',
]);
// Configure the service. (see below for more details)
return $service;
}
/**
* Register application container services.
*
* #param \Cake\Core\ContainerInterface $container The Container to update.
* #return void
* #link https://book.cakephp.org/4/en/development/dependency-injection.html#dependency-injection
*/
public function services(ContainerInterface $container): void
{
}
/**
* Bootstrapping for CLI application.
*
* That is when running commands.
*
* #return void
*/
protected function bootstrapCli(): void
{
try {
$this->addPlugin('Bake');
} catch (MissingPluginException $e) {
// Do not halt if the plugin is missing
}
$this->addPlugin('Migrations');
// Load more plugins here
}
}
APIController code
<?php
namespace App\Controller;
use Cake\Controller\Controller;
use Cake\Event\EventInterface;
class ApiController extends Controller
{
public function initialize(): void
{
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Authentication.Authentication');
}
private function setCorsHeaders()
{
$this->response = $this->response->cors($this->request)
->allowOrigin(['*'])
->allowMethods(['*'])
->allowHeaders(['x-xsrf-token', 'Origin', 'Content-Type', 'X-Auth-Token', 'Access-Control-Allow-Headers', 'Authorization', 'HTTP_Authorization', 'X-Requested-With'])
->allowCredentials(['true'])
->exposeHeaders(['Link'])
->maxAge(300)
->build();
}
public function beforeRender(EventInterface $event)
{
// .......
$this->setCorsHeaders();
}
public function beforeFilter(EventInterface $event)
{
// ......
if ($this->request->is('OPTIONS')) {
$this->setCorsHeaders();
return $this->response;
}
}
}
UserController code
<?php
namespace App\Controller\Api;
use Cake\View\JsonView;
use Firebase\JWT\JWT;
use App\Controller\ApiController;
use Lib\PpState\PpState;
class UserController extends ApiController
{
// public function viewClasses(): array
// {
// return [JsonView::class];
// }
public function initialize(): void
{
parent::initialize();
$this->loadModel('User');
// var_dump(debug_backtrace());
// dd($_SERVER['HTTP_AUTHORIZATION']);
dd($this->Authentication);
$this->Authentication->allowUnauthenticated(['login', 'add']);
// dd('hhesssssheh');
}
public function index()
{
// dd('ashsh');
$this->Authentication->logout();
// dd($this->Authentication->getResult());
// dd($this->Authentication);
$json = [
'success' => true,
'message' => 'welcome',
];
$this->set(compact('json'));
$this->viewBuilder()->setOption('serialize', 'json');
}
public function logout()
{
// JWT::destroy();
// $decoded = JWT::decode($jwt, new Key($key, 'HS256'));
// dd($decoded);
// dd($this->request);
//
// $result = $this->Authentication->getResult();
// dd($result);
// $json = ['route' => 'logout'];
// if ($result->isValid()) {
// $this->Authentication->logout();
// // $this->set('user', [
// // 'message' => 'You are successfully logout'
// // ]);
// $json = ['message' => 'You are successfully logout'];
// }
$json = [
'success' => true,
'message' => 'You are successfully logout',
];
$this->set(compact('json'));
$this->viewBuilder()->setOption('serialize', 'json');
// $this->viewBuilder->setOption('serialize', 'user');
// $this->set(compact('json'));
// $this->viewBuilder()->setOption('serialize', 'json');
// If the user is logged in send them away.
// if ($result->isValid()) {
// $target = $this->Authentication->getLoginRedirect() ?? '/home';
// return $this->redirect($target);
// }
// if ($this->request->is('post')) {
// $this->Flash->error('Invalid username or password');
// }
}
public function add()
{
if ($this->User->emailInUse($this->request->getData('username'))) {
$json = [
'success' => false,
'message' => 'User email already exists, Please choose different email',
];
} else {
$user = $this->User->newEntity($this->request->getData());
$newUser = $this->User->save($user);
if (!empty($newUser->id)) {
$privateKey = file_get_contents(CONFIG . '/jwt.key');
$payload = [
'iss' => 'myapp',
'sub' => $newUser->id,
'iat' => time(),
'exp' => time() + 300,
];
if (!in_array($this->request->getData('st'), PpState::getActiveStateAbbreviations())) {
$json = [
'success' => false,
'message' => 'Oh, bother! Poppins Payroll does not yet operate in your state. We’ve made note of your location, so we know where we’re needed. We look forward to being able to serve you soon.',
];
} else {
$json = [
'success' => true,
'token' => JWT::encode($payload, $privateKey, 'HS256'),
];
}
} else {
$json = [
'success' => false,
'message' => 'Issue in user registration',
];
}
}
$this->set(compact('json'));
$this->viewBuilder()->setOption('serialize', 'json');
}
public function login()
{
$result = $this->Authentication->getResult();
if ($result->isValid()) {
$privateKey = file_get_contents(CONFIG . '/jwt.key');
$user = $result->getData();
$payload = [
'iss' => 'myapp',
'sub' => $user->id,
'iat' => time(),
'exp' => time() + 60,
];
$json = [
'success' => true,
'token' => JWT::encode($payload, $privateKey, 'HS256'),
];
} else {
$this->response = $this->response->withStatus(401);
$json = [];
}
$this->set(compact('json'));
$this->viewBuilder()->setOption('serialize', 'json');
}
}
Postman API calls
I am looking for CakePHP 4 Authorization issue to solve while implementing JWT token bases APIs
The problem is the order in which you load the authenticator in your Application.php.
You should load your Jwt first and then the Form authenticator.
$service->loadAuthenticator('Authentication.Jwt', [
'secretKey' => Security::getSalt(),
'returnPayload' => false
]);
$service->loadAuthenticator('Authentication.Form', [
'fields' => $fields,
'loginUrl' => '/users/login'
]);
I have three tables named users, products and projects.
products and projects have one too many relationships
products have id this id belongs to many projects
This is my products.php table
Schema::create('products', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->text('detail');
$table->string('color');
$table->string('image');
$table->string('logo');
$table->unsignedBigInteger('user_id');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
This is projects.php thable
Schema::create('projects', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('chapter_name', 255)->nullable();
$table->string('sub_section_name', 500)->nullable();
$table->string('title_1', 255)->nullable();
$table->string('description_1', 5000)->nullable();
$table->string('image_1', 255)->nullable();
$table->string('image_2', 255)->nullable();
$table->string('image_3', 255)->nullable();
$table->string('title_2', 255)->nullable();
$table->string('description_2', 5000)->nullable();
$table->string('title_3', 255)->nullable();
$table->string('description_3', 255)->nullable();
$table->string('video_1', 255)->nullable();
$table->string('video_2', 255)->nullable();
$table->string('video_3', 255)->nullable();
$table->unsignedBigInteger ('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
// $table->foreignId('product_id')->nullable();
$table->unsignedBigInteger('product_id')->references('id')->on('products')->onDelete('cascade');
$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->nullable();
});
Here in my ProjectImport.php I want call product_id = id of products table
This is my ProjectImport.php
public function model(array $row)
{
return new Project([
'chapter_name' => $row['chapter_name'],
'sub_section_name' => $row['sub_section_name'],
'title_1' => $row['title_1'],
'description_1' => $row['description_1'],
'image_1' => $row['image_1'],
'image_2' => $row['image_2'],
'image_3' => $row['image_3'],
'title_2' => $row['title_2'],
'description_2' => $row['description_2'],
'title_3' => $row['title_3'],
'description_3' => $row['description_3'],
'video_1' => $row['video_1'],
'video_2' => $row['video_2'],
'video_3' => $row['video_3'],
'user_id' => auth()->user()->id,
'product_id' => Product::where('user_id',Auth::id())->pluck('id') // Here i want product_id = product table id
// 'product_id' => id()->id
]);
}
The relationship is one to many and one to many. Here user have many products with id and every products can have many projects.
This is ProductController.php
<?php
namespace App\Http\Controllers;
use App\Models\Product;
use Illuminate\Http\Request;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
class ProductController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
// public function indexGetProducts(){
// return User::find(auth()->user()->id)->getProducts;
// }
public function index()
{
// $products = Product::latest()->paginate(20);
$products = Product::where('user_id',auth()->user()->id)->latest()->paginate(20);
return view('products.index',compact('products'))
->with('i', (request()->input('page', 1) - 1) * 5);
// $products= Product::where('user_id',auth()->user()->id)->orderby('created_at','desc')->get();
// return view('products.index',compact('products'))->with('i', (request()->input('page', 5) - 1) * 5);
}
function authapi(Request $request)
{
$user = User:: where('email', $request->email)->first();
if(!$user || !Hash::check($request->password, $user->password)){
return response([
'message' => ['These credentials do not match our records.']
],404);
}
$token = $user -> createToken('my-app-token')->plainTextToken;
$response = [
'user' => $user,
'token' => $token
];
return response($response,201);
}
function all_app_jsons(){
// return Product::all();
return User::find(auth()->user()->id)->getProducts;
}
function search_by_name($name){
return Product::where('name','like','%'.$name.'%')->get();
}
function search_by_id($id){
return Product::where('id',$id)->
where('user_id',auth()->user()->id)->get();
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
return view('products.create');
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//$tag = Product::create($request->all());
//return redirect()->route('admin.tags.index');
$request->validate([
'name' => 'required',
'detail' => 'required',
'color' => 'required',
'image' => 'required|image|mimes:png,jpg,jpeg|dimensions:width=1080,height=1920|max:2048',
'logo' => 'required|image|mimes:png,jpg,jpeg|dimensions:width=512,height=512|max:1024',
]);
$input = $request->all();
// $request->validated();
$input['user_id'] = auth()->user()->id;
if ($image = $request->file('image')) {
$destinationPath = 'image/';
$profileImage = date('YmdHis') . "." . $image->getClientOriginalExtension();
$image->move($destinationPath, $profileImage);
$input['image'] = "$profileImage";
}
if ($logo = $request->file('logo')) {
$destinationPath = 'logo/';
$profileLogo = date('YmdHis') . "." . $logo->getClientOriginalExtension();
$logo->move($destinationPath, $profileLogo);
$input['logo'] = "$profileLogo";
}
Product::create($input);
return redirect()->route('projects.index')
->with('success','Product created successfully.');
}
/**
* Display the specified resource.
*
* #param \App\Product $product
* #return \Illuminate\Http\Response
*/
public function show(Product $product)
{
return view('products.show',compact('product'));
}
/**
* Show the form for editing the specified resource.
*
* #param \App\Product $product
* #return \Illuminate\Http\Response
*/
public function edit(Product $product)
{
return view('products.edit',compact('product'));
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param \App\Product $product
* #return \Illuminate\Http\Response
*/
// public function update(Request $request, Product $product)
public function update(Request $request, $product_id)
{
$user_id = Auth::user()->id ;
$request->validate([
'name' => 'required',
'detail' => 'required',
'color' => 'required',
]);
$input = $request->all();
if ($image = $request->file('image')) {
$destinationPath = 'image/';
$profileImage = date('YmdHis') . "." . $image->getClientOriginalExtension();
$image->move($destinationPath, $profileImage);
$input['image'] = "$profileImage";
}else{
unset($input['image']);
}
if ($logo = $request->file('logo')) {
$destinationPath = 'logo/';
$profileLogo = date('YmdHis') . "." . $logo->getClientOriginalExtension();
$logo->move($destinationPath, $profileLogo);
$input['logo'] = "$profileLogo";
}else{
unset($input['logo']);
}
$product_id->update($input);
return redirect()->route('products.index')
->with('success','Product updated successfully');
}
/**
* Remove the specified resource from storage.
*
* #param \App\Product $product
* #return \Illuminate\Http\Response
*/
public function destroy(Product $product)
{
$product->delete();
return redirect()->route('products.index')
->with('success','Product deleted successfully');
}
// function indextwo(){
// //return DB::select("select * from products");
// //DB::table('products')->orderBy('id','desc')->first();
// return Product::orderBy('id', 'DESC')->first();
// }
}
This is ProjectController.php
<?php
namespace App\Http\Controllers;
use App\Exports\UsersExport;
use App\Models\Project;
use App\Imports\ProjectsImport;
use App\Models\Product;
use Maatwebsite\Excel\Facades\Excel;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class ProjectController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
// $projects = Project::where('user_id',auth()->user()->id)->latest()->paginate(20);
// $projects = Project::where('user_id',auth()->user()->id)->where('product_id')->latest()->paginate(20);
// $projects = Project::where('user_id',auth()->user()->id)->latest('product_id',8) ->paginate(20);
// $projects = Project::whereIn('product_id',Product::where('user_id',Auth::id())->pluck('id')->toArray())->latest();
// $projects = Project::whereIn('product_id',Product::where('user_id',Auth::id())->pluck('id')->toArray())->latest()->paginate(20);
$projects = Project::whereIn('product_id',Product::where('user_id',Auth::id())->pluck('id')->toArray())->latest()->paginate(20);
return view('projects.index', compact('projects'))
->with('i', (request()->input('page', 1) - 1) * 5);
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
return view('projects.create');
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$request->validate([
'chapter_name' => 'required',
'sub_section_name' => 'required',
'title_1' => 'required',
'description_1' => 'required',
'image_1' => 'required',
'image_2' => 'required',
'image_3' => 'required',
'title_2' => 'required',
'description_2' => 'required',
'title_3' => 'required',
'description_3' => 'required',
'video_1' => 'required',
'video_2' => 'required',
'video_3' => 'required',
]);
// $input = $request->all();
// $input['user_id'] = auth()->user()->id;
// $input['product_id'] = $id;
$input = Project::whereIn('product_id',Product::where('user_id',Auth::id())->pluck('id'));
Project::create($input);
return redirect()->route('project.index')
->with('success','Product created successfully.');
}
/**
* Display the specified resource.
*
* #param \App\Models\Project $project
* #return \Illuminate\Http\Response
*/
public function show(Project $project)
{
// $category = $project->category;
return view('projects.show', compact('project'));
}
/**
* Show the form for editing the specified resource.
*
* #param \App\Models\Project $project
* #return \Illuminate\Http\Response
*/
public function edit(Project $project)
{
return view('projects.edit', compact('project'));
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param \App\Models\Project $project
* #return \Illuminate\Http\Response
*/
public function update(Request $request, Project $project)
{
// $user_id = Auth::user()->id ;
$request->validate([
'chapter_name' => 'required',
'sub_section_name' => 'required',
'title_1' => 'required',
'description_1' => 'required',
'image_1' => 'required',
'image_2' => 'required',
'image_3' => 'required',
'title_2' => 'required',
'description_2' => 'required',
'title_3' => 'required',
'description_3' => 'required',
'video_1' => 'required',
'video_2' => 'required',
'video_3' => 'required',
]);
$input = $request->all();
$project->update($input);
return redirect()->route('project.index')
->with('success','Product updated successfully');
}
/**
* Remove the specified resource from storage.
*
* #param \App\Models\Project $project
* #return \Illuminate\Http\Response
*/
public function destroy(Project $project)
{
$project->delete();
return redirect()->route('projects.index')
->with('success', 'Project deleted successfully');
}
public function importProject()
{
Excel::import(new ProjectsImport, request()->file('file'));
return back()->with('success','Project created successfully.');
}
public function export()
{
return Excel::download(new UsersExport, 'projects.xlsx');
}
}
This is user Model user.php
class User extends Authenticatable
{
use HasApiTokens;
use HasFactory;
use HasProfilePhoto;
use Notifiable;
use TwoFactorAuthenticatable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
public function Products(){
return $this->hasMany('App\Models\Product');
}
public function Project(){
return $this->hasMany('App\Models\Project');
}
// public function products(){
// return $this->hasMany(Product::class);
// }
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password',
'remember_token',
'two_factor_recovery_codes',
'two_factor_secret',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
/**
* The accessors to append to the model's array form.
*
* #var array
*/
protected $appends = [
'profile_photo_url',
];
}
This is product model product.php
class Product extends Model
{
use HasFactory;
protected $fillable = [
'name', 'detail', 'image','color','logo','user_id'
];
public function User(){
return $this->belongsTo(User::class);
}
public function Project(){
return $this->hasMany('App\Models\Project');
}
}
This is project model project.php
class Project extends Model
{
use HasFactory;
protected $fillable = [
'chapter_name',
'sub_section_name',
'title_1',
'description_1',
'image_1',
'image_2',
'image_3',
'title_2',
'description_2',
'title_3',
'description_3',
'video_1',
'video_2',
'video_3',
'user_id',
'product_id'
];
public function User(){
return $this->belongsTo(User::class);
}
public function Product(){
return $this->belongsTo(Product::class);
}
}
Solved by Project::where('product_id',Product::where('user_id',Auth::id())->pluck('id')->last())->delete();
In ProjectImport
I am getting this error when I try to run the index method inside the controller:
Declaration of OneTokenAuth::validate() should be compatible with CModel::validate($attributes = NULL, $clearErrors = true)
My controller:
<?php
/**
* Class is used for
*/
class OneTokenAuthController extends Controller
{
public function init()
{
$this->attachbehavior('restBehavior', new RestBehavior());
parent::init();
}
public function filters()
{
return ['accessControl',];
}
public function accessRules()
{
return [
[
'deny',
'actions' => [
'index',
],
'users' => ['#']
]
];
}
/**
* Entry point for validating JWT token
* If the token is valid, user will be logged in as an admin
* and redirected to the admin dashboard
*
* #param [string] $t
* #return void
*/
function actionIndex($t){
$token = CHtml::encode(strip_tags($t));
$auth = new OneTokenAuth($token);
if(!$auth->verify())
die('Token is not valid');
if(!$auth->validate())
die('Token is not valid');
$this->redirect('admin/jobs/dashboardNewest');
}
}
My model:
<?php
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Token;
use Lcobucci\JWT\ValidationData as JWTValidation;
/**
* This is the model class for table "jwt_access_log".
*
* The followings are the available columns in table 'jwt_access_log':
* #property integer $id
* #property text $token
* #property integer $token_status
* #property timespamp $created_at
*/
class OneTokenAuth extends CActiveRecord
{
const VALID = 100;
const UNVERIFIED = 200;
const NONVALID = 300;
private $_singkey;
private $_token;
private $_signer;
private $_data;
function __construct ($token){
$this->_singkey = '1234xxxx';
$this->_signer = new Sha256();
$this->_token =(new Parser())->parse((string) $token);
$this->_token->getHeaders(); // Retrieves the token header
$this->_token->getClaims(); // Retrieves the token claims
$this->_data = new JWTValidation;
$this->_data->setIssuer('http://example.com');
$this->_data->setAudience($this->_token->getClaim('iss'));
}
public function tableName()
{
return 'jwt_access_log';
}
public function rules()
{
return [
['token_status', 'numerical', 'integerOnly' => true],
['token', 'length', 'max' => 1024],
['created_at', 'safe'],
];
}
/**
* #return array customized attribute labels (name=>label)
*/
public function attributeLabels()
{
return array(
'id' => 'ID',
'token' => 'Token',
'token_status' => 'Token Status',
'created_at' => 'Created At'
);
}
public function verify(){
if($this->_token->verify($this->_signer, $this->_singkey))
return true;
$this->makeLog(self::NONVALID);
return false;
}
public function validate(){
if($this->_token->validate($this->_data)){
$this->adminLogin();
return true;
}
$this->makeLog(self::UNVERIFIED);
return false;
}
public function makeLog($status)
{
$model = new self();
var_dump('<pre>', $model, '</pre>');die;
$model->setAttributes([
'token' => $this->_token,
'token_status' => $status,
]);
$model->save();
}
private function adminLogin()
{
$this->makeLog(self::VALID);
$login = new LoginComponent([
'email' => 'admin#admin.com',
'password' => 'u4ci_7aM%pigRe]Vp9B',
]);
$login->login();
}
}
What is going here?
The method in the derived class must have the same parameters as the parent class, you must specify parameters $attributes and $clearErrors
public function validate($attributes=null,$clearErrors=true){
if($this->_token->validate($this->_data)){
$this->adminLogin();
return true;
}
$this->makeLog(self::UNVERIFIED);
return false;
}
Below is my code for AuthController
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use Validator;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
//use App\Http\Requests\Request;
use Request;
use View;
use Hash;
use DB;
use Auth;
class AuthController extends Controller
{
/*
|--------------------------------------------------------------------------
| Registration & Login Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users, as well as the
| authentication of existing users. By default, this controller uses
| a simple trait to add these behaviors. Why don't you explore it?
|
*/
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
/**
* Where to redirect users after login / registration.
*
* #var string
*/
protected $redirectTo = '/home';
protected $redirectAfterLogout = '/login';
protected $username = 'user_name';
/**
* Create a new authentication controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware($this->guestMiddleware(), ['except' => 'logout']);
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:6|confirmed',
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
}
public function showLogin()
{
if (Auth::check())
{
return redirect('/home');
}
else
{
return View::make('index');
}
}
public function doLogin()
{
//echo 'test';
$input = Request::all();
$pass = Hash::make($input['password']);
//print_r($input);exit;
//echo $input['username'];exit;
/*DB::table('admin_user')->insert(
['user_name' => $input['username'], 'password' => $pass]
);*/
if (Auth::attempt(['user_name' => $input['username'], 'password' => $input['password']])) {
return redirect('/home');
//return View::make('home');
}
else
{
return redirect('/');
}
}
public function doLogout()
{
Auth::logout();
return redirect('/');
}
}
Below is my Route Code
Route::get('/',array('uses'=>'Auth\AuthController#showLogin') );
Route::post('/login',array('uses'=>'Auth\AuthController#doLogin'));
//Route::get('/login',array('uses'=>'Login#showLogin') );
Route::group(['middleware' => ['web', 'auth.basic']], function(){
Route::get('/home',['uses'=>'Home#getHome']);
Route::get('/logout',array('uses'=>'Auth\AuthController#doLogout') );
});
i am using user name instead of email id for Auth but below error is shown
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'email' in
'where clause' (SQL: select * from admin_user where email = admin
limit 1)
below is my kernal.php code
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* #var array
*/
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
];
/**
* The application's route middleware groups.
*
* #var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
],
'api' => [
'throttle:60,1',
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* #var array
*/
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'can' => \Illuminate\Foundation\Http\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
];
}
please help me how can i do login with username .
Thanks in advance.
Update:
Add the auth middleware to specific route
Route::group(['middleware' => ['web']], function(){
Route::get('/',array('uses'=>'Auth\AuthController#showLogin') );
Route::post('/login',array('uses'=>'Auth\AuthController#doLogin'));
Route::get('/home',['uses'=>'Home#getHome'])->middleware('auth');//update
Route::get('/logout',array('uses'=>'Auth\AuthController#doLogout') );
});
To redirect to intended page after login replace your doLogin() function with following:
public function doLogin()
{
$input = Request::all();
$pass = Hash::make($input['password']);
if (Auth::attempt(['user_name' => $input['username'], 'password' => $input['password']])) {
return redirect()->intended('/home');//This line is changed
}
else
{
return redirect('/');
}
}
Explaination:
intended() method redirects the user to the previous page, from where the user is redirected to login page. It expects a default route as a parameter, where user will be sent if he has came here directly.
Update 2:
add doLogout in your AuthController's constructor:
public function __construct()
{
$this->middleware($this->guestMiddleware(), ['except' => 'doLogout']);
}
You can simply override $username in AuthController by writing protected $username = 'username'.
I've changed the auth.php file in order to authenticate my users according to authors table. But I keep getting No account for you when I'm running test route.
auth.php
<?php
return array(
'driver' => 'eloquent',
'model' => 'Author',
'table' => 'authors',
'reminder' => array(
'email' => 'emails.auth.reminder', 'table' => 'password_reminders',
),
);
routes.php
Route::get('test', function() {
$credentials = array('username' => 'giannis',
'password' => Hash::make('giannis'));
if (Auth::attempt($credentials)) {
return "You are a user.";
}
return "No account for you";
});
AuthorsTableSeeder.php
<?php
class AuthorsTableSeeder extends Seeder {
public function run()
{
// Uncomment the below to wipe the table clean before populating
DB::table('authors')->delete();
$authors = array(
[
'username' => 'giannis',
'password' => Hash::make('giannis'),
'name' => 'giannis',
'lastname' => 'christofakis'],
[
'username' => 'antonis',
'password' => Hash::make('antonis'),
'name' => 'antonis',
'lastname' => 'antonopoulos']
);
// Uncomment the below to run the seeder
DB::table('authors')->insert($authors);
}
}
Addendum
I saw in another post that you have to implement the UserInterface RemindableInterface interfaces. But the result was the same.
Author.php
<?php
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class Author extends Eloquent implements UserInterface, RemindableInterface {
protected $guarded = array();
public static $rules = array();
public function posts() {
return $this->hasMany('Post');
}
/**
* Get the unique identifier for the user.
*
* #return mixed
*/
public function getAuthIdentifier()
{
return $this->getKey();
}
/**
* Get the password for the user.
*
* #return string
*/
public function getAuthPassword()
{
return $this->password;
}
/**
* Get the e-mail address where password reminders are sent.
*
* #return string
*/
public function getReminderEmail()
{
return "giannis#hotmail.com";
}
}
You don't need to Hash your password when you are using Auth::attempt(); so remove Hash::make from routes
Route::get('test', function() {
$credentials = array('username' => 'giannis',
'password' => 'giannis');
if (Auth::attempt($credentials)) {
return "You are a user.";
}
return "No account for you";
});
and it will work like a charm!