#nuxtjs/auth login method calls a user method upon completion - asp.net-core

I'm using the nuxtjs/auth module to authenticate a user, with the backend written in .NET Core
When configuring the nuxtjs/auth package, I add the following to nuxt.config.js
//nuxt.config.js
.
.
auth: {
strategies: {
local: {
endpoints: {
login: { url: 'users/authenticate', method: 'post', propertyName: 'data.token' },
}
}
}
},
.
.
the login function called when clicking 'login' looks like this
async login () {
try {
await this.$auth.loginWith('local', {
data: {
Username: this.username,
Password: this.password
}
})
this.$router.push('/')
} catch (e) {
console.log(e) <-------------------
this.error = e.response.data.message
}
}
The console.log(e) returns the following message:
Error: Request failed with status code 404
at createError (commons.app.js:565)
at settle (commons.app.js:728)
at XMLHttpRequest.handleLoad (commons.app.js:98)
And in the console I also get
GET https://example.com/api/api/auth/user 404 (Not Found)
So it would seem that upon completing the initial authentication request, the nuxtjs/auth module calls 'user' in the API.
My backend is written in NET Core
So my question is, am I supposed to write in the NET Core backend, because the documentation for the nuxtjs/api package does not seem to explain how the basic usage of the module works

Related

How to prevent nuxt auth to go to error page if the pass or email is wrong

I'm using NuxtJs v2.13 with its auth module and Laravel with passport for my backend. for login i use the documented method:
async signIn(formData){
await this.$auth.loginWith('local',{
data: formData
})
if(this.$auth.user.depth > 1){
this.goTo('/cms/product')
}else{
this.goTo('/')
}
}
when the email or password is wrong it send me too nuxt error page! i should remain on login page.
what should i do!!?
BTW, i gonna use vee-validate on my form too. and this is my auth config on nuxt.config.js:
auth: {
strategies: {
local: {
endpoints: {
login: { url: 'auth/login', method: 'post', propertyName: '' },
logout: { url: 'auth/logout', method: 'post' },
user: { url: 'auth/info', method: 'get', propertyName: 'data' }
}
}
},
redirect: {
login: '/login',
logout: '/',
callback: '/login',
home: '/'
},
cookie: {
prefix: 'auth.',
options: {
path: '/',
maxAge: process.env.AUTH_COOKIE_MAX_AGE
}
}
},
Nuxt is redirecting because the error isn't being handled. You can simply wrap this code in an error handler. It's also good to put this code near the login component or page so you can use the status code of the error to display some meaningful response to the user, e.g. that the credentials were invalid.
try {
await this.$auth.loginWith('local', {
data: formData,
})
if (this.$auth.user.depth > 1) {
this.goTo('/cms/product')
} else {
this.goTo('/')
}
} catch (error) {
if (error.response) {
// Get the error status, inform the user of the error.
}
// Unexpected error, tell the user to try again later.
}
Since the #nuxtjs/auth package requires the #nuxtjs/axios package you can also read about intercepting errors on a global level with Axios Interceptors. I personally use try/catch blocks at the method level and use interceptors for catching 401 Unauthenticated errors and deleting the user information from Vuex.

Google OAuth2 redirect_uri_mismatch still occurring despite trying several solutions

I am currently trying to connect to Google OAuth with JS on server-side and am getting this error despite trying everything I could find on the web.
$('#sign-in-button').click(function () {
auth2.grantOfflineAccess().then(signInCallback);
});
function signInCallback(result) {
console.log(result)
console.log(typeof result)
if (result['code']) {
$('#sign-in-button').prop('disabled', true);
$.ajax({
type: 'POST',
url: 'http://localhost:8080/auth',
headers: {
'X-Requested-With': 'XMLHttpRequest'
},
contentType: 'application/json; charset=utf-8',
success: function (successResult) {
//todo next flow stage
console.log('Ready to proceed to next stage!')
},
processData: false,
data: JSON.stringify(result)
})
} else {
// todo handle error
console.log('An error occurred within the OAuth stage.')
}
}
The code above is what I am using on the client. The below code is the Express route for /auth.
app.post('/auth', function (req, res) {
if (req.header('X-Requested-With')) {
let oAuth2Client = getOAuthClient(); // this method uses return new OAuth2(clientId, clientSecret, redirectUrl) where redirect url = 'http://localhost:8080/link'.
let code = req.body['code'];
if (code) {
oAuth2Client.getToken(code, function (error, tokens) {
if (error) {
console.log(error.stack);
console.log('Whoops, an error occurred!')
res.send('An error occurred during the OAuth backend stage.')
} else {
console.log('No error.')
console.log(tokens)
google.options({auth: oAuth2Client})
}
})
} else {
//todo fail no code
console.log('Code failure.')
}
} else {
//todo return fail CSRF
console.log('CSRF failure.')
}
})
On cloud console, you can see my efforts of trying every possible URI under the sun!
Most strangely, in the Gaxios error, the URI is correct in the request body!
But I still get redirect_uri_mismatch
What can I try to fix this other than what I have listed below?
Add all the extra URI variants to cloud console
Use oAuth2Client.getAuthUrl() instead of my client side code
Different redirect URI (with & without slash etc.)

