Laravel 5.3 RESTFul API without authentication - api

I want to create an API with Laravel 5.3 but i don't need any kind of authentication. Is it possible to get rid of it? I don't want any token or any kind of authentication.

Yes, it's possible
normally in your
route/api.php
you'd have something like
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
you just need to remove the part of the middleware that's referencing auth.
So the above would look like:
Route::middleware('api')->get('/user', function (Request $request) {
return $request->user();
//middleware('api') URI prefix. which would become '/api/user'
});
or
Route::apiResource('user', 'UserController');
//same as above but includes crud methods excluding 'create and edit'

To help anyone in my situation who arrive here : be aware that any route in api.php is prefixed by "api/".
It is set in /app/Providers/RouteServiceProvider.php.
So :
Route::get('/delegates', "APIController#delegate");
Will be accessible from
http://www.yourdomain.com/api/delegates
Sorry if it's a bit off-topic, but hope it can help someone.

Of course you can get rid of it. Just setup your routes to don't use any middleware.
Create your API routes on routes/api.php file, then modify the app/Http/Kernel.php file to set your middlewares correctly:
Remove (or add) the middlewares you don't want on api middleware group.
By default, L5.3 comes with two middlewares on api group:
'api' => [
'throttle:60,1',
'bindings',
],
The first one provides a rate limiting to your API (60 requests/minute),
the second substitutes your model bindings.

It's possible, just create route to your controller and return data (Without any auth middleware).

Allow your route to run without auth
Http\Middleware\VerifyCsrfToken
public function handle($request, Closure $next)
{
if (!$request->is('api/*'))
{
return parent::handle($request, $next);
}
return $next($request);
}
Set route like this
'api' => 'APIController'
This is method in APIController ('/api/data')
public function getData(Request $request)
{
return "Hello";
}

Related

How to allow to unauthenticated users see some specific pages or actions pages in Cake PHP 3?

With CakePHP 3 we used Auth component and this worked like this CakePHP - How to allow unauthenticated access to specific pages
Now I'm trying to use the new Authentication and Authorization plugins instead (I don't know if it is the best solution).
I have this case:
I have some tables in the database for entities (cars, brands, and users). I have users and 4 level user roles (pyramid).
- Admins can change everything
- Editors can see and add brands and cars, but only can edit or update cars and brands created by themselves.
- Registered users can add only cars and edit their cars (and see all cars and brands).
- Anonymous users can see all but only can create a user account.
Authentication works well alone. To allow anonymous user access to content I use $this->Authentication->allowUnauthenticated(['login', 'add']); but when I load Authorization plugin, everything give error.
Do I need to specify all Authorization access with authorizeModel and other functions? There is a way to authorize at the same time with both plugins? Do I really need Authorization plugin for this and is recommended or Authentication plugin can handle this?
With previous Auth component I worked with something like this piece of code:
In AppController.php
public function beforeFilter(Event $event)
{
$this->Auth->allow(['view', 'display']);
}
public function isAuthorized($user)
{
return true;
}
In UsersController.php
public function beforeFilter(Event $event)
{
parent::beforeFilter($event);
$this->Auth->allow('add', 'logout');
}
In Cars and Brands controllers
public function isAuthorized($user)
{
if (isset($authUser['role']) && $authUser['role'] === 'admin') {
return true;
}
if ($this->request->action === 'add') {
return true;
}
if ($this->request->action === 'index') {
return true;
}
if (in_array($this->request->action, ['edit'])) {
$carId = (int)$this->request->params['pass'][0];
if ($this->Cars->exists(['id' => $carId, 'user_id' => $authUser['id']])) {
return true;
}
}
return false;
}
Followed from https://book.cakephp.org/3/es/tutorials-and-examples/blog-auth-example/auth.html
My versions are:
- CakePHP 3.8
- Authentication plugin 1.4
- Authorization plugin 1.3
Sorry if my question is a bit basic but documentation is not very clear with this. I can add more details if needed.
Edit: If I quit unauthenticatedRedirect I get:
No identity found. You can skip this check by configuring `requireIdentity` to be `false`.
Authentication\Authenticator\UnauthenticatedException
If I add requireItentity as false, in AppController
$this->loadComponent('Authentication.Authentication', [
'requireIdentity' => false
]);
I get (where / is the path, can be /cars /brands)
The request to `/` did not apply any authorization checks.
Authorization\Exception\AuthorizationRequiredException
If I use this in AppController (always Authentication before Authorization)
$this->loadComponent('Authentication.Authentication', [
'requireIdentity' => false
]);
$this->loadComponent('Authorization.Authorization', [
'skipAuthorization' => [
'login',
]
]);
and this in Application
$service->setConfig([
'unauthenticatedRedirect' => \Cake\Routing\Router::url('/users/login'),
'queryParam' => 'redirect',
]);
I send all users to login page but authorization checks error appears.
With $this->Authorization->skipAuthorization(); in beforeFilter() user can see the pages and works but I don't know if it is appropriated.
If I use this in any controller beforeFilter $this->Authorization->authorizeModel('index', 'add', 'display' ...);
I get
Policy for `App\Model\Table\CarsTable` has not been defined.
Authorization\Policy\Exception\MissingPolicyException
In home (or pages controller) I get
Policy for `Cake\ORM\Table` has not been defined.
Authorization\Policy\Exception\MissingPolicyException
Do I really need to create policies for each table? I think is more complex than previous Auth component or maybe I'm doing something wrong.

