Nuxt js: how to use proxy in laravel sanctum? - proxy

Nuxt js NOTE: It is highly recommended to use proxy to avoid CORS and same-site policy issues.
I couldn't understand the use of "target" and "pathRewrite
" in the proxy.
who can describe them?
if my backend(laravel) URL be localhost:8000 and my frontend(Nuxt) URL be localhost:3000 then how should I config it?

You may use Axios proxy in NuxtJS like this:
export default {
axios: {
credentials: true,
proxy: true,
debug: process.env.NODE_ENV !== 'production',
},
proxy: {
'/api/': process.env.API_URL,
},
auth: {
redirect: {
login: '/auth/login',
logout: '/auth/login',
callback: '/auth/login',
home: '/feed',
},
strategies: {
laravelSanctum: {
provider: 'laravel/sanctum',
url: 'api', // note the URL here.
endpoints: {
login: {
url: '/auth/login',
},
logout: {
url: '/auth/logout',
},
user: {
url: '/auth/me',
},
},
},
}
}
}
I couldn't understand the use of "target" and "pathRewrite " in the proxy.
Let's say your API_URL is localhost:8000.
If you write proxy config like this:
proxy: {
'/api': process.env.API_URL,
},
It will add /api at the end of the URL. So your API_URL will be localhost:8000/api.
Now you may call API request with Axios like this:
this.$axios.$get('api/me');
In the behind, it will call to this URL: localhost:8000/api/me.
If you write your proxy config like this:
proxy: {
'/api': {
target: process.env.API_URL,
pathRewrite: { '^/api': '/' }
}
},
It will remove /api from the end of the URL. So your API_URL will be localhost:8000.
Now you may call API request with Axios like this:
this.$axios.$get('api/me');
In the behind, it will call to this URL: localhost:8000/me.
Enjoy :)

Related

Nuxtjs Auth module with Laravel Sanctum Provider

I have integrated the nuxt/auth module with the Laravel Sanctum provider and the login works fine, the problem is when I want to remember the user.
I sent to the api a boolean parameter with the name remember and in the api the option remember is assigned well, the token is saved in the user table and the nuxt/auth module sets the cookie remember_web_59ba36addc2b2b2b2f9401580f014c7f58ea4e30989d but if I set the SESSION_LIFETIME to 5 minutes when I refresh the page after 5 minutes the user is disconnected and does not keep the session until 2027 which is the date assigned to the cookie, I attach an image with the dates of the cookies.
nuxt.config.js
auth: {
strategies: {
'laravelSanctum': {
provider: 'laravel/sanctum',
url: process.env.BASE_URL
},
}
},
// Axios module configuration: https://go.nuxtjs.dev/config-axios
axios: {
baseUrl: process.env.BASE_URL,
credentials: true
},
And on the login page
this.$auth.loginWith('laravelSanctum', {
data: this.form
})
The cookies with the times
in nuxt.config.js
axios: {
baseURL: 'http://localhost/twillo-api/api'
},
auth: {
redirect: {
login: '/account/login',
callback: '/account/login',
home: '/'
},
strategies: {
local: {
token: {
property: 'data.accessToken',
required: true,
global: true,
maxAge: 43200,
type: 'Bearer',
name: 'Authorization'
},
user: {
property: 'user',
autoFetch: false
},
endpoints: {
login: { url: '/login', method: 'post' },
},
localStorage: {
prefix: 'auth.'
}
}
},
},
And on the login page
setUniversal will store user record in cookie.
this.$auth.loginWith('local', { data: payload })
.then(response => {
if(response.data.status) {
this.$auth.setUser(response.data.data.userData)
this.$auth.$storage.setUniversal('user', response.data.data.userData)
this.$auth.$storage.setUniversal('loggedIn', true)
}else {
this.invalidCredential= response.data.message
}
}).catch(error => {
this.backendErrors = error.response.data.errors
})

How/Where does nuxtjs set the authorization header