How to properly use passport-github for REST API authentication?

I am building a vue.js client which needs to be authenticated through github oauth using an express server. It's easy to do this using server side rendering but REST API has been troublesome for me.
I have set the homepage url as "http://localhost:3000" where the server runs and I want the authorization callback url to be "http://localhost:8080" (which hosts the client). I am redirecting to "http://localhost:3000/auth/github/redirect" instead, and in its callback redirecting to "http://localhost:8080". The problem I am facing is that I am unable to send user data to the vuejs client through res.redirect. I am not sure if I am doing it the right way.
router.get("/github", passport.authenticate("github"));
router.get(
"/github/redirect",
passport.authenticate("github", { failureRedirect: "/login" }),
(req, res) => {
// res.send(req.user);
res.redirect("http://localhost:8080/"); // req.user should be sent with this
}
);
I have implemented the following approach as a work around :-
A route that returns the user details in a get request :
router.get("/check", (req, res) => {
if (req.user === undefined) {
res.json({});
} else {
res.json({
user: req.user
});
}
});
The client app hits this api right after redirection along with some necessary headers :
checkIfLoggedIn() {
const url = `${API_ROOT}auth/check/`;
return axios(url, {
headers: { "Content-Type": "application/json" },
withCredentials: true
});
}
To enable credentials, we have to pass the following options while configuring cors :
var corsOption = {
origin: true,
credentials: true
};
app.use(cors(corsOption));

How to save JWT Token in Vuex with Nuxt Auth Module?

I am currently trying to convert a VueJS page to NuxtJS with VueJS. Unfortunately I have some problems with authenticating the user and I can't find a solution in Google. I only use Nuxt for the client. The API is completely separate in express and works with the existing VueJS site.
In Nuxt I send now with the Auth module a request with username and password to my express Server/Api. The Api receives the data, checks it, and finds the account in MongoDB. This works exactly as it should. Or as I think it should. Now I take the user object and generate the jwt from it. I can debug everything up to here and it works.
Now I probably just don't know how to keep debugging it. I send an answer with res.json(user, token) back to the Nuxt client (code follows below). As I said, in my current VueJS page I can handle this as well. Also in the Nuxt page I see the answer in the dev console and to my knowledge the answer fits.
Now some code.
The login part on the express Api:
const User = require('../models/User')
const jwt = require('jsonwebtoken')
const config = require('../config/config')
function jwtSignUser(user){
const ONE_YEAR = 60 * 60 * 24 * 365
return jwt.sign(user,config.authentication.jwtSecret, {
expiresIn: ONE_YEAR
})
}
module.exports = {
async login (req, res){
console.log(req.body)
try{
const {username, password} = req.body
const user = await User.findOne({
username: username
})
if(!user){
return res.status(403).send({
error: `The login information was incorrect.`
})
}
const isPasswordValid = await user.comparePassword(password)
if(!isPasswordValid) {
return res.status(403).send({
error: `The login information was incorrect.`
})
}
const userJson = user.toJSON()
res.json({
user: userJson,
token: jwtSignUser(userJson)
})
} catch (err) {
console.log(err)
res.status(500).send({
error: `An error has occured trying to log in.`
})
}
}
}
nuxt.config.js:
auth: {
strategies: {
local: {
endpoints: {
login: {url: '/login', method: 'post' },
user: {url: '/user', method: 'get' },
logout: false,
}
}
},
redirect: {
login: '/profile',
logout: '/',
user: '/profile',
callback:'/'
}
}
even tried it with nearly any possible "propertyName".
and, last but not least, the method on my login.vue:
async login() {
try {
console.log('Logging in...')
await this.$auth.loginWith('local', {
data: {
"username": this.username,
"password": this.password
}
}).catch(e => {
console.log('Failed Logging In');
})
if (this.$auth.loggedIn) {
console.log('Successfully Logged In');
}
}catch (e) {
console.log('Username or Password wrong');
console.log('Error: ', e);
}
}
What I really don't understand here... I always get "Loggin in..." displayed in the console. None of the error messages.
I get 4 new entries in the "Network" Tag in Chrome Dev Tools every time I make a request (press the Login Button). Two times "login" and directly afterwards two times "user".
The first "login" entry is as follow (in the General Headers):
Request URL: http://localhost:3001/login
Request Method: OPTIONS
Status Code: 204 No Content
Remote Address: [::1]:3001
Referrer Policy: no-referrer-when-downgrade
The first "user" entry:
Request URL: http://localhost:3001/user
Request Method: OPTIONS
Status Code: 204 No Content
Remote Address: [::1]:3001
Referrer Policy: no-referrer-when-downgrade
Both without any Response.
The second login entry:
Request URL: http://localhost:3001/login
Request Method: POST
Status Code: 200 OK
Remote Address: [::1]:3001
Referrer Policy: no-referrer-when-downgrade
and the Response is the object with the token and the user object.
The second user entry:
Request URL: http://localhost:3001/user
Request Method: GET
Status Code: 200 OK
Remote Address: [::1]:3001
Referrer Policy: no-referrer-when-downgrade
and the Response is the user object.
I think for the login should only the login request be relevant, or I'm wrong? And the user request works because the client has asked for the user route and the user route, always send the answer with the actual user object in my Express API.
Because I think, the problem is in the login response? Here some screenshots from the Network Tab in Chrome Dev Tools with the Request/Response for login.
First login request without response
Second login request
Response to second login request
Do I have to do something with my Vuex Store? I never found any configured Vuex Stores in examples for using the Auth Module while using google so I thougt I do not have to change here anything.
Thats my Vuex Store (Vue Dev Tools in Chrome) after trying to login without success:
{"navbar":false,"token":null,"user":null,"isUserLoggedIn":false,"access":false,"auth":{"user":"__vue_devtool_undefined__","loggedIn":false,"strategy":"local","busy":false},"feedType":"popular"}
There is also some logic I use for my actual VueJS site. I will remove that when the Auth Module is working.
Asked by #imreBoersma :
My /user endpoint on Express looks like:
app.get('/user',
isAuthenticated,
UsersController.getUser)
I first check if the User is authenticated:
const passport = require('passport')
module.exports = function (req, res, next) {
passport.authenticate('jwt', function (err, user) {
if(err || !user) {
res.status(403).send({
error: 'You are not authorized to do this.'
})
} else {
req.user = user
next()
}
})(req, res, next)
}
After that I search the User document in MongoDB and send the document to the client:
const User = require('../models/User')
module.exports = {
[...]
getUser (req, res) {
User.findById(req.user._id, function (error, user){
if (error) { console.error(error); }
res.send(user)
})
}
[...]
}
Feel free to ask for more information.
I think I can answer my own question.
I searched the whole time for an error regarding to my api response.
The problem was the "propertyName" on user endpoint in the nuxt.config.js.
It is set to "user" as default. When I set it to "propertyName: false", than everything works as it should.
auth: {
strategies: {
local: {
endpoints: {
login: {url: '/login', method: 'post', propertyName: 'token' },
user: {url: '/user', method: 'get', propertyName: false },
logout: false,
}
}
}
},

