I've tried to exclude requests from another localhost server (http://localhost:8080/order/placeorder) to another one localhost server (http://localhost:8000)
I don't want to disable all csrf protection by removing
\App\Http\Middleware\VerifyCsrfToken::class in Illuminate\Foundation\Http\Kernel.php
I've tried to modify app/Http/Middleware/VerifyCsrfToken.php
protected $except = [
'http://localhost:8080/*',
'http://localhost:8080',
'/order/placeorder/*',
'http://localhost:8080/order/placeorder'
];
and I also tried this way
private $openRoutes = [
'http://localhost:8080/*',
'http://localhost:8080',
'/order/placeorder/*',
'http://localhost:8080/order/placeorder'
];
public function handle($request, Closure $next)
{
//add this condition
foreach($this->openRoutes as $route) {
if ($request->is($route)) {
return $next($request);
}
}
return parent::handle($request, $next);
}
But I still got this error
TokenMismatchException in VerifyCsrfToken.php
Can anyone suggest me what should I do and what I've done wrong?
The exceptions are routes within your own application that are excluded, not the URLs of servers that are requesting it. You will never put localhost, http, or any domain in these exceptions in normal circumstances. If you wish for a request by an external server to be accepted, I would disable CSRF protection for the routes it is accessing (because you want a cross-site request, that's what CSRF prevents).
For example, if you want any external server to be able to send a POST request to /order/placeorder, you would simply add that route to the exclusion. You also need to add any other route you want it to be able to access. If there are a lot, there are other more manageable ways to do this with middleware as well.
To authenticate the server making the request, it should send a token to verify itself. You can create a static token for this purpose (like an API key), or possibly use an OAuth implementation of some sort with access/refresh tokens - there is a package for Laravel for this that makes it easy.
Related
TLDR; see image below 3 - is that possible and how?
I read about API protection - Sanctum & Passport, but none of these seems what I can accomplish with my app since it's a little specific and simplified in a way.
For example, Sanctum's way of authenticating sounds like something I'd like, but without the /login part (i have a custom /auth part, see below.): https://laravel.com/docs/8.x/sanctum#spa-authenticating.
If the login request is successful, you will be authenticated and
subsequent requests to your API routes will automatically be
authenticated via the session cookie that the Laravel backend issued
to your client.
My app has no login per se - we log-in the user if they have a specified cookie token verified by the 3rd party API (i know token-auth is not the best way to go, but it is quite a specific application/use). It's on /auth, so Sanctum's description above could work, I guess if I knew where to fiddle with it. Our logic:
VueJS: a mobile device sends an encrypted cookie token - app reads it in JS, sends it to my Laravel API for verification.
Get the token in Laravel API, decrypt, send to 2nd API (not in my control), verifying the token, and sends back an OK or NOT OK response with some data.
If the response was OK, the user is "logged-in."
The user can navigate the app, and additional API responses occur - how do I verify it's him and not an imposter or some1 accessing the API directly in the browser?
I guess the session could work for that, but it's my 1st time using Laravel, and nothing seemed to work as expected. Also, sessions stored in files or DB are not something I'm looking forward to if required.
For example, I tried setting a simple session parameter when step 3 above happened and sending it back, but the session store was not set up, yet it seemed at that point. Then I could check that session value to make sure he's the same user that was just verified.
For an easier understanding of what I'm trying to accomplish and if it's even feasible:
The main question is, what is the easiest way to have basic API protection/authentication/verification whilst sending the token for authentication to 3rd party API only on 1st request (and if the app is reopened/refreshed of course) - keeping in mind, that no actual users exist on my Laravel API.
Or would it be best to do the token-auth to the 3rd party API on each request?
If I understand your case correctly there's no real User model involved, right? If so, you'll not be able to use any of Laravel's built-in authentication methods as they all rely on the existence of such a model.
In that case you'll need one endpoint and a custom authentication Middleware that you'll need to create yourself in Laravel in order to handle everything:
The endpoint definition:
Route::post('authenticate', [TokenController::class, 'login']);
The controller:
class TokenController extends Controller
{
public function login(Request $request)
{
// First read the token and decrypt it.
// Here you'll need to replace "some_decryption()" with the required decrypter based on how your VueJS app encrypts the token.
$token = some_decryption( $request->input('token') );
// Then make the request to the verification API, for example using Guzzle.
$isTokenOk = Http::post('http://your-endpoint.net', [
'token' => $token,
])->successful();
// Now issue a Laravel API token only if the verification succeeded.
if (! $isTokenOk) {
abort(400, 'Verification failed');
}
// In order to not store any token in a database, I've chosen something arbitrary and reversibly encrypted.
return response()->json([
'api-token' => Crypt::encrypt('authenticated'),
]);
}
}
Subsequent requests should pass the api token in the Authorization header as a Bearer token. And then in the Middleware you'll check for Bearer token and check if it matches our expected value:
class AuthTokenAuthenticationMiddleware
{
public function handle($request, Closure $next)
{
$authToken = $request->bearerToken();
if (! $authToken || ! Crypt::decrypt($authToken) === 'authenticated') {
abort(401, 'Unauthenticated');
}
return $next($request);
}
}
The Middleware needs to be registered in app/Http/Kernel.php:
protected $routeMiddleware = [
...
'auth-token' => AuthTokenAuthenticationMiddleware::class,
];
And finally apply this new middleware to any of your routes that should be authenticated:
Route::middleware('auth-token')->get('some/api/route', SomeController::class);
Warning: this authentication mechanism relies on reversible encryption. Anyone able to decrypt or in possession of your APP_KEY will ultimately be able to access your protected endpoints!
Of course this is one way to deal with custom userless authentication and there are many more. You could for example insert an expiration date in the encrypted token instead of the string "authenticated" and verify if it's expired in the middleware. But you get the gist of the steps to be followed...
If you do have a User model in place, then you could use Laravel Sanctum and issue an API token after User retrieval instead of forging a custom encrypted token. See https://laravel.com/docs/8.x/sanctum#issuing-mobile-api-tokens
// Fetch the corresponding user...
$user = User::where('token', $request->input('token'))->first();
return $user->createToken('vuejs_app')->plainTextToken;
Subsequent requests should pass the token in the Authorization header as a Bearer token.
Protect routes using the middleware provided by Sanctum:
Route::middleware('auth:sanctum')->get('some/api/route', SomeController::class);
I see quite a few people having a similar issue with this, but no final resolved solutions. I have been trying to get this working for about 24 hours now and still no luck!
Goals
Build and API using Laravel 6 and Dingo API
Be able to consume the API externally, authenticating with Passport oAuth.
Be able to consume the API internally, via ajax, using passports self-authenticating feature.
Be able to consume the API internally, with PHP, using dingo's self-consuming methods.
What I have found out so far
Auth provider order
Most solutions I have seen suggest setting up both the passport auth and dingo alongside one another. This is auth:api (passport) and api.auth (dingo).
// API route middleware
$api->group(['middleware' => 'auth:api', 'api.auth'], function (Router $api) {
...
The api.auth here is actually a custom auth provider setup in laravel and configured to dingo, which bridges the passport logic into dingo.
// Auth provider
class DingoPassportAuthProvider extends Authorization
{
protected $guard;
public function __construct(AuthManager $auth)
{
dump('DingoPassportAuthProvider Instantiated');
$this->guard = $auth->guard('api');
}
public function authenticate(Request $request, Route $route)
{
if ($this->guard->check()) {
return $this->guard->user();
}
throw new UnauthorizedHttpException('Not authenticated via Passport.');
}
public function getAuthorizationMethod()
{
return 'Bearer';
}
}
// Configured in dingo (Api.php)
'auth' => [
'passport' => \App\Providers\DingoPassportAuthProvider::class,
],
If we put the dingo API provider first in the middleware stack we get:
Internal API requests work IF you specify the user for the call with the be() method: $this->api->be($request->user())->get('/api/profile')
External API requests and internal AJAX requests authenticate correctly and the user is returned from the custom dingo auth provider, however, for some reason you cannot then access this user from within the API controllers: $user = $request->user(); // null
If we put the Passport API provider first in the middleware stack we get:
Internal API requests do not work at all (401 always returned)
External API requests and internal AJAX requests work as intended.
The authenticate method on the dingo passport provider is no longer called. I think this may have something to do with the 401 returned on internal calls.
I believe the correct way around, is to put the passport authentication first. This way, we authenticate the user before calling the dingo authentication, resulting in 2 things:
Passport works natively as expected.
Dingo internal API calls should now just be able to be called with $this->api->get('/api/profile') (omit defining the user with be()), however this does not work.
At the moment I have the previous configuration. Passport works as intended for external and ajax calls, but the internal dingo calls always return 401.
There are a few boilerplate templates I have checked out and they do not seem to do anything different. I wonder if something changed in L6 to explain why the internal requests do not work.
I have found one work around for now, which gets most of the way there...
Within the custom dingo auth provider:
class DingoPassportAuthProvider extends Authorization
{
public function authenticate(Request $request, Route $route)
{
if (Auth::guard('web')->check()) {
return Auth::guard('web')->user();
}
if (Auth::guard('api')->check()) {
$user = Auth::guard('api')->user();
Passport::actingAs($user);
return $user;
}
throw new UnauthorizedHttpException('Not authenticated via Passport.');
}
public function getAuthorizationMethod()
{
return 'Bearer';
}
}
This now checks to see if the request is coming from either the web guard (internal request) or the api guard (external or ajax request) and returns the correct user.
For the api guard, there seems to be an issue that the user is authenticated but not actually available within the controllers. To get around this I added the Passport::actingAs($user). It is probably not best practice, but the guards are now acting as they should and as are all my different scenarios.
Then in the API route middleware, we only specify the custom dingo provider.
// API route middleware
$api->group(['middleware' => 'api.auth'], function (Router $api) {
...
One thing to note with this, is dingos be() method does not work quite as expected. Instead you need to switch the user as you would in a general laravel app.
\Auth::loginUsingId(2);
$user = $this->api->get('/api/profile');
I want to make boot function for my app preview, for that I have plan to add new variable to .env file and let's name it APP_Mode so I want to say:
If APP_Mode=preview prevent all actions and redirect back with
xxxxxx text as flash session message.
The point
The point of this boot action that I try to achieve is to not let users change any of my preview site settings like store/delete/update etc.
Question
Is that possible? How?
First off, might be worth considering if Laravel's maintenance mode might work for you - you can whitelist the IP addresses that are able to access the site, and it will appear down for everyone else.
If that's not going to do the trick, you'll probably be best to create your own middleware - it will likely be similar to the CheckForMaintenanceMode middleware that Laravel ships with. In the handle method you can check for the configuration option to see if you're in preview mode or not, and then decide how to handle the request.
If you're using "RESTful" routing like Laravel recommends - that is, GET requests are idempotent and don't change anything, and only POST/PUT/DELETE requests make changes - your middleware can simply return a HTTP 403 response (forbidden) if your preview mode is enabled and the request method isn't GET.
A very simple implementation (you'll likely need to tweak) to get you started would be something like this:
public function handle($request, Closure $next) {
if (config('app.mode') === 'preview' && $request->method() !== 'GET') {
abort(403);
}
return $next($request);
}
Just in regard to using config('app.mode') instead of something env('APP_MODE') is that you shouldn't be using the env helper outside of the configuration files - otherwise you can't take advantage of Laravel's config caching. So add another config option in the config/app.php file that you can use to check the mode the app is in.
I am building a REST user-microservice using Laravel 5.5 + Passport.
I am using the standard Passport::routes(), but I have had to modify the Auth::routes in order to make them return JSON responses, and to make them work with Passport.
I have added the following lines to my routes/web.php file:
Route::group(['middleware' => 'auth:api'], function () {
$this->post('logout', 'Auth\LoginController#logout')->name('logout');
});
This allows me to POST https://myapi/logout
If I make the call with the header "Authorization => Bearer TOKEN", I get a successful logout response.
If I provide no header at all, I get a "not authenticated" message (which is good)
However, if I provide the header with a revoked token, I get a recursive deadloop of the function: Illuminate\Auth\RequestGuard->user() (it keeps calling itself recursively until stack-overflow)
This is all done in the auth:api middleware, my logout code is not reached, but my LoginController constructor is called. Constructor code:
public function __construct(Application $app)
{
$this->apiConsumer = $app->make('apiconsumer');
$this->middleware('guest')
->except('logout');
}
I'm struggling to understand if it's my code causing this issue, or some combination of Laravel + passport + auth.
My first thought was that the auth:api middleware fails to authenticate the user, and as a result redirects the user to /home, where for some reason it's triggered again, recursively. But if that was the case, why would it work correctly with no header?
My current thinking is that the token in question does exist in the database, but Laravel is failing to figure out that it's revoked.
Any suggestions appreciated,
I found an answer (if not the answer) after a lot of research. It appears this is a Laravel bug (https://github.com/laravel/passport/issues/440). The solution is to add OAuthServerException to the $dontReport array in app/Exceptions/Handler.php:
class Handler extends ExceptionHandler
{
protected $dontReport = [
...
\League\OAuth2\Server\Exception\OAuthServerException::class,
];
}
This will avoid trying to log user information, thereby avoid the deadloop.
I have faced this in localhost. in my case, I have used xampp server and facing this issue
after creating a virtual host like "testlarave.test" then solve the error
I use this package = https://github.com/aacotroneo/laravel-saml2
I configured everything in the SP and iDP sections in saml2_settings.php as instructed.
STEPS
I go to : /admin/login
I got redirected and landed on my iDP log-in page immediately, it is a correct behavior.
I log-in with the proper username and password.
After successfully authenticated by my iDP, I got the SAML Response from my iDP like this sample
{
"SAMLResponse": "PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6\r\nU0FNTDoyLjA6cHJvdG9jb2wiIERlc3RpbmF0aW9uPSJodHRwczovL3Rlc3RzZXJ2\r\nZXIuYmVudW5ldHMuY29tL2FkbWluL3NlY3VyZS9kYXNoYm9hcmQiIElEPSJpZC1C\r\nNlBFSnhLNFhGWUg3T1hzbGZLU2trbGt0YmMtIiBJblJlc3BvbnNlVG89Ik9ORUxP\r\nR0lOXzIxNjFiNTA1OTFmNjc1ZmUzZGM0MmZlYzRlZDJkOGU1MWRlZmQ2ZmQiIElz\r\nc3VlSW5zdGFudD0iMjAxNy0wMy0yOFQxOTozMzo1M1oiIFZlcnNpb249IjIuMCI+\r\nPHNhbWw6SXNzdWVyIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0YzpTQU1M\r\nOjIuMDphc3NlcnRpb24iIEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6\r\nMi4wOm5hbWVpZC1mb3JtYXQ6ZW50aXR5Ij5UZWxlbmV0PC9zYW1sOklzc3Vlcj48\r\nc2FtbHA6U3RhdHVzPjxzYW1scDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6\r\nbmFtZXM6dGM6U0FNTDoyLjA6c3RhdHVzOlN1Y2Nlc3MiLz48L3NhbWxwOlN0YXR1\r\ncz48c2FtbDpBc3NlcnRpb24geG1sbnM6c2FtbD0idXJuOm9hc2lzOm5hbWVzOnRj\r\nOlNBTUw6Mi4wOmFzc2VydGlvbiIgSUQ9ImlkLThvWVBULWlwVFZhR2UwSHpwRGdS\r\nSEoyWEp4Zy0iIElzc3VlSW5zdGFudD0iMjAxNy0wMy0yOFQxOTozMzo1M1oiIFZl\r\ncnNpb249IjIuMCI+PHNhbWw6SXNzdWVyIEZvcm1hdD0idXJuOm9hc2lzOm5hbWVz\r\nOnRjOlNBTUw6Mi4wOm5hbWVpZC1mb3JtYXQ6ZW50aXR5Ij5UZWxlbmV0PC9zYW1s\r\nOklzc3Vlcj48ZHNpZzpTaWduYXR1cmUgeG1sbnM6ZHNpZz0iaHR0cDovL3d3dy53\r\nMy5vcmcvMjAwMC8wOS94bWxkc2lnIyI+PGRzaWc6U2lnbmVkSW5mbz48ZHNpZzpD\r\nYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5v\r\ncmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PGRzaWc6U2lnbmF0dXJlTWV0aG9k\r\nIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI3Jz\r\nYS1zaGExIi8+PGRzaWc6UmVmZXJlbmNlIFVSST0iI2lkLThvWVBULWlwVFZhR2Uw\r\nSHpwRGdSSEoyWEp4Zy0iPjxkc2lnOlRyYW5zZm9ybXM+PGRzaWc6VHJhbnNmb3Jt\r\nIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI2Vu\r\ndmVsb3BlZC1zaWduYXR1cmUiLz48ZHNpZzpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJo\r\ndHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48L2RzaWc6\r\nVHJhbnNmb3Jtcz48ZHNpZzpEaWdlc3RNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8v\r\nd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjc2hhMSIvPjxkc2lnOkRpZ2VzdFZh\r\nbHVlPitTQkNSRjNTenZvMzgxVlJ0dWcvRUJvallCUT08L2RzaWc6RGlnZXN0VmFs\r\ndWU+PC9kc2lnOlJlZmVyZW5jZT48L2RzaWc6U2lnbmVkSW5mbz48ZHNpZzpTaWdu\r\nYXR1cmVWYWx1ZT5SaWt5czdsQWNOc250ZlVkZVg0dC9jWjBRelRyRTNGc3RTempx\r\nZDEyaU5sUGpJVkxJVitHTXM1UXQ3U2ZUbXJaMk9oVnF1RUxZUkhuOTY5SHArZFhU\r\ndlYwaEQ5ZHQ5a3NSVE9wbTdnSkN5bzF2MlVhckpMSzdGRCtPZ1N3Y3kwNW9VSWhp\r\nNFV1ajRweGFoMzlrZzZlZUpTZHhtMHNiejBKNUM1bmZRSnhyYWMvOVBDVVJjQkpC\r\nSVJCOExTeGlJemdFTS9VQWkwaEIwdmdTZ0pqRzlSb05Wd2V1S0J6MWlGM0I0NzU2\r\ndXVjVmtOL1dvcG4rdWVwMVlDaEFlRGs3ZlcyUzR2anlocGJWa05STC81MDRUMVFR\r\nRTFhZ3JQdzdPREFvalhpaUZpaGtTbEZJUGxtMVlNY0k4UXdmOExCUXNHUTI4TTZC\r\ncFBya3ROQ0QwdjhxOVRjSnc9PTwvZHNpZzpTaWduYXR1cmVWYWx1ZT48ZHNpZzpL\r\nZXlJbmZvPjxkc2lnOlg1MDlEYXRhPjxkc2lnOlg1MDlDZXJ0aWZpY2F0ZT5NSUlG\r\nRURDQ0EvaWdBd0lCQWdJU0VTR1BVRnY2bnJkejlNUWhQZFVIb2dHTk1BMEdDU3FH\r\nU0liM0RRRUJDd1VBTUdBeEN6QUpCZ05WQkFZVEFrSkZNUmt3RndZRFZRUUtFeEJI\r\nYkc5aVlXeFRhV2R1SUc1MkxYTmhNVFl3TkFZRFZRUURFeTFIYkc5aVlXeFRhV2R1\r\nSUVSdmJXRnBiaUJXWVd4cFpHRjBhVzl1SUVOQklDMGdVMGhCTWpVMklDMGdSekl3\r\nSGhjTk1UVXdOREE1TVRVek9ETXlXaGNOTVRnd05qSTFNRFkwTWpRNFdqQlBNU0V3\r\nSHdZRFZRUUxFeGhFYjIxaGFXNGdRMjl1ZEhKdmJDQldZV3hwWkdGMFpXUXhLakFv\r\nQmdOVkJBTVRJWGRzYzA5ellrMXVaMlJXYVhBdWRXRjBMbU52Y25BdWRHVnNaVzVs\r\nZEM1aVpUQ0NBU0l3RFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VC\r\nQU1ESXRxSVRZUmRoY1dvOGZteW8wWlVRd0xmQ3doN2c4QndSQStFT2xuTUFLcXRX\r\nMG4vZ3JCRTRadThrQVZUNVpJUTlBZVU3STJNR0FOeks2MTBqU2ZRbWtHRElTUjF3\r\nWXBDbms2b1hxNWhQcFlHblJmRmtURW84d1VwZ1BXc3ZyTVR0RW9MeEVHdU1lZTYr\r\nd05RVXpsN1BHTEpGdkwvcE9QZ095Y2k3Sjh2U2d4ZVB3RFlURUJEa3RYOWtnRlBZ\r\ncXlVcVBTck94aDcyWmsrUFZjaHlVWDNzTFIrZ2VkcTFWQ2lISWdwQUVLMjNxL05W\r\nZlEwakRTaUhaMmZOc1lZdng3c1RlL0crR0w2djRnamxDNit5ODZ4U3lOZGFteHkv\r\nMmRPbGEyM2lWRDNoQ1d6amM1ZnpKTkc3OVRpUGVteWR1akhUcFg4MXhhUWs5aDFM\r\nUHRibzBzTUNBd0VBQWFPQ0FkTXdnZ0hQTUE0R0ExVWREd0VCL3dRRUF3SUZvREJK\r\nQmdOVkhTQUVRakJBTUQ0R0JtZUJEQUVDQVRBME1ESUdDQ3NHQVFVRkJ3SUJGaVpv\r\nZEhSd2N6b3ZMM2QzZHk1bmJHOWlZV3h6YVdkdUxtTnZiUzl5WlhCdmMybDBiM0o1\r\nTHpBc0JnTlZIUkVFSlRBamdpRjNiSE5QYzJKTmJtZGtWbWx3TG5WaGRDNWpiM0p3\r\nTG5SbGJHVnVaWFF1WW1Vd0NRWURWUjBUQkFJd0FEQWRCZ05WSFNVRUZqQVVCZ2dy\r\nQmdFRkJRY0RBUVlJS3dZQkJRVUhBd0l3UXdZRFZSMGZCRHd3T2pBNG9EYWdOSVl5\r\nYUhSMGNEb3ZMMk55YkM1bmJHOWlZV3h6YVdkdUxtTnZiUzluY3k5bmMyUnZiV0Zw\r\nYm5aaGJITm9ZVEpuTWk1amNtd3dnWlFHQ0NzR0FRVUZCd0VCQklHSE1JR0VNRWNH\r\nQ0NzR0FRVUZCekFDaGp0b2RIUndPaTh2YzJWamRYSmxMbWRzYjJKaGJITnBaMjR1\r\nWTI5dEwyTmhZMlZ5ZEM5bmMyUnZiV0ZwYm5aaGJITm9ZVEpuTW5JeExtTnlkREE1\r\nQmdnckJnRUZCUWN3QVlZdGFIUjBjRG92TDI5amMzQXlMbWRzYjJKaGJITnBaMjR1\r\nWTI5dEwyZHpaRzl0WVdsdWRtRnNjMmhoTW1jeU1CMEdBMVVkRGdRV0JCVG40ckhR\r\nMFF3MzhaTDdWTm1JSjVzWGpFeC85VEFmQmdOVkhTTUVHREFXZ0JUcVRuelVnQzNs\r\nRllHR0pveUNiY0NZcE0rWER6QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFIUHRY\r\nL2EvRXA4MWhWWnF0MWlKN1ArZ0dZaWhRL1pJRjNUMmdkMDlia0lIVjBUemNPQjhW\r\nQTM0ODdTSno4QkNCektkS2Jncng5K25uY2hYMlZrYURaNisySTM0a0ROczF3UDlW\r\nOUVxMlZKQTdudDk0S3ZqWWU2bjlidm5ZL1JPclNOSmxURVRNYkRSRWp1WEErMEp4\r\nczN4SFFQS1RvRUxkZHJROUxjWUw3ZEhEOUNuVHEreEkremlXWVVySWFPN1VHc1p3\r\nZ2tSa1BFZ201cnFyTjBndiswVVFXMEJra21BM1RuR2VDV2dRMVFRUHdKSzU3OVpw\r\nZ2R3VVNBTlZ0LzFpc2RrUzhmbGcrclBOUXljNnBZMUdMbFd5WEI5Y3FrRVpsamt4\r\nM2NUVmVKY01JSmtwRE4yRERpUHg4L1lPZUFwV05aNG9CVTRkc3FwSFVZLzFiUEZq\r\nL2c9PTwvZHNpZzpYNTA5Q2VydGlmaWNhdGU+PC9kc2lnOlg1MDlEYXRhPjwvZHNp\r\nZzpLZXlJbmZvPjwvZHNpZzpTaWduYXR1cmU+PHNhbWw6U3ViamVjdD48c2FtbDpO\r\nYW1lSUQgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6bmFtZWlk\r\nLWZvcm1hdDp0cmFuc2llbnQiIE5hbWVRdWFsaWZpZXI9IlRlbGVuZXQiIFNQTmFt\r\nZVF1YWxpZmllcj0idGVzdHNlcnZlci5iZW51bmV0cy5jb20iPmlkLUFRT3pzZ0pE\r\nUU1BbG8zdmxvS2NINVRSd1BmMC08L3NhbWw6TmFtZUlEPjxzYW1sOlN1YmplY3RD\r\nb25maXJtYXRpb24gTWV0aG9kPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6\r\nY206YmVhcmVyIj48c2FtbDpTdWJqZWN0Q29uZmlybWF0aW9uRGF0YSBJblJlc3Bv\r\nbnNlVG89Ik9ORUxPR0lOXzIxNjFiNTA1OTFmNjc1ZmUzZGM0MmZlYzRlZDJkOGU1\r\nMWRlZmQ2ZmQiIE5vdE9uT3JBZnRlcj0iMjAxNy0wMy0yOFQxOTo0ODo1M1oiIFJl\r\nY2lwaWVudD0iaHR0cHM6Ly90ZXN0c2VydmVyLmJlbnVuZXRzLmNvbS9hZG1pbi9z\r\nZWN1cmUvZGFzaGJvYXJkIi8+PC9zYW1sOlN1YmplY3RDb25maXJtYXRpb24+PC9z\r\nYW1sOlN1YmplY3Q+PHNhbWw6Q29uZGl0aW9ucyBOb3RCZWZvcmU9IjIwMTctMDMt\r\nMjhUMTk6MzM6NTNaIiBOb3RPbk9yQWZ0ZXI9IjIwMTctMDMtMjhUMTk6Mzg6NTNa\r\nIj48c2FtbDpBdWRpZW5jZVJlc3RyaWN0aW9uPjxzYW1sOkF1ZGllbmNlPnRlc3Rz\r\nZXJ2ZXIuYmVudW5ldHMuY29tPC9zYW1sOkF1ZGllbmNlPjwvc2FtbDpBdWRpZW5j\r\nZVJlc3RyaWN0aW9uPjwvc2FtbDpDb25kaXRpb25zPjxzYW1sOkF1dGhuU3RhdGVt\r\nZW50IEF1dGhuSW5zdGFudD0iMjAxNy0wMy0yOFQxOTozMzo1M1oiIFNlc3Npb25J\r\nbmRleD0iaWQtWEVRcWVNZFRiRHRaLXNhaFN4ZnNYdVA2MWlJLSIgU2Vzc2lvbk5v\r\ndE9uT3JBZnRlcj0iMjAxNy0wMy0yOFQyMDozMzo1M1oiPjxzYW1sOkF1dGhuQ29u\r\ndGV4dD48c2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6\r\ndGM6U0FNTDoyLjA6YWM6Y2xhc3NlczpQYXNzd29yZFByb3RlY3RlZFRyYW5zcG9y\r\ndDwvc2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj48L3NhbWw6QXV0aG5Db250ZXh0\r\nPjwvc2FtbDpBdXRoblN0YXRlbWVudD48L3NhbWw6QXNzZXJ0aW9uPjwvc2FtbHA6\r\nUmVzcG9uc2U+\r\n",
"RelayState": "https://testserver.benunets.com/admin/login"
}
kernel.php
I can only see this response only because I comment out my CFRF token on my app/Http/kernel.php
// \App\Http\Middleware\VerifyCsrfToken::class,
ROUTE
Route::post('admin/secure/dashboard', 'SAMLController#post');
CONTROLLER
public function post(){
return Input::all();
}
What is the best practice to deal with SAML POST and still maintaining CSRF protection ?
Should I create a middleware or anything similar to that ?
You may exclude your endpoint by adding it to the $except property of the VerifyCsrfToken middleware.
After that you may want to add your own middleware to check if the post request came from an origin you explicitly accept.
The documentation of the package also states that you should configure a middleware group in te config which at least needs the StartSession middleware. So you can make a special middleware-group which excludes the VerifyCsrfToken middleware. However, I do believe it would be better to exclude the endpoint, and add your own middleware check.
Also, you are referencing the url admin/secure/dashboard. Are you using this for debugging the POST request? Because I believe the actual endpoint for iDP needs to be https://your-url.com/saml2/acs (unless you changed the default configuration). This page will use the post data to trigger an event with which you can login the appropriate user.