Passing Controller Action output as SupplyData in UseSpaPrerendering of .Net Core

In .Net Core application, I have below code in Configure method of Startup.cs file.
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
spa.UseSpaPrerendering(options =>
{
options.BootModulePath = $"{spa.Options.SourcePath}/dist-server/main.js";
options.BootModuleBuilder = env.IsDevelopment() ? new AngularCliBuilder(npmScript: "build:ssr") : null;
options.ExcludeUrls = new[] { "/sockjs-node" };
});
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
UseSpaPrerendering has an option to provide SupplyData callback which lets you pass arbitrary, per-request, JSON-serializable data.
In my case there are pages in my Angular application which makes http requests to fetch data. Since these requests are made to the same application. I see a potential of optimization i.e. if we could just call the corresponding Controller Action method and supply its data to Angular, so that we dont have to make an http request for SSR.
Can anyone please guide how to achieve this.
I know that below is how we pass data using SupplyData
options.SupplyData = (context, data) =>
{
// Creates a new value called isHttpsRequest that's passed to TypeScript code
data["isHttpsRequest"] = context.Request.IsHttps;
};
But how to we pass the results/output of a Controller Actions (which returns json).
I wrote a package to determine the currently activated SPA route from the supplydata delegate.
https://github.com/MusicDemons/AspNetSpaPrerendering
You have to define all your SPA routes using the SpaRouteBuilder and then you can check which route was activated and get the route data (like an id). Based on that you get data from your database through your repositories and add this data to the array. A complete example is included.

AssumeDefaultVersionWhenUnspecified is not working as expected