axios.post is returning error when used with redux-saga

I recently converted my redux-thunk middleware code to use redux-saga and it was working all these days fine and all of a sudden it is throwing an error. Not sure why!!
My Spring Boot REST Client is returning the proper response and no errors in the log. And if i make the same request using swagger i am getting the response back as expected so there is nothing wrong on the server side.
I have the following code
const LOGIN_URL = 'http://localhost:8888/api/a/login';
export function* loginUserAsync(action) {
console.log('.loginUserAsync() : action:', action);
yield put({ type: LoginConstants.LOGIN_USER_IN_PROGRESS });
const postParams = {
username: action.props.username,
password: action.props.password
};
const headerParams = {
headers: {
'Content-Type': 'application/json',
//'Content-Type': 'x-www-form-urlencoded'
}
};
console.log('headerParams', headerParams);
console.log('postParams', postParams);
try {
console.log('Before making async post call using axios');
const response = yield call(axios.post, LOGIN_URL, postParams, headerParams);
let token;
console.log('response', response);
if (response.headers) {
token = response.headers['x-auth-token'];
AsyncStorage.setItem('jwt', token);
}
// Login Succeeded fire Login Success Action
yield put({
type: LoginConstants.LOGIN_USER_SUCCESS,
token,
account: response.data
});
const navigatorUID = Store.getState().navigation.currentNavigatorUID;
Store.dispatch(NavigationActions.push(navigatorUID, Router.getRoute('home')));
} catch (error) {
// Login Failed fire Login Failure Action
console.log('loginUserAync() : error:[' + JSON.stringify(error) + ']');
yield put({
type: LoginConstants.LOGIN_USER_FAILURE,
error: error.data
});
}
}
export function* loginUser() {
console.log('.loginUser() :');
yield takeEvery(LoginConstants.LOGIN_USER, loginUserAsync);
}
In the console i am seeing the following:
I have no idea why it stopped working all of a sudden.
Thanks
Sateesh
For some reason localhost and 127.0.0.1 are not being recognized and i have to use the actual IP Address.
I had that Issue when i tried to run it in my mac book. It always worked with localhost in Ubuntu.