I inherited a web project from another developer who's left the company. It is built with nuxtjs and laravel, neither of which I am strong with.
In the web project, after a user goes to a login screen, types in email and password, and presses save, I can see in my developer tools that the nuxtjs framework sends a {email: "user#email.com", password: "password"} to the laravel api at https://example.project.com/api/login. The laravel api then returns a 200 response with this payload { data: { message: "Login successful.", token: "50|Fs88RPU7HON1LnBskm35O9txG0OnXDiG3x4XWILJ" }}. Everything is great so far!
Immediately after the 200 response above, NuxtJS sends another request to https://example.project.com/api/auth/user in an attempt to get information about this user. Nginx gives a 401 response. My first suspicion for why this happens is because NuxtJS sent an Authorization: Bearer undefined as shown in this screenshot of my browser dev tools
I've seen other situations with Authorization: Bearer [object object].
I want to know how does NuxtJS decide what value to provide to the Authorization http header? This is my current nuxt.config.js
export default {
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
title: 'Blah',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: '' },
],
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.png' }],
},
// Auto import components: https://go.nuxtjs.dev/config-components
components: true,
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
// https://go.nuxtjs.dev/axios
'#nuxtjs/axios',
'#nuxtjs/auth'
],
auth: {
redirect: {
login: '/login',
logout: '/',
callback: '/api/login',
home: '/'
},
strategies: {
local: {
endpoints: {
login: { url: '/api/login'},
user: { url: '/api/auth/user'}
},
}
},
localStorage: true
},
proxy: {
'/api': {
target: 'https://example.project.com/',
pathRewrite: { '^/api': '' },
},
},
// Axios module configuration: https://go.nuxtjs.dev/config-axios
axios: {
baseURL: 'https://example.project.com/',
credentials: true,
headers : {
common: {
'Accept' : 'application/json'
}
}
},
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
}
}
And also, this is the line of code in pages/login.vue that starts the login process:
await this.$auth.loginWith('local', { data: {email:"user#email.com",password:"password"} });
Simply add Authorization header as default header right after authorization request. Assuming that server sends access token in response the code might look like this:
const response = await this.$auth.loginWith('local', {
data: {
email: "user#email.com",
password:"password"
}
})
const { token } = response;
axios.defaults.headers.common = { Authorization: `Bearer ${token}` };
change your strategy as below to set property name of the token being returned in response.
strategies: {
local: {
token: {
property: 'token'
},
endpoints: {
login: { url: '/api/login'},
user: { url: '/api/auth/user'}
},
}
},
It will include the authorization header in all your requests using $axios.
also you might need to set propery of the user which you are returning from backend also.
This is done by a library in the background. #nuxtjs/auth or #nuxtjs/auth-next will set the token depending on your config in nuxt.config.ts.
You can find the token in the local storage in auth._token.<strategy>. To use a Bearer token in the subsequent userinfo request you might need to set:
nuxt.config.ts
auth: {
strategies: {
local: {
token: {
type: 'Bearer',
}
}
}

Nuxt.js - No 'Access-Control-Allow-Origin' header is present on the requested resource

Errors
Access to XMLHttpRequest at 'https://api.domain.com/api/register' from origin 'https://nuxt-app.domain.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I am using PHP Laravel for backend API development and Nuxt.js for my frontend application.
Laravel Sanctum Installation
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
In App/Http/Kernel.php to api middleware group, Add Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class
In config/cors.php, set supports_credentials to true
In .env file, add SESSION_DOMAIN=.domain.com and SANCTUM_STATEFUL_DOMAINS=nuxt-app.domain.com
In routes/api.php, Modify Route::middleware('auth:sanctum')
nuxt.config.js
{
modules: [
'#nuxtjs/axios',
'#nuxtjs/auth-next'
],
axios: {
credentials:true,
proxy: true
},
proxy: {
'/api': {
target: 'https://api.domain.com',
pathRewrite: { '^/api': '/' }
}
},
auth: {
strategies: {
laravelSanctum: {
provider: "laravel/sanctum",
url: "https://api.domain.com",
endpoints: {
login: {
url: "/api/login",
method: "POST"
},
logout: {
url: "/api/logout",
method: "POST"
},
user: {
url: "/api/user"
}
},
user: {
property: false
}
}
},
redirect: {
login: "/login",
logout: "/login",
home: "/dashboard"
}
},
}
Register.vue
<script>
export default {
middleware: ["guest"],
head() {
return {
title: "Register",
};
},
data() {
return {
form: {
name: "",
email: "",
password: "",
password_confirmation: "",
},
errors: [],
};
},
methods: {
async register() {
await this.$axios.get("https://api.domain.com/sanctum/csrf-cookie");
await this.$axios
.$post("https://api.domain.com/api/register", this.form)
.then((response) => {
console.log(response);
this.$router.push("/login");
})
.catch((error) => {
this.errors = error.response.data.errors;
console.log(this.errors);
});
},
},
};
</script>
Is there anything else to do? If 'Yes' then, please guide me.
Otherwise, Why it's not working on the production server? Does anyone know how to fix this error?

Error 404 when login with nuxt auth and laravel passport

I'm authenticating with Laravel Passport and my front end has been implemented with nuxt.
I receive the following 404 error when sending a request with nuxt Auth to Backend:
{"message":"","exception":"Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException","file":"D:\\temopo\\api-test\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\AbstractRouteCollection.php","line":43,"trace":[{"file":"D:\\temopo\\api-test\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\RouteCollection.php","line":162,"function":"handleMatchedRoute","class":"Illuminate\\Routing\\AbstractRouteCollection","type":"->"},{"file":"D:\\temopo\\api-test\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php","line":647,"function":"match","class":"Illuminate\\Routing\\RouteCollection","type":"->"},{"file":"D:\\temopo\\api-test\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php","line":636,"function":"findRoute","class":"Illuminate\\Routing\\Router","type":"->"},{"file":"D:\\temopo\\api-test\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php","line":625,"function":"dispatchToRoute","class":"Illuminate\\Routing\\Router","type":"->"},{"file":"D:\\temopo\\api-test\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php","line":166,"function":"dispatch","class":"Illuminate\\Routing\\Router","type":"->"},{"file":"D:\\temopo\\api-test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php","line":128,"function":"Illuminate\\Foundation\\Http\\{closure}","class":"Illuminate\\Foundation\\Http\\Kernel","type":"->"},{"file":"D:\\temopo\\api-test\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest.php","line":21,"function":"Illuminate\\Pipeline\\{closure}","class":"Illuminate\\Pipeline\\Pipeline","type":"->"},{"file":"D:\\temopo\\api-test\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull.php","line":31,"function":"handle","class":"Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest","type":"->"},{"file":"D:\\temopo\\api-test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php","line":167,"function":"handle","class":"Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull","type":"->"},{"file":"D:\\temopo\\api-test\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest.php","line":21,"function":"Illuminate\\Pipeline\\{closure}","class":"Illuminate\\Pipeline\\Pipeline","type":"->"},{"file":"D:\\temopo\\api-test\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\TrimStrings.php","line":40,"function":"handle","class":"Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest","type":"->"},{"file":"D:\\temopo\\api-test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php","line":167,"function":"handle","class":"Illuminate\\Foundation\\Http\\Middleware\\TrimStrings","type":"->"},{"file":"D:\\temopo\\api-test\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize.php","line":27,"function":"Illuminate\\Pipeline\\{closure}","class":"Illuminate\\Pipeline\\Pipeline","type":"->"},{"file":"D:\\temopo\\api-test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php","line":167,"function":"handle","class":"Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize","type":"->"},{"file":"D:\\temopo\\api-test\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance.php","line":86,"function":"Illuminate\\Pipeline\\{closure}","class":"Illuminate\\Pipeline\\Pipeline","type":"->"},{"file":"D:\\temopo\\api-test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php","line":167,"function":"handle","class":"Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance","type":"->"},{"file":"D:\\temopo\\api-test\\vendor\\fruitcake\\laravel-cors\\src\\HandleCors.php","line":38,"function":"Illuminate\\Pipeline\\{closure}","class":"Illuminate\\Pipeline\\Pipeline","type":"->"},{"file":"D:\\temopo\\api-test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php","line":167,"function":"handle","class":"Fruitcake\\Cors\\HandleCors","type":"->"},{"file":"D:\\temopo\\api-test\\vendor\\fideloper\\proxy\\src\\TrustProxies.php","line":57,"function":"Illuminate\\Pipeline\\{closure}","class":"Illuminate\\Pipeline\\Pipeline","type":"->"},{"file":"D:\\temopo\\api-test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php","line":167,"function":"handle","class":"Fideloper\\Proxy\\TrustProxies","type":"->"},{"file":"D:\\temopo\\api-test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php","line":103,"function":"Illuminate\\Pipeline\\{closure}","class":"Illuminate\\Pipeline\\Pipeline","type":"->"},{"file":"D:\\temopo\\api-test\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php","line":141,"function":"then","class":"Illuminate\\Pipeline\\Pipeline","type":"->"},{"file":"D:\\temopo\\api-test\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php","line":110,"function":"sendRequestThroughRouter","class":"Illuminate\\Foundation\\Http\\Kernel","type":"->"},{"file":"D:\\temopo\\api-test\\public\\index.php","line":52,"function":"handle","class":"Illuminate\\Foundation\\Http\\Kernel","type":"->"},{"file":"D:\\temopo\\api-test\\server.php","line":21,"function":"require_once"}]}
my nuxt auth and axios config:
axios: {
baseURL: 'http://localhost:8000/',
header:{
'content-type':'application/json'
}
},
auth: {
strategies: {
laravelPassport: {
provider: 'laravel/passport', // Using nuxtAuth laravel passport provider
url: 'http://localhost:8000/',
clientId: '1',
client_secret: '****MPZAMzicKGjByb1hnTciqLScP7KUr7CyKgf', //Is the same as the value inside the database
grantType: 'password'
},
}
},
nuxt login mehtod and data
data() {
return {
login: {
username: '',
password: '',
},
}
},
methods: {
async loginMethod() {
await this.$auth.loginWith('laravelPassport',{ data: this.login })
},
},
Laravel API routes
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Auth\LoginControlle;
use \App\Http\Controllers\Auth\SignupControlle;
Route::post('/login',LoginControlle::class);
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
i had this problem and solved after one week.
in my opinion, use the proxy same below codes: let's coding ;-)
nuxt.config.js
axios: {
proxy: true,
baseURL: process.env.API_URL,
},
proxy: {
'/backend': {
target: process.env.API_URL,
pathRewrite: { '^/backend': '/' },
},
},
auth: {
redirect: {
home: '/profile',
login: '/profile',
logout: '/',
},
strategies: {
laravelPassportPasswordGrant: {
name: 'authMakeup',
provider: 'laravel/passport',
url: '/backend',
endpoints: {
token : '/api/v1/confirmCode',
user:{url:'/api/v1/user', method:'get'},
logout:{url: '/api/v1/logout', method: 'post'}
},
clientId: process.env.PASSPORT_CLIENT_ID,
clientSecret: process.env.PASSPORT_CLIENT_SECRET,
grantType: 'password',
},
},
},
in .env file:
API_URL="http://localhost:8000"
PASSPORT_CLIENT_ID=************
PASSPORT_CLIENT_SECRET=***********************
using:
this.$auth.loginWith("authMakeup", {
data: params
});
if you want to login by user & password not require override token in endpoint section.
but i had want to login by mobile, override it to custom route example:
token : '/api/v1/confirmCode',

Laravel sanctum & nuxt/auth-next request to auto fetch user is not sent anymore

I'm using nuxt auth with laravel sanctum, the login works but the request to get the authenticated user is not sent anymore !
successful login proof
And this is my nuxt.config.js
axios: {
baseUrl: process.env.API_URL,
credentials: true,
},
auth: {
strategies: {
'laravelSanctum': {
provider: 'laravel/sanctum',
url: process.env.API_URL,
endpoints: {
login: { url: '/api/login'},
user: { url: '/api/user', method: 'get', propertyName: false },
},
autoFetchUser:true,
tokenRequired: true,
tokenType: "Bearer"
},
},
redirect: {
login: '/auth/login',
logout: '/auth/login',
callback: '/auth/login',
home: '/'
},
localStorage: false
},
I was using 127.0.0.1 instead of localhost
in all my urls, that's why somehow it was not sendind the /api/user request !
Client .env
PORT=3000
HOST=localhost
BASE_URL=http://localhost:3000
API_URL=http://localhost:8000
Server .env
APP_URL=https://localhost:8000
SESSION_DOMAIN=localhost
SANCTUM_STATEFUL_DOMAINS=localhost:3000

Resources