I have been using asp net core versioning component for my WebAPI. Need your help in understanding how AssumeDefaultVersionWhenUnspecified is working. (tried searching for documentation, but couldn't find one)
My startup looks like below
services.AddApiVersioning(o => {
o.ReportApiVersions = true;
o.AssumeDefaultVersionWhenUnspecified = true;
o.DefaultApiVersion = new ApiVersion(2, 0);
o.ApiVersionReader = new UrlSegmentApiVersionReader();
});
When the route attribute is something like below
[ApiVersion("2.0")]
[Route("api/v{version:apiVersion}/values")]
[ApiController]
public class ValuesV2Controller : ControllerBase
{
...
}
The above route works only when the api version is specified. ie: http://localhost:55401/api/v2/values
If I call like http://localhost:55401/api/values, getting 404 error
My question is this... How AssumeDefaultVersionWhenUnspecified works. Wouldn't it ignore the version in Route? Looks like Route attribute takes precedence over AssumeDefaultVersionWhenUnspecified. If I choose QueryString or Header versioning and when the Route looks like
[ApiVersion("2.0")]
[Route("api/values")]
the default routing reaches the API
Am I missing anything or is my understanding wrong? How shall I achieve default routing to the latest version API using url versioning?
I am also trying to achieve the same functionality. By looking into [https://github.com/Microsoft/aspnet-api-versioning/issues/351#issuecomment-425106940]
I am assuming that we can't achieve default API version AssumeDefaultVersionWhenUnspecified functionality with only a single style of versioning uses a URL segment [Route("api/v{version:apiVersion}/[controller]")]
We have to define two routes separately as follow
[Route("api/[controller]")]
[Route("api/v{version:apiVersion}/[controller]")]
and to hide the two implementations from swagger you can achieve using this link
Summarizing the the solution from the github issue linked by Athi S, here's what you need to do :
In ConfigureServices inside Startup.cs file :
services.AddApiVersioning(o =>
{
o.AssumeDefaultVersionWhenUnspecified = true;
o.ApiVersionSelector = new CurrentImplementationApiVersionSelector(o);
// o.DefaultApiVersion = new ApiVersion(1, 0);
});
You can optionally set ApiVersionSelector to a new instance of CurrentImplementationApiVersionSelector. What this does is, it automatically selects the highest api version registered in controllers. E.g. A controller decorated with [ApiVersion("1.2")] takes precedence over [ApiVersion("1.1")].
If you want to specify default api version explicitly, you can do so by leaving ApiVersionSelector to DefaultApiVersionSelector and setting DefaultApiVersion to your required api version.
In your controllers :
Register the required routes by decorating your controllers with the given Route attributes
[Route("api/[controller]")]
Or if you want the api to work both with and without the api version number specified, you can do so by declaring two routes for the controller.
[Route("api/[controller]")]
[Route("api/v{version:apiVersion}/[controller]")]

disable csrf for unprotect method post, put and delete in laravel 5

in laravel 4 not use csrf protect method (POST, PUT and DELETE) is default but in larave 5 use csrf to protect post, put and delete method from injection code is default is default. this protection is no problem for form but it have problem for build api rest.
so help me to show how to disable csrf unprotect method ( POST, PUT and DELETE) for build api rest in laravel 5. thanks
go to app->http->kernel
open kernel file:
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\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, // this is the csrf token, just disable using '//'
];
It is a method from here and I have tested that it should be okay.
In short, to disable csrf in particular pages, just change the app/Http/Middleware/VerifyCsrfToken.php to something like this:
public function handle($request, Closure $next)
{
//disable CSRF check on following routes
$skip = array(
'user/path/xys',
'user/profile',
'my/unprotected/route'
);
foreach ($skip as $key => $route) {
//skip csrf check on route
if($request->is($route)){
return parent::addCookieToResponse($request, $next($request));
}
}
return parent::handle($request, $next);
}
If your concern is just for /api/* routes, you can follow my answer here on Stack Overflow
HOpe this helps you to get clean and short code.

Laravel 5 Auth for Restful Resource Controllers to restrict resource to logged in user

I have a pretty basic RESTful address manager. I have user accounts setup with user login all based on Auth and am in the process of integrating entrust but that's beyond the scope of this. For now, I simply want to restrict access to my AddressController to users who are logged in. I'm able to do this on a route using:
Route::get('profile', ['middleware' => 'auth', 'uses' => 'UserController#getProfile']);
However if I try this on my RESTful resource as follows it doesn't work - I don't get an error, but the un-authenticated user can still access the resource.
Route::resource('addresses', 'AddressController', ['middleware' => 'auth']);
Try grouping your resources that should use a specific middleware:
Route::group(['middleware' => 'auth'], function(){
Route::resource('addresses', 'AddressController');
});
Only you know how your scenario is, but another way to run filters in resources is to call to needed middlewares in the resource's constructor like:
class AddressController extends Controller {
public function __construct()
{
$this->middleware('auth');
}