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.
Related
I'm trying to implement IPN in my Laravel project, a post request from my website is working thanks to "csrf",
i try to implement it like written here:
https://developer.paypal.com/docs/api-basics/notifications/ipn/ht-ipn/
in my routes/web.php:
Route::post('i', [IController::class, 'y'])->name('i');
and in IController whats written on the side:
public function y()
{
error_log('function y called');
// STEP 1: read POST data
// Reading POSTed data directly from $_POST causes serialization issues with array data in the POST.
// Instead, read raw POST data from the input stream.
$raw_post_data = file_get_contents('php://input');............
The error_log doesn't show up, means the function is never entered.
Question: How can i force Laravel to except POSTS From Paypal?
You can Exclude URIs From CSRF Protection in laravel.
Goto App\Http\Middleware\VerifyCsrfToken and add url which you want to exclude csrf token.
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* The URIs that should be excluded from CSRF verification.
*
* #var array
*/
protected $except = [
'i',
];
}
As document says
Sometimes you may wish to exclude a set of URIs from CSRF protection.
For example, if you are using Stripe to process payments and are
utilizing their webhook system, you will need to exclude your Stripe
webhook handler route from CSRF protection since Stripe will not know
what CSRF token to send to your routes.
Typically, you should place these kinds of routes outside of the web
middleware group that the App\Providers\RouteServiceProvider applies
to all routes in the routes/web.php file. However, you may also
exclude the routes by adding their URIs to the $except property of the
VerifyCsrfToken middleware:
Ref:https://laravel.com/docs/8.x/csrf#csrf-excluding-uris
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 have a React SPA in the same Laravel project. The login/signup/logout and all other js views are in the js folder and use axios api calls for all POST/GET requests. I want to use the default Laravel session based web authentication for the embedded SPA, since it's in the same project folder and it will be the only javascript client accessing it. This api does not need to be open to the public, just for this react app, and it's an SPA for the speed and good user experience instead of full page reloads.
I've tried using Passport before, and for over a month, I still can't get it to work as intended. I do not want to deal with tokens, access tokens, refresh tokens, revoking tokens, CSRF, etc. Just the out of the box simple Laravel session based auth that works so easily on web, but want it to work on my react app. The only blade file is the index.blade.php which includes the react app.js
Any idea how we can accomplish this?
UPDATE 1:
After implementing #ceejayoz's suggestion:
You have to add the various Session/Cookie middlewares in
app/Http/Kernel.php (stuff like
\Illuminate\Session\Middleware\StartSession::class) to the API routes.
I added to $middlewareGroups.api to match the web middleware in app/Http/Kernel.php:
'api' => [
'throttle:60,1',
'bindings',
// Newly added middleware to match web middleware
\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,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
I realized there are two issues that occurred:
In the sessions table, even if not logged in, when loading app home page (or any page), multiple sessions are inserted into the sessions table. Shouldn't a new single session be inserted into this table only after user login?
After user log in, when refreshing the page manually in the browser and a call is made to a protected route, I get a 401 Unauthenticated which points me to this method in Illuminate/Auth/GuardHelpers.php:
public function authenticate() {
if (! is_null($user = $this->user())) {
return $user;
}
throw new AuthenticationException; // throws this 401 exception on logged in page refresh when fetching data from private route
}
Some additional notes:
In config/auth.php I updated the guards.api.driver to session instead of token.
In routes/api.php I have the protected routes wrapped in auth middleware like this: Route::group(['middleware' => 'auth'], function() { PRIVATE ROUTES HERE }
In config/session.php I have 'domain' => '.mydomain.com'
I am sending back these headers with each axios api request like this:
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
let token = document.head.querySelector('meta[name="csrf-token"]');
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
Any idea how we can fix these 2 issues?
Looks like your session was not persistent.
Check if you changed any values in config/session.php that might create problems.
You can check default sesion config values here
From the comments, #Wonka solved his problem by changing
'same_site' => 'strict'
to
'same_site' => null
It's doable (and I've done the same myself for some apps).
By default, the routes in routes/api.php don't have sessions available, but you can add the various Session/Cookie middlewares in app/Http/Kernel.php (stuff like \Illuminate\Session\Middleware\StartSession::class) to the API routes.
You can, as #ljubadr suggested, also put the API routes right in routes/web.php instead, although that'd probably mean you'd need to make other changes (like removing CSRF protection from the web routes).
So I have an application that sends an AJAX request to an external server which does some stuff then makes a post call to the laravel application that made the initial call.
So I am trying to do a POST call to the laravel application. Now from the AJAX request i am sending the csrf_token()
Here are the headers I've put into my post request:
X-CSRF-TOKEN: LO8Dg7j1jZssXXGSLIa8inBgh2Y1QSsp6Birc1Ui
X-Requested-With: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded
That token belongs to the logged in user that made the AJAX request. Now the problem i'm getting is from this i get a TokenMismatchException500 error.
Is there something else I need to do in my external post calls headers in order to not encounter this error?
As i've got the CSRF token i am using a rest client to try send a test post using those headers and I get the same error?
The aim is on the recieving laravel app controller will then be able to use the token and i'll be able to use $request->user(); to get the user.
Note the recieving route has the web middleware attached to it.
Since you are making request from another server external url.Because of this you are getting erorr.Csrf token works with the same application not working if you try to exicute from other application. so you can disable csrf token.
if you want to disable token for all request then add this in VerifyCsrfToken
protected $except = [
'/*',
];
Excluding URIs From CSRF Protection
Sometimes you may wish to exclude a set of URIs from CSRF protection. For example, if you are using Stripe to process payments and are utilizing their webhook system, you will need to exclude your Stripe webhook handler route from CSRF protection since Stripe will not know what CSRF token to send to your routes.
Typically, you should place these kinds of routes outside of the web middleware group that the RouteServiceProvider applies to all routes in the routes/web.php file. However, you may also exclude the routes by adding their URIs to the $except property of the VerifyCsrfToken middleware:
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;
class VerifyCsrfToken extends BaseVerifier
{
/**
* The URIs that should be excluded from CSRF verification.
*
* #var array
*/
protected $except = [
'stripe/*',
];
}
Ref:
https://laravel.com/docs/5.5/csrf
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.