user auth Laravel 5.2 - authentication

in my project I need to protect some views.
I create a router group:
Route::group(['middleware' => ['auth']], function (){
//Spot
Route::get('administrator/spot-new', 'SpotController#create');
Route::post('administrator/spot-new', 'SpotController#store');
}
in my Spot Controller:
public function __construct()
{
$this->middleware('auth');
}
but when I try to access to spot view I can't see the login page.
I have this error:
Sorry, the page you are looking for could not be found.

Laravel 5.2 have added Middleware Groups.
https://laravel.com/docs/5.2/middleware#middleware-groups
Web middleware group is responsible for Start Session / Encrypt Cookies / Verify CSRF Token etc.. see below
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,
],
You're required to add when working with sessions and any other stuff
in that group.
So to solve your problem add 'web' to your middleware
Route::group(['middleware' => ['web', 'auth']], function (){
Route::get('administrator/spot-new', 'SpotController#create');
Route::post('administrator/spot-new', 'SpotController#store');
}
And in your controller constructor
public function __construct()
{
//$this->middleware('auth'); (No need for this one)
}

Related

Piranha CMS middleware to capture requests to /uploads

When a request is made for an image|file it doesn't reach my middleware.
I can see that when UseCms is called it adds PiranhaStartupFilter
serviceBuilder.Services.AddTransient<IStartupFilter, PiranhaStartupFilter>();
Which adds UseStaticFiles() to the ApplicationBuilder.
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
{
return builder =>
{
builder
.UseSecurityMiddleware()
.UseStaticFiles()
.UseMiddleware<RoutingMiddleware>()
.UseMiddleware<SitemapMiddleware>();
next(builder);
};
}
How could I overwrite this functionality so that my middleware is called for requests?
I'm expecting a call to /uploads/foo.jpg would be picked up in the InvokeAsync method of my middleware, registered like so:
app.UsePiranha(options =>
{
options.Builder.CustomImageTools();
});
At present only files & favicon requests reach the InvokeAsync method in my middleware.
As middleware in asp.net is executed in the order they are added into the pipeline it should be sufficient to add your interceptor before making any calls to Piranha.
You can add the middleware by adding a service above the call to UseCms() in startup.cs.
services.AddPiranha(options =>
{
options.CustomImageFilter();
options.UseCms();
}
public class CustomImageFilter : IStartupFilter
{
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
{
return app =>
{
app.UseWhen(
context => some_condition,
appbuilder => appbuilder.CustomImageTools()
);
// Call the next configure method
next(app);
};
}
}

Laravel 8 Route not Defined Error Caused by Auth Middleware

I am attempting to access a route defined in my routes/web.php file:
Route::get('/dashboard', [ConsoleController::class, 'dashboard'])->middleware('auth');
I am not logged in. The Authenticate.php middleware file attempts to redirect me back to the login page:
class Authenticate extends Middleware
{
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return route('');
}
}
}
I have also tried using return route('/'); in the Authenticate.php middleware.
My routes/web.php file has a default route which works fine if I go to the page manually:
Route::get('/', [ConsoleController::class, 'loginForm'])->middleware('guest');
However, the Authenticate.php is causing the following error:
Symfony\Component\Routing\Exception\RouteNotFoundException
Route [] not defined.
http://localhost:8888/dashboard
And it points to the following line of code:
public function route($name, $parameters = [], $absolute = true)
{
if (! is_null($route = $this->routes->getByName($name))) {
return $this->toRoute($route, $parameters, $absolute);
}
throw new RouteNotFoundException("Route [{$name}] not defined.");
}
I have found many similar posts on and off Stack Overflow, but none of those solutions have helped.
Am I naming my default route wrong? Can I not use this route in my Authenticate.php middleware? Any help would be appreciated.
Issue is, you are using route() method of Laravel, which expect route name as a parameter but you are passing actual url.
In your routes/web.php file, add name to your route as
Route::get('/dashboard', [ConsoleController::class, 'dashboard'])->middleware('auth')->name('dashboard');
Then in your Authenticate middleware file,
class Authenticate extends Middleware
{
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return route('dashboard');
}
}
}

Logout of MVC Application From Angular 5

