Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Receiving unauthenticated after successful login and receiving cookies #80

Closed
mattg1995 opened this issue Mar 4, 2020 · 42 comments
Closed

Comments

@mattg1995
Copy link

mattg1995 commented Mar 4, 2020

  • Airlock Version: 1.0.0
  • Laravel Version: 7.0.1
  • PHP Version: 7.3.11
  • Database Driver & Version: 10.3.15-MariaDB Homebrew

Description:

After successfully hitting the airlock/csrf-cookie endpoint and logging in I still receive unauthenticated when hitting my API in subsequent requests. I can see the cookies being sent in the request (XSRF-TOKEN and the session) but it still will not authenticate with the airlock middleware.

Screenshot 2020-03-04 at 10 24 16

SESSION_DOMAIN=.hub.test
AIRLOCK_STATEFUL_DOMAINS=front.hub.test

Cors config:

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Laravel CORS Options
    |--------------------------------------------------------------------------
    |
    | The allowed_methods and allowed_headers options are case-insensitive.
    |
    | You don't need to provide both allowed_origins and allowed_origins_patterns.
    | If one of the strings passed matches, it is considered a valid origin.
    |
    | If array('*') is provided to allowed_methods, allowed_origins or allowed_headers
    | all methods / origins / headers are allowed.
    |
    */

    /*
     * You can enable CORS for 1 or multiple paths.
     * Example: ['api/*']
     */
    'paths' => ['api/*', 'airlock/csrf-cookie', 'login', 'logout'],

    /*
    * Matches the request method. `[*]` allows all methods.
    */
    'allowed_methods' => ['*'],

    /*
     * Matches the request origin. `[*]` allows all origins.
     */
    'allowed_origins' => ['*'],

    /*
     * Matches the request origin with, similar to `Request::is()`
     */
    'allowed_origins_patterns' => [],

    /*
     * Sets the Access-Control-Allow-Headers response header. `[*]` allows all headers.
     */
    'allowed_headers' => ['*'],

    /*
     * Sets the Access-Control-Expose-Headers response header.
     */
    'exposed_headers' => false,

    /*
     * Sets the Access-Control-Max-Age response header.
     */
    'max_age' => false,

    /*
     * Sets the Access-Control-Allow-Credentials header.
     */
    'supports_credentials' => true,
];

Please can you give some guidance on this, I have tried all the relevant channels (slack, discord etc) and still not able to solve the issue

Thank you

@migueldevpt
Copy link

This is happening to me too in the following project.
https://github.com/migueldamaso/test-airlock

@driesvints
Copy link
Member

Please ask this on a support channel.

Thanks.

@mattg1995
Copy link
Author

I have tried all relevant channels multiple times

@mattg1995
Copy link
Author

This seems to be a common issue amongst the people I've talked to in various channels. Would it be possible to look into this please would be appreciated @driesvints

@simonmsara
Copy link

simonmsara commented Mar 4, 2020

@driesvints we would appreciate it if you stopped closing the issues without pointing to the solution, this is probably a bug. I am getting the unauthenticated response even when the SPA is served directly from the Laravel app.

@danpastori
Copy link

Did you try setting the SESSION_DRIVER to cookie? That did it for me.

@migueldevpt
Copy link

Hello everyone i managed to get my airlock app working. The problem was that the default AIRLOCK_STATEFUL_DOMAINS value is localhost. This means that if you are using artisan serve you must use localhost:8000 instead of 127.0.0.1:8000.
I hope this helps

@migueldevpt
Copy link

migueldevpt commented Mar 5, 2020

If anyone needs my code is is https://github.com/migueldamaso/test-airlock
And my .env is:

`APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost

LOG_CHANNEL=stack

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=
DB_USERNAME=
DB_PASSWORD=

BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1

MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
`

Don't forget the db credentials

@driesvints
Copy link
Member

Hey everyone,

Over the past two months since Airlock was released we have gotten tons of issues involving cookies, CSRF, and other things. Every single one of them was the result of a misconfiguration somewhere or not reading the docs well enough.

We have dozens of open source repos to attend. There's still over 300 other issues that need my attention and I can't possible offer the same attention to every single one of them. This isn't a support channel and we have numerous other channels where there's a large community ready to help you out. Especially the Discord channel and Laracasts forums are very active.

