Search code examples
laravelaxiossingle-page-applicationheadless-cmslaravel-7

How to log in from a single page react app to Laravel 7.x on another domain?


I have a single page create-react-app running on localhost:3000 and I want to log in to a laravel 7.x instance running on myapp.loc (vhost).

Eventually I would like a single page running on app.mysite.com with laravel running on api.mysite.com.

I'm able to log in to my laravel instance directly from myapp.loc. I've installed Laravel passport and the scaffolding, etc and can create Client IDs and Secrets, but I'm unsure if they are needed and if so, how to use them.

What I am unsure of and cannot find any documentation for, is how to log in to laraval from my SPA (running on localhost:3000). I have set my CORS headers and can connect requests that don't require auth, but I don't know how to log in or structure auth requests once logged in.

I can't find any documentation on axios.post / get requests with a focus on logging in from another domain and maintain user-based access.

Since I don't know enough to ask a concise question, there are three layers that I feel like I should be searching for an answer.

  1. Is it possible for laravel to act as the backend for my single page app from another domain?
  2. If so, are there documented, best practices / well worn paths for accomplishing this?
  3. If so, what would a sample axios login and subsequent session call look like? (e.g. payload and header shape)

Solution

    1. Yes you can, I suggest to use https://laravel.com/docs/7.x/sanctum instead of passport because is easier to setup and it was created especially for this scenario.

    2. You need to configure CORS using the official Laravel Package https://github.com/fruitcake/laravel-cors this way you will open Laravel's CORS to be able to reach it from anywhere localhost, or any domain that you can set up into allowed_origins. inside the cors.php config file according to the documentation of the package.

    3. After configuring Sanctum/Passport and ensuring you are generating the required token for your SPA using the createToken method described in Sanctum or Passport docs, you have to save the token to connect to your protected endpoints however they recommend to use cookie SPA based authentication but that's not strictly necessary.

    Create an API Service

    In this example I will create an API Service to encapsulate API calls

    import axios from 'axios';
    
    const URI = 'https://yourlaravel.api/api/';
    
    axios.defaults.headers.common = { Accept: 'application/json', 'Content-Type': 'application/json' };
    
    const ApiInstance = axios.create();
    
    const API = {
      login: (user) => {
        return ApiInstance.post(`${URI}login`, user);
      },
      getUser: () => {
        return ApiInstance.get(`${URI}user`);
      },
      setUser: (user) => {
        return ApiInstance.post(`${URI}user`, user);
      },
    };
    

    Send A Login Request to your login endpoint and save the token

    import API;
    
    
    API.login({email:'[email protected]',password:'32323'})
        .then(response=>{
          //save the token
          //response.data.accessToken  
    })
    
    

    Fetch data from your protected endpoints using the token

    //Set the default authorization header when you have an access token
    axios.defaults.headers.common = {'Authorization': `Bearer ${token}`}
    
    
    //Get your data
    
    API.getUser().then(response=>{
          //response.data
    })
    
    //Post something
    
    API.setUser({user:'Os'}).then(response=>{
          //response.data
    })