We have an angular 5 application built on top of MVC authentication. The application is served up from the Home/Index action, and once the application is loaded, the angular routing takes care of pretty much everything. We are doing this primarily because we wanted to use MVC's Authentication processes (we are using Identity Server 4 as our Oath system).
This works well with one exception: logout. When we attempt to logout, the application seems to be immediately reauthorized and reloads instead of returning us to our Identity Server login page.
Originally, we had success in our development environment through this code:
[HttpPost]
public async Task<IActionResult> Logout()
{
foreach (string key in Request.Cookies.Keys)
{
Response.Cookies.Delete(key);
}
await HttpContext.SignOutAsync();
return Ok();
}
But it was a false positive, because all of our applications were running on localhost, so they had access to each other's cookies. Due to this, the Identity Server cookies were cleared along with the cookies for the Angular application.
We attempted to replace that logic with something like this:
public async Task Logout()
{
if (User?.Identity.IsAuthenticated == true)
{
// delete local authentication cookie
await HttpContext.SignOutAsync("Cookies");
await HttpContext.SignOutAsync("oidc");
}
}
However, it did not log out in either environment (however that code works for one of our MVC applications using the same identity server).
To give some background, our logout process for the Angular application comes from a material menu, where we then prompt the user if they really want to logout with a modal, before calling the logout function. Code snippets of this process:
Method called by logout button:
public openDialog(): void {
let dialogRef = this.dialog.open(ModalComponent, {
width: '250px',
data: { text: this.logoutText, ok: this.okText, cancel: this.cancelText }
});
dialogRef.afterClosed().subscribe(result => {
if (result !== undefined) {
switch (result.data) {
case 'ok':
this.logout();
break;
case 'cancel':
break;
default:
break;
}
}
});
}
private logout(): void {
this.sessionService.logOut();
}
Session service:
public logOut(): void {
this.auth.revokeToken();
this.http.post(this.logoutUrl, undefined).subscribe(x => window.location.reload());
}
As mentioned, calling logout this way ends up with a page refresh and the user not really being logged out. There's probably something simple we are missing, but all of the tinkering I've done so far has not led to any success.
EDIT:
Our angular routing is fairly simple (though the pathing prevents us from calling something like home/logout):
{
path: 'parts',
component: PartsComponent,
canActivate: [AuthGuard],
runGuardsAndResolvers: 'always',
data: { title: 'Parts' }
},
{
path: '',
redirectTo: 'parts',
pathMatch: 'full'
},
{
path: '**',
redirectTo: 'parts'
}
Our MVC routes are also fairly straightforward
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapRoute(
"Sitemap",
"sitemap.xml",
new { controller = "Home", action = "SitemapXml" });
routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Home", action = "Index" });
});
I'm not certain how we could easily route to home/logout with the angular routes the way they are. I'm guessing we'd have to add a route for it. We tried that at one point but it never routed correctly. I'm trying to find my notes on what we tried.
After you cleared the local cookies of your application send the user to the end_session_endpoint of your Idsrv. (The code you showed to clear your session should work, if not I'd the config in startup.cs and debug to check if the redirect really removed the cookie in the browser).
E.g. https://demo.identityserver.io/.well-known/openid-configuration
There you see the endpoint. This should remove the session on the Idsrv. Depending on your setup this could kill your sessions on your other applications that uses the same Identity Server instance.
You can read more about this in the docs.
I don't see a problem with the Angular routing interfering with your server side routing. As long as you ofcourse really do a redirect to that page using a regular window.location.replace
And ofcourse like #Win mentioned it would be a good security guideline to revoke refresh_token and reference_tokens if you use those.
I could not answer for Angular; I'm still working on it. However, client web app could ask IDP to revoke access token and refresh token when user signs out at client. For example, in ASP.Net Core -
using System;
using System.Threading.Tasks;
using IdentityModel.Client;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
namespace MY_APP.Controllers
{
public class AccountController : Controller
{
[HttpGet]
public async Task<IActionResult> SignOut()
{
var discoveryClient = new DiscoveryClient("IDP_URL");
var metaDataResponse = await discoveryClient.GetAsync();
var revocationClient = new TokenRevocationClient(
metaDataResponse.RevocationEndpoint,
"CLIENT_NAME",
"CLIENT_SECRET");
// revoke the access token
string accessToken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.AccessToken);
if (!string.IsNullOrWhiteSpace(accessToken))
{
var revokeAccessTokenResponse = await revocationClient.RevokeAccessTokenAsync(accessToken);
if (revokeAccessTokenResponse.IsError)
throw new Exception("Problem encountered while revoking the access token.",
revokeAccessTokenResponse.Exception);
}
// revoke the refresh token
string refreshToken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.RefreshToken);
if (!string.IsNullOrWhiteSpace(refreshToken))
{
var revokeRefreshTokenResponse = await revocationClient.RevokeAccessTokenAsync(refreshToken);
if (revokeRefreshTokenResponse.IsError)
throw new Exception("Problem encountered while revoking the refresh token.",
revokeRefreshTokenResponse.Exception);
}
return SignOut(
new AuthenticationProperties { RedirectUri = "CALL_BACK_URL" },
CookieAuthenticationDefaults.AuthenticationScheme,
OpenIdConnectDefaults.AuthenticationScheme);
}
}
}

