Nuxt Auth login - working on localhost, 301 and 405 on server - vue.js

My problem is, that login/logout works perfectly on my localhost, but as soon as I deploy it on a server I got 301 and 405 errors, with the "The GET method is not supported for this route. Supported methods: POST" message and I cant figure it out why is that.
My nuxt.config.js:
},
auth: {
strategies: {
local: {
user: {
property: 'data'
},
token: {
maxAge: 86400,
global: true
},
endpoints: {
login: { url: '/api/auth/login/', method: 'post' },
logout: { url: '/api/auth/logout/', method: 'post' },
user: { url: '/api/auth/user/', method: 'get' }
}
},
}
},
build: {
My login method:
async login() {
this.errors = {};
try {
await this.$auth.loginWith('local', { data: this.loginForm });
...
} catch (error) {
if (error.response.status === 401) {
this.inactive = error.response.data.message;
}
this.errors = error?.response?.data?.errors;
}
},
My Laravel api.php:
Route::group(['prefix' => 'auth'], function () {
Route::post('login/', [AuthController::class, 'login']);
Route::post('register', [AuthController::class, 'register']);
Route::post('set-password', [AuthController::class, 'setPassword']);
Route::group(['middleware' => ['auth:sanctum']], function () {
Route::get('user/', [AuthController::class, 'user']);
Route::post('logout/', [AuthController::class, 'logout']);
Route::post('password-reset', [AuthController::class, 'passwordReset']);
});
});
And i will attach my network tab from my browser (first is on localhost/working, second one is on a server/not working):
I don't know what I'm messing up but after several days of debugging I'm hopeless. I've emptied every possible caches on the backend side so I'm thinking thats not the problem. But hopefully somebody else will be much more clever than me and can tell me what's going on.

Related

How can I set Next-Auth callback url? and next-auth session return null

I want to set login, logout callback url.
So, I set the callback url like this.
//signIn
const signInResult = await signIn("credentials", {
message,
signature,
redirect: false,
callbackUrl: `${env.nextauth_url}`,
});
//signOut
signOut({ callbackUrl: `${env.nextauth_url}`, redirect: false });
But, When I log in, I look at the network tab.
api/auth/providers, api/auth/callback/credentials? reply with
callbackUrl(url) localhost:3000
It's api/auth/callback/credentials? reply.
It's api/auth/providers reply
and api/auth/session reply empty object.
When I run on http://localhost:3000, everything was perfect.
But, After deploy, the login is not working properly.
How can I fix the error?
I added [...next-auth] code.
import CredentialsProvider from "next-auth/providers/credentials";
import NextAuth from "next-auth";
import Moralis from "moralis";
import env from "env.json";
export default NextAuth({
providers: [
CredentialsProvider({
name: "MoralisAuth",
credentials: {
message: {
label: "Message",
type: "text",
placeholder: "0x0",
},
signature: {
label: "Signature",
type: "text",
placeholder: "0x0",
},
},
async authorize(credentials: any): Promise<any> {
try {
const { message, signature } = credentials;
await Moralis.start({
apiKey: env.moralis_api_key,
});
const { address, profileId } = (
await Moralis.Auth.verify({ message, signature, network: "evm" })
).raw;
if (address && profileId) {
const user = { address, profileId, signature };
if (user) {
return user;
}
}
} catch (error) {
console.error(error);
return null;
}
},
}),
],
pages: {
signIn: "/",
signOut: "/",
},
session: {
maxAge: 3 * 24 * 60 * 60,
},
callbacks: {
async jwt({ token, user }) {
user && (token.user = user);
return token;
},
async session({ session, token }: any) {
session.user = token.user;
return session;
},
async redirect({ url, baseUrl }) {
// Allows relative callback URLs
if (url.startsWith("/")) return `${baseUrl}${url}`;
// Allows callback URLs on the same origin
else if (new URL(url).origin === baseUrl) return url;
return baseUrl;
},
},
secret: env.nextauth_secret,
});

Nuxt auth module axios not setting CSRF token on request

I'm using the Nuxt auth module v5 and the Laravel sanctum provider. My csrf-cookie route works fine, and my login route works fine, but when trying to call this.$axios from a function, such as when creating a user's account (since auth module doesn't offer this) I'm getting a CSRF token mismatch.
It would appear that using axios directly like this doesn't have access to setting the cookie since no user logged in, how can I get the cookie to be set?
Method for account creation
/*
** Create accounr
*/
createAccount () {
this.feedback.isShown = false
this.isCreatingAccount = true
if (this.apiAccountCreationSource) this.apiAccountCreationSource.cancel('aborted')
const CancelToken = this.$axios.CancelToken
this.apiAccountCreationSource = CancelToken.source()
this.$axios.post(`${this.$config.apiUrl}/api/account`, this.account, {
cancelToken: this.apiAccountCreationSource.token,
timeout: 30 * 1000
}).then(res => {
this.apiAccountCreationSource = null
this.setContextualResponse(res)
setTimeout(() => {
this.login()
}, 250)
}).catch(err => {
this.setContextualResponse(err.response ? err.response.data : null)
}).finally(() => {
this.isCreatingAccount = false
})
},
Nuxt config
// Axios module configuration: https://go.nuxtjs.dev/config-axios
axios: {
credentials: true,
baseURL: process.env.API_DOMAIN
},
// Auth module configuration: https://auth.nuxtjs.org/
auth: {
redirect: {
login: '/account/login/',
logout: '/account/login/',
callback: '/account/login/',
home: '/account/dashboard/'
},
strategies: {
'laravelSanctum': {
provider: 'laravel/sanctum',
url: process.env.API_DOMAIN,
endpoints: {
login: { url: '/api/login', method: 'post' },
logout: { url: '/api/account/logout', method: 'post' },
user: { url: '/api/account', method: 'get', propertyName: 'user' }
}
}
}
},
If you need to get the CSRF token all you need to do is make a request to your token endpoint and your browser should save the XSRF token. Then axios will automatically send this token in every subsequent request.
So all that you need to do is make a axios GET request to your csrf-cookie route before you send your POST request.
this.$axios.get(`${this.$config.apiUrl}/sanctum/csrf-cookie`)
Or you can chain both requests doing something like this:
this.$axios.get(`${this.$config.apiUrl}/sanctum/csrf-cookie`).then(() => {
return this.$axios.post(`${this.$config.apiUrl}/api/account`, this.account, {
cancelToken: this.apiAccountCreationSource.token,
timeout: 30 * 1000
}).then((res) => {
this.apiAccountCreationSource = null
this.setContextualResponse(res)
setTimeout(() => {
this.login()
}, 250)
}).catch((err) => {
this.setContextualResponse(err.response ? err.response.data : null)
}).finally(() => {
this.isCreatingAccount = false
})
})
Your authentication strategy works without this hassle because it handles this csrf request internally (https://github.com/nuxt-community/auth-module/blob/dev/src/providers/laravel-sanctum.ts)
References:
https://laravel.com/docs/8.x/sanctum#csrf-protection
https://github.com/axios/axios/issues/708#issuecomment-280920224

How to set session using Nuxt-Auth?

I am trying to use Nuxt/auth, but run into problem with session saving in localStorage.
Login.vue
methods: {
sendLoginLink() {
this.$auth.loginWith('local', {
data: {
username: "test#gmail.com",
password: "testpassword"
}
}).then((date) => {
console.log("data", date)
}).catch((err) => {
console.error("err", err)
})
}
Nuxt.config.js
auth: {
strategies: {
local: {
endpoints: {
login: { url: '/dashboard', method: 'post', propertyName: 'token' }
},
tokenType: ''
}
}
axios: {
baseURL: 'http://localhost:1234'
},
modules: [
'#nuxtjs/axios',
'#nuxtjs/auth-next',
]
When the user logs in, the function sendLoginLink is called and throw error in console:
Which means that the auth-token is so large that it cannot be stored in localStorage, but all other things related to this function are saved in localStorage. For example:
I googled a lot but didn't find a good solution to the problem. For example, I tried to clear all localStorage memory before running sendLoginLink() function but the result is the same. Different browsers have the same problem

Catch error server response with #nuxtjs/auth

I'm trying to catch the error response for #nuxtjs/auth but it doesn't seem to return anything but undefined.
It refuses to login if I include the user so I want to know why it's returning undefined.
CONFIG:
auth: {
strategies: {
local: {
endpoints: {
login: {
url: 'http://127.0.0.1:80/api/login',
method: 'post',
propertyName: 'token'
},
logout: false,
user: {
url: 'http://127.0.0.1:80/api/me',
method: 'get',
propertyName: undefined
}
},
tokenRequired: true,
tokenType: 'bearer',
}
},
plugins: [
'#/plugins/auth.js'
]
},
PLUGIN:
export default function ({ app }) {
app.$auth.onError((error, name, endpoint) => {
console.error(name, error)
});
}
VIEW FUNCTION:
- both handleSuccess and handleFailure returns undefined.
login() {
this.toggleProcessing(0);
let payload = {
username: 'admin',
password: 'admin123'
}
let handleSuccess = response => {
console.log(response);
this.toggleProcessing(0);
}
let handleFailure = error => {
console.log(error);
this.toggleProcessing(0);
}
this.$auth.loginWith('local', { data: payload }).then(handleSuccess).catch(handleFailure);
},
You can use e.response
async login() {
try {
const login = {
username: this.username,
password: this.password
}
let response = await this.$auth.loginWith('local', { data: login })
console.log('response', response)
} catch (e) {
console.log('Error Response', e.response)
}
}
I fell into the same problem and after spending some time i found out a very good way to catch the response. The solution is to use the axios interceptor. Just replace your plugin file code with the following
export default function ({$axios, $auth}){
$axios.interceptors.response.use(function (response) {
// Do something with response data
return response;
}, function (error) {
// Do something with response error
return Promise.reject(error);
});
}
I'm not sure initially what might be wrong here because I can't see the complete nuxt.config.js and your full component but here are a few things to check:
#nuxtjs/axios is installed
Both axios and auth modules are registered in the modules section of nuxt.config.js:
modules: [
'#nuxtjs/axios',
'#nuxtjs/auth'
]
Also, ensure the middleware property for auth is set in the component/page component.
Ensure you're following the documentation on this page: https://auth.nuxtjs.org/getting-starterd/setup
Ive been using try -> this.$auth.loginWith to catch error server response with #nuxtjs/auth.
login() {
const data = { form };
try {
this.$auth
.loginWith("local", { data: data })
.then(api => {
// response
this.response.success = "Succes";
})
.catch(errors => {
this.response.error = "Wrong username/password";
});
} catch (e) {
this.response.error = e.message;
}
},
Specify the token field in the nuxt.config
strategies: {
local: {
endpoints: {
login: { // loginWith
url: "auth/login",
method: "post",
propertyName: "data.token" // token field
},
user: { // get user data
url: "auth/user",
method: "get",
propertyName: "data.user"
},
}
}
},
modules: ["#nuxtjs/axios", "#nuxtjs/auth"],

Testing angular services in rails

I'm trying to test my services with jasmine and I keep gettin and "Unknown provider: AuthServiceProvider <- AuthService in angular/angular.js on line 2683"
my service is defined:
app.factory( 'AuthService', ["$resource", "$rootScope", "apiPrefix", function($resource, $rootScope, apiPrefix) {
auth_resource = $resource(apiPrefix + "/session", {}, {
logout: {method:'GET'}
});
var currentUser;
return {
login: function(email, password, success, failure) {
auth_resource.save({}, {
email: email,
password: password
}, function(response){
currentUser = response
success()
}, function(response){
failure()
});
},
logout: function(success, failure) {
auth_resource.logout(
function(response){
currentUser = undefined
}, function(){
$scope.alerts.push({type: "success", msg: "Logged out" })
}, function(){
$scope.alerts.push({type: "error", msg: "Sorry, something went wrong" })
}
)
},
isLoggedIn: function(){ return currentUser !== undefined},
currentUser: function() { return currentUser; }
};
}]);
and my test:
describe("AuthService", function(){
var httpBackend;
beforeEach(inject(function($httpBackend, AuthService){
module('app');
httpBackend = $httpBackend;
AService = AuthService;
}));
it("should login the user", function(){
// test here
});
});
my jasmine config file is:
// This pulls in all your specs from the javascripts directory into Jasmine:
// spec/javascripts/*_spec.js.coffee
// spec/javascripts/*_spec.js
// spec/javascripts/*_spec.js.erb
//= require application
//= require_tree ./
This seems to be configured properly because I can test my controllers fine so I'm not sure why it doesn't recognize my services.
You can use $injector to get the service and then inject it to the actual test like this
describe("AuthService", function () {
var httpBackend, AService, apiPrefix;
beforeEach(module('app'));
beforeEach(function () {
angular.mock.inject(function ($injector) {
httpBackend = $injector.get('$httpBackend');
apiPrefix = angular.mock.module('apiPrefix'); // I assume you have apiPrefix module defined somewhere in your code.
AService = $injector.get('AuthService', {apiPrefix: apiPrefix});
})
});
it("should login the user", inject(function (AService) {
// test here
}));
});
I assume you have apiPrefix module defined somewhere in your code.