Please try to use a support channel. If you find solutions to your problems we'd really appreciate a pr to the docs if something could be explained better.

@phiter calling people lazy isn't helping out anyone. We work hard to offer all of this for free.

@driesvints
Copy link
Member

I also want to add that we appreciate it that you're using Airlock and want to help make it better. I'm genuinely sorry that I can't help out more. If I find some free time later on I'll maybe try to look into this.

@laravel laravel locked and limited conversation to collaborators Mar 5, 2020
@laravel laravel unlocked this conversation Mar 5, 2020
@taylorotwell
Copy link
Member

If there is a bug, find it and send a PR. Welcome to open source. Airlock is a simple package and doesn’t contain much code. Airlock works for me and others and as Dries noted all of these issues have been configuration problems so far. But, we welcome and look forward PRs to fix any bugs.

@simonmsara
Copy link

Hi guys, I would like to start by saying your efforts and contributions to the industry are greatly appreciated and we do not take them for granted, even though we throw our toys out of the pram here and there; it's not you it's us 😂.

I think I might have found the issue that's causing the authentication failure – Airlock's guard is trying to get the user from the 'web' guard which is returning null but switching to the 'api' guard is returning the authenticated user. If it's not a bug then this might be a clue as to why it's failing?

Thanks again for the help ✌️

@simonmsara
Copy link

I think I might have found the issue that's causing the authentication failure – Airlock's guard is trying to get the user from the 'web' guard which is returning null but switching to the 'api' guard is returning the authenticated user. If it's not a bug then this might be a clue as to why it's failing?

The 'web' guard is used to get the authenticated user instance but this can be changed in the auth config by changing the default guard to anything else. I have made a PR to use the configured default guard but still pass in the 'web' as a fallback. If this isn't the way to go we will need to update the docs to say your default guard should be set to 'web'.

@evansmwendwa
Copy link

The issue tends to be in one of two areas. AIRLOCK_STATEFUL_DOMAINS configuration or the auth guard for your routes which needs to be updated yo use airlock

@phiter
Copy link

phiter commented Mar 8, 2020

In my case I had the default guard as api, but airlock only works with web so I needed to run auth('web')->login($user); and it worked

@nolros
Copy link

nolros commented Apr 7, 2020

The key issue here are the cookies. You need to manage them manually if you have any hope of making this work in production. For example, if you login and then attempt to login again via JS, the guard will identify you as logged in and redirect you to home, which will result in html in your data field. Even if you auth('web')->logout($user), you will still run into the issue that it might not logout as Sanctum looks to the cookies to determine logged in status. Sometimes you can authenticate but because of the cookies your status will still remain unauthenticated. Therefore, if you logout you need to delete the cookies manually to be ensure you have actually logged out. If you login, you need to delete the cookies. You can decorate Authenticate middleware to do a number of checks and also config middleware in your Auth controllers. Other option create your own middleware, and/or decorate the Auth controllers of Auth::routes and/or make your own Auth controller and remove Auth::routes. If you use Vuex and VueRouter then you need to implement the same Laravel guard logic.

@bciriak
Copy link

bciriak commented Jun 20, 2020

Hey guys, for me the problem was that I was setting the "SANCTUM_STATEFUL_DOMAINS" to my api domain which sits on port 8000 (localhost:8000). When I changed it to my Vue SPA domain port which is 8080 (localhost:8080) it worked. So maybe just check that.

@ianrussel
Copy link

@driesvints we would appreciate it if you stopped closing the issues without pointing to the solution, this is probably a bug. I am getting the unauthenticated response even when the SPA is served directly from the Laravel app.

Did you solve this? I also have this issue. My react js lives in same laravel project, inside resources/js

@morris14
Copy link

Setting 'SANCTUM_STATEFUL_DOMAINS' works for me. Thanks for all the hard work @taylorotwell @driesvints 👍

@vermadilipjpr
Copy link

Try like this: Auth::login($user, true);
It might help.

@tsangaris
Copy link

tsangaris commented Oct 6, 2020

I have the same issue with API to be http://api.example.test (Homestead) and my VUE Cli SPA to be at http://example.test:3000.

