-1

I have read too many solutions but still not solved my issue. I am using Laravel (sanctum) in backend and Next js in front-end.

Laravel version: 9 Backend Url: http://127.0.0.1:8000 Front-End url: http://localhost:3000

Cors.php

    'paths' => ['api/*', 'sanctum/csrf-cookie','login','logout',],

    'allowed_methods' => ['*'],

    'allowed_origins' => ['http://127.0.0.1:3000'],

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],

    'exposed_headers' => [],

    'max_age' => 0,

    'supports_credentials' => true,

Karnel.php

  */
    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,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

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

config/sanctum.php


    'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
        '%s%s',
        'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
        Sanctum::currentApplicationUrlWithPort()
    ))),

    /*
    |--------------------------------------------------------------------------
    | Sanctum Guards
    |--------------------------------------------------------------------------
    |
    | This array contains the authentication guards that will be checked when
    | Sanctum is trying to authenticate a request. If none of these guards
    | are able to authenticate the request, Sanctum will use the bearer
    | token that's present on an incoming request for authentication.
    |
    */

    'guard' => ['web'],

.env

SESSION_DRIVER=cookie
SANCTUM_STATEFUL_DOMAINS=localhost:3000
SESSION_DOMAIN=localhost

.htaccess file on public folder

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews -Indexes
    </IfModule>

    RewriteEngine On

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} (.+)/$
    RewriteRule ^ %1 [L,R=301]

    # Send Requests To Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>

Route/Api.php


Route::get('/user', [AuthController::class, 'me'])->middleware('auth:sanctum');

AuthController

public function me(Request $request)
{
  return response()->json([
    'status' => 'success',
    'message' => 'Data Fetch Success',
    'data' => [
        "name" => "Zahid Hasan Raju",
    ],
  ]);
}

Axios Request from

import Head from "next/head";
import axios from "axios";

export default function Home() {
 
  const getConfig = {
    method: "get",
    url: "http://localhost:8000/api/user",
    withCredentials: true,
  };



  const handleClick = async () => {
    await axios(getConfig).then((res) => console.log(res.data));
    alert("success");
  };

  return (
    <>
      <Head>
        <title>Home Page</title>
      </Head>
      <h1>Home Page</h1>
      <button className='btn btn-success' onClick={handleClick}>
        Fetch user
      </button>
    </>
  );
}

Result

result

My expectation SPA is authenticated using Sanctum from backend, so i need to show some data in frontend without login.

when i logged in , then i can get session cookie / Barer token for an user. Using this Barer token or session i can get data and do everything.

Without login it's saying ""Unauthenticated.""

suppose i have a list of product in my database, and i want to show the product list from backend to front-end without login, then how can i get the data list?

juliomalves
  • 42,130
  • 20
  • 150
  • 146
  • Does this answer your question? [Laravel sanctum unauthenticated](https://stackoverflow.com/questions/60843137/laravel-sanctum-unauthenticated) – steven7mwesigwa Jan 23 '23 at 06:35
  • no, i did not get my answer there. I want to show data in my frontend without loggedin or without bearer token. how can i get the data from backend? – zahid hasan Jan 23 '23 at 07:00
  • If you plan to authenticate a SPA, your front app have to be authenticated from front-side and the Laravel's cookie based sessions will be attached to the next requests. As a general answer I recommend you to check your current cookie in client side. If it is not set, there is sth wrong. – Hamid Haghdoost Jan 23 '23 at 07:23
  • in you routes/api.php , add new route without middleware checking for authentication, for example `Route::get('/products', [ProductController::class, 'list']);` – Win Jan 23 '23 at 08:09
  • @win without middleware i got the data, but it's risky. Without Middleware anyone can stole my data using this route. How can i protect this route only for my SPA access? – zahid hasan Jan 23 '23 at 08:42
  • *I want to show data in my frontend without loggedin or without bearer token. how can i get the data from backend?* Without logging in and submitting a token via the HTTP `Authorization` request header, how would [Laravel Sanctum](https://laravel.com/docs/9.x/sanctum) differentiate your request from that of a guest user?‍♀️ – steven7mwesigwa Jan 23 '23 at 08:57
  • [Unauthenticated Message In Sanctum](https://stackoverflow.com/questions/75166556/unauthenticated-message-in-sanctum) – steven7mwesigwa Jan 23 '23 at 09:02
  • @zahidhasan I suggest for data you create your own (forever) token with a custom api middleware to check it (and preferable to log it as well), just for communication between front and backend. with this custom middleware you can differeanciate between "guest request" (no middleware) , "your front app requesting essential data" (custom middleware) and "logged in user" (api:sanctum) – Win Jan 23 '23 at 09:49

1 Answers1

0

I'm not sure if this is the best approach, but I always just create another middleware that can handle both authenticated and un-authenticated request with working with sanctum since the auth:sanctum would just redirect to login or return un-authenticated message if call via api and you use it.

create your middle first php artisan make:middleware GuestOrAuth

then use Auth facades to handle the authentication if the request contains bearer token

something like below

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class GuestOrAuth {
    
    public function handle(Request $request, Closure $next) {

        if ($request->bearerToken()) 
            Auth::setUser( Auth::guard('sanctum')->user() );
            
        return $next($request);
    }
}

then on Kernel.php add that middleware under $routeMiddleware

protected $routeMiddleware = [
    .
    .
    .
    'guest.or.auth' => \App\Http\Middleware\GuestOrAuth::class
];

Then you'd be able to use like below which return the user if they are logged-in and return anything you want if not logged-in

Route::middleware(['guest.or.auth'])->get('/test', function() {
    return auth()->user() ?? 'Not logged-in!';
});
silver
  • 4,433
  • 1
  • 18
  • 30
  • I can manage user authentication and it's working fine, No issue for user authentication. Suppose I have 50 products, so i have to show all products in home page (in next js). so, this product data how can i get from backend laravel with sanctum guard? – zahid hasan Jan 23 '23 at 08:45
  • 1
    I already explained above, sanctum middleware will check if your request is authenticated before it proceeds with your controller method, and will throw un-authenticated message, I dont get what you are expecting? – silver Jan 23 '23 at 08:54