CakePHP3 Auth redirectURL route broken

I have a controller with a particular method to login:
public function login() {
if ($this->request->is('post')){
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
return $this->redirect($this->Auth->redirectUrl());
}
// not logged
$this->Flash->error('Your username or password is incorrect');
}
}
and default route looks like
Router::scope('/', function (RouteBuilder $routes) {
$routes->fallbacks(DashedRoute::class);
});
after user is logged in CakePHP throws an error
Error: A route matching "/" could not be found.
None of the currently connected routes match the provided parameters.
Add a matching route to config/routes.php
when IMO it should to redirect to the page (based on a related controller) from where login method was executed.
Login code is based on that tutorial.
Any thoughts?
To solve this issue:
Please update the below lines in routes.php file
Router::defaultRouteClass('DashedRoute');
Router::scope('/', function (RouteBuilder $routes) {
$routes->connect('/', ['controller' => 'users', 'action' => 'index']);
$routes->fallbacks('DashedRoute');
});
Plugin::routes();
Please do create index() in users controller.
Let me know if any issue.

Authenticating a user role in Laravel and protecting a route

I have taken advice from people here and given Laravel a try, I have been trying to create a user authentication system. I am having trouble translating what I know works in PHP to Laravel using Eloquent.
What I am trying to do here is identify a user, their roles, if the user has a role of admin they can access the route /admin
I know I can use a package such as Entrust but that is not really helping me learn.
I have created Models for both User and Role. I also have a lookup table called role_user with a user_id and role_id.
In User.php I have
public function roles(){
return $this->belongsToMany('Role', 'users_roles');
}
In Role.php I have
public function users()
{
return $this->belongsToMany('User', 'users_roles');
}
I know if I used
$roles = user::find(1)->roles;
return ($roles);
It will and does return the correct user id (1) and the roles assigned to that user. Now what I am struggling with is how to pick out the admin role and only if the user has this will it allow access to /admin
The route should essentially be
Route::get('admin', function()
{
return View::make('admin.index');
})->before('auth');
What I can't figure how/where/should I check for the admin role first and how to then apply that to the auth check to only permit an admin access to the route.
Any help appreciated.
Lee
For Laravel 5, use Middleware:
Create new middleware
# php artisan make:middleware RoleMiddleware
Check the user role - redirect if invalid role
// app/Http/Middleware/RoleMiddleware.php
class RoleMiddleware
{
public function handle($request, Closure $next, $role)
{
if (! $request->user()->hasRole($role)) {
// Redirect...
}
return $next($request);
}
}
Add key in order to assign to routes - can also make global
// app/Http/Kernel.php
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'role' => \App\Http\Middleware\RoleMiddleware::class, // new
];
Protect the routes
// app/Http/routes.php
Route::put('post/{id}', ['middleware' => 'role:editor', function ($id) {
// routes for editor
}]);
You have used auth filter so you should check in the auth filter in app/filters.php file:
Route::filter('auth', function($route, $request)
{
// Login check (Default)
if (Auth::guest()) return Redirect::guest('login');
// Admin check
if(!in_array('admin', Auth::user()->roles->toArray())) {
return Redirect::to('/'); // Redirect home page
}
});
You may use a different filter, for example:
Route::get('admin', function()
{
return View::make('admin.index');
})->before('isAdmin');
Declare the custom isAdmin filter in app/filters.php:
Route::filter('isAdmin', function($route, $request)
{
if(!Auth::check()) return Redirect::guest('login');
if( !in_array('admin', Auth::user()->roles->toArray()) ) {
return Redirect::to('/'); // Redirect home page
}
});