Don't know how to overcome this issue with the 401 Unauthenticated.

Any ideas?

=======================

Turns out that while creating my user in Tinker, for some reason Hash::make('password'); went wrong. So i couldn't authenticate due to wrong password.

@ipearx
Copy link

ipearx commented Oct 12, 2020

Anyone new, be aware to use SANCTUM_STATEFUL_DOMAINS instead of AIRLOCK_STATEFUL_DOMAINS in your .env file.

That's what caught me out. I'm guessing the name of the project changed through development? So some comments are old and use the wrong name.
This will be needed if you're using a custom domain e.g. I use myprojectname.test locally. Would be good to add this to the documentation.

@stanliwise
Copy link

stanliwise commented Oct 19, 2020

For anyone having the Unauthentication error, please ensure you follow this steps.

  • Send a post request to /sanctum/csrf-cookie
  • Send a post request to web route /login to get authenticated. This is important sanctum authenticate using the web route and not api route

After this step you will be successfully authenticated by auth:sanctum middleware in API route.

Other things to be aware of:

  1. Ensure your SESSION_DOMAIN is set to localhost or your host without port
  2. SANCTUM_STATEFUL_DOMAIN is set to your sub domain/SPA IP with the port e.g localhost:8000
  3. Also set SESSION_DRIVER=cookie

@insidert
Copy link

This is because of misconfiguring the sanctum and session domains.

  • Make sure the laravel app is serving from localhost (127.0.0.1) by doing the good old php artisan serve. Do not use virtual hosts because you cannot serve the front-end apps from the same virtual host.
  • Check the port numbers of your front-end app. Usually, React app serves at http://localhost:3000 and Vue app serve from http://localhost:8080.
  • It is necessary for the front-end app(s) and the laravel app to serve from the same domain - localhost in our case.
  • Set sanctum stateful domains in .env file. These are the addresses of our front-end apps including the port numbers.
SANCTUM_STATEFUL_DOMAINS=localhost:8080,127.0.0.1:8080,localhost:3000,127.0.0.1:3000
  • Set session domain in .env file. You need to change this at production to your domain name.
SESSION_DOMAIN=localhost
  • Set paths and supports_credentails in cors.php The routes of web.php you wish to have access to in your front-end app should be added to the paths array.
'paths' => ['api/*', 'login', 'register', 'otp/*', 'sanctum/csrf-cookie'],

'supports_credentials' => true,
  • And finally, you should make requests from the front-end app to the localhost/api/other-route but not to 127.0.0.1/api/other-route using axios.

@ipearx
Copy link

ipearx commented Oct 29, 2020

@insidert

Make sure the laravel app is serving from localhost (127.0.0.1) by doing the good old php artisan serve. Do not use virtual hosts...

I'm using Sanctum with Apache Virtual Hosts even with wildcard subdomains, and it works fine once I set the stateful domains correctly. My front end is served by the same app as my backend. Keep in mind some apps have to share web servers when deployed.

I'm using this config in my .env file:

SANCTUM_STATEFUL_DOMAINS=.mydomain.test,mydomain.test

@Aslam97
Copy link

Aslam97 commented Nov 14, 2020

Setting SANCTUM_STATEFUL_DOMAINS without protocol.
Setting SESSION_DRIVER to cookie
Include login in paths and enable supports_credentials work for me

@csimpi
Copy link

csimpi commented Apr 11, 2021

@Aslam97
Are you sure you need to set SESSION_DOMAIN to cookie?
I think you mix it up with SESSION_DRIVER which value should be cookie indeed

@Aslam97
Copy link

Aslam97 commented Apr 11, 2021

@csimpi ah my mistake. edited

@hectordommo
Copy link

Some other tip is that you have to setup EnsureFrontendRequestsAreStateful in the api middlewareGroups at app/Http/Kernel.php as so:

'api' => [
            EnsureFrontendRequestsAreStateful::class,
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

@altercode
Copy link

For those who are using NEXT JS as an SPA DO NOT call axios from inside getServerSideProps or getStaticSiteProps!
Instead use useEffect hook to fetch data from external API.

@esmaily
Copy link

esmaily commented Jul 7, 2021

I'm config all settings for sanctum but not working.
SESSION_DRIVER=cookie SESSION_DOMAIN=localhost SANCTUM_STATEFUL_DOMAINS=localhost,127.0.0.1:8000,localhost:3000 'supports_credentials' => true, 'paths' => [ 'api/*', 'login', 'register', 'logout', 'sanctum/csrf-cookie' ], axios.defaults.withCredentials = true

@budiodank
Copy link

If you are using PHP FastCGI and Apache to serve your Laravel application, HTTP Basic authentication may not work correctly. To correct these problems, the following lines may be added to your application's .htaccess file:

RewriteCond %{HTTP:Authorization} ^(.+)$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

Reference :
https://laravel.com/docs/8.x/authentication

@elidrissidev
Copy link

FWIW, I was scratching my head for a full day only to realize the issue was related to browser cache, switching to Firefox worked. 🤷

@SinMu-L
Copy link

SinMu-L commented Sep 19, 2022

这是因为错误配置了 sanctum 和 session 域。

  • 确保 laravel 应用程序从 localhost (127.0.0.1) 提供服务,方法是做旧的php artisan serve.不要使用虚拟主机,因为您无法从同一虚拟主机提供前端应用程序。
  • 检查前端应用程序的端口号。通常,React 应用服务于http://localhost:3000.Vue 应用服务于http://localhost:8080.
  • _前端应用程序_和_laravel 应用程序_必须从同一个域提供服务 - 在我们的例子中是 localhost。
  • 在.env 文件中设置圣所状态域。这些是我们前端应用程序的地址,包括端口号。
SANCTUM_STATEFUL_DOMAINS=localhost:8080,127.0.0.1:8080,localhost:3000,127.0.0.1:3000
  • 在.env 文件中设置会话域。您需要在生产时将其更改为您的域名。
SESSION_DOMAIN=localhost
  • 在 cors.php 中设置路径和 support_credentails 您希望在前端应用程序中访问的 web.php的_路由_应_添加_到路径数组_中_。****__
'paths' => ['api/*', 'login', 'register', 'otp/*', 'sanctum/csrf-cookie'],

'supports_credentials' => true,
  • 最后,您应该从前端应用程序向_localhost/api/other-route_发出请求,而不是使用 axios向_127.0.0.1/api/other-route发出请求。_

Thanks
I modified the configuration as follows
.env

SESSION_DRIVER=cookie
SANCTUM_STATEFUL_DOMAINS=127.0.0.1:8000
SESSION_DOMAIN=127.0.0.1

Then start laravel by command
php artisan serve

@lcsfort
Copy link

lcsfort commented Jan 8, 2023

Hello everyone, for me the solution was to add the \Illuminate\Session\Middleware\StartSession::class middleware in the api middlewareGroups at app/Http/Kernel.php

'api' => [ 
    \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
    'throttle:api',
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
    \Illuminate\Session\Middleware\StartSession::class
],

@stanliwise
Copy link

Hello everyone, for me the solution was to add the \Illuminate\Session\Middleware\StartSession::class middleware in the api middlewareGroups at app/Http/Kernel.php

'api' => [ 
    \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
    'throttle:api',
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
    \Illuminate\Session\Middleware\StartSession::class
],

Never use a session on api calls that would reap open your api to cross site script attack. It’s dangerous

@lcsfort
Copy link

lcsfort commented Jan 8, 2023

@stanliwise Thanks 🙏

@stanliwise
Copy link

@stanliwise Thanks 🙏

Sanctum session auth is basically for SPA applications that uses the cookie based authentication. If you’re using api calls simple use the plain text token method and pass it as bearer.

@lcsfort
Copy link

lcsfort commented Jan 8, 2023

@stanliwise I'm using sanctum cookie-based auth strategy for a react SPA

@stanliwise
Copy link

@stanliwise I'm using sanctum cookie-based auth strategy for a react SPA

Are you aware of

EnsureFrontendRequestsAreStateful middleware?

@lcsfort
Copy link

lcsfort commented Jan 8, 2023

Yes, I'm aware of it. I'm using it as well.

@chimobi-justice
Copy link

I guess the best way go configure your laravel sanctum and SPA is to configure your laravel ENV file properly and also add
the withCredentials: true, at your axios config it works for me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests