URIError in NuxtJS production when hosting on vercel - javascript

I am developing an application with ssr in nuxt. The problem I have is when I run "npm start" after doing the build and generate. The application starts working normally but when I try to log in it doesn't work although in development mode it works perfectly. The api is built with express and I am using tokens and nuxt auth as authentication method. The server endpoints declared in the auth strategy never get executed, use console.log () on the login endpoint handler to check. Anyone have any idea how I can solve this problem? Thanks for your time!
Login component script:
<script>
import { mapGetters } from 'vuex'
import index from './index.vue'
export default {
components: {
index,
},
data() {
return {
email: '',
password: '',
}
},
computed: {
...mapGetters(['isAuthenticated']),
},
methods: {
close() {
this.$router.push('/')
},
login() {
const button = document.querySelector('.center-form button')
button.disabled = true
button.innerHTML = '...'
const data = { password: this.password, email: this.email }
this.$auth
.loginWith('local', { data })
.then((x) => {
this.$auth.strategy.token.set(x.data.token)
this.$router.push('publicar-inmueble')
})
.catch((err) => {
console.log(err)
})
},
},
}
</script>
Nuxt auth strategy:
auth: {
strategies: {
local: {
token: {
property: 'token'
},
user: {
property: 'user'
},
endpoints: {
login: { url: '/server/api/usuarios/login', method: 'post', propertyName: 'data' },
user: { url: '/server/api/usuarios/mi-perfil', method: 'get', propertyName: 'data' },
logout: { url: '/server/api/usuarios/logout', method: 'delete' }
}
}
}
},
Store:
export const getters = {
isAuthenticated(state) {
return state.auth.loggedIn
},
loggedInUser(state) {
return state.auth.user
}
}

Go to your app's settings on vercel, the URL should look like this:
https://vercel.com/<your-username>/<your-project>/settings/environment-variables
There, drop in your env variable (my screenshot is a value example!) and trigger a build of your app. Should work fine then.

Related

Problem using Next-Auth with Credentials Provider for authenticating on existing system

I am using Next-Auth Credentials provider to authenticate using our existing API.
When I follow the directions on https://next-auth.js.org/configuration/callbacks
like this:
callbacks: {
async jwt({ token, user }) {
if (user) {
token.accessToken = user.jwt
}
return token
},
async session({ session, token, user }) {
session.accessToken = token.accessToken
return session
}
}
the resulting session object from useSession() looks like this:
{
expires: "2022-03-22T18:29:02.799Z",
user: {email: 'john#nextIsGreat.com'}
}
I can't use that as it does not have the token available.
So I was able to make up my own working solution, but it is kind of strange because of the way things are grouped together. Here is what I am doing now, that I am trying to figure out how to do better. I use comments to point out the problem areas:
[...nextauth].js:
import NextAuth from 'next-auth'
import Credentials from 'next-auth/providers/credentials'
import axios from 'axios'
export default NextAuth({
providers: [
Credentials({
name: 'Email and Password',
credentials: {
username: { label: 'Username', type: 'text', placeholder: 'jsmith' },
password: { label: 'Password', type: 'password' }
},
authorize: async (credentials) => {
const url = process.env.API_URL + '/authenticate'
const result = await axios.post(url, {
username: credentials.username,
password: credentials.password
})
const user = result.data
console.log(user)
//It logs this:
/*
{
jwt: 'eyJhbasU1OTJ9.NQ356H4Odya62KmN...', //<---***This is the token i pass in to all of my API calls****
user: {
userId: 207,
email: 'john#nextIsGreat.com',
firstName: 'John',
lastName: 'Doe',
roleId: 1,
}
}
*/
if (user) {
return Promise.resolve(user)
} else {
return Promise.resolve(null)
}
}
})
],
callbacks: {
async jwt({ token, user }) {
if (user) {
if (user.jwt) {
token = { accessToken: user.jwt, restOfUser: user.user }
}
}
return token
},
async session(seshProps) {
return seshProps
}
}
})
Home.js:
export const Home = () => {
const { data: session } = useSession()
console.log(session)
//LOGS THIS --->
/*
{
"session": { "user":{}, "expires":"2022-03-22T17:06:26.937Z"},
"token":{
"accessToken":"eyJ...",
"iat":1645376785,
"exp":1647968785,
"jti":"41636a35-7b9a-42fd-8ded-d3dfgh123455a"
"restOfUser": {
"userId":207,
"email":"john#nextIsGreat.com",
"firstName":"John",
"lastName":"Doe",
"roleId":1
}
}
{
*/
const getPosts=()=> {
const url = 'localhost:4000/posts'
const {data} = axios.get(url, {
Authorization: session.token.accessToken <--**This is the way I am calling my API
})
console.log(data)
}
return (
<div onClick={getPosts}>
Hello, {session.token.restOfUser.firstName}
/* I have to access it like this now, which seems wrong ***** */
</div>
)
}
Cheers for creating your own solution but you do not need it. NextAuth CredentialsProvider handles it already by setting your NextAuth session configuration to session: {strategy: "jwt", ... }.
You can also remove your callbacks for jwt() and session() and remove your owned generated JWT access token. As you do not need it, this way you can authenticate your existing system.
And at your CredentialsProvider({authorize(){}} authorize method. If you had directly connected to the user database, you can directly look up the user credential without doing a post request since it is already considered a server-side function.

Nuxt auth user reset after browser refresh

i'm building an app with user login and register info. I use nuxt/auth module for handling the authentification. Whenever the user get logs in the state changes to true without a problem. The only issue i'm having is when i call set user method , the user info get registered successfully, but whenever i refresh the browser i lose the user data even though in the first place it was set successfully.
my nuxt.js config for nuxt auth module
auth: {
strategies: {
local: {
token: {
property: "token",
global: true,
},
redirect: {
"login": "/account/login",
"logout": "/",
"home": "/page/ajouter-produit",
"callback": false
},
endpoints: {
login: { url: "http://localhost:5000/login", method: "post" },
logout: false, // we don't have an endpoint for our logout in our API and we just remove the token from localstorage
user:false
}
}
}
},
My register/login component
async typeForm(e) {
this.typesubmit = true;
// stop here if form is invalid
this.$v.$touch();
if (this.$v.typeform.$anyError) {
return;
}
const user = await axios.post(`${baseUrl}register`,{
username:this.typeform.username,
password:this.typeform.password,
email:this.typeform.email,
tel:this.typeform.tel,
adresse:this.typeform.adresse,
store:this.typeform.store,
})
.then(response => {
console.log(response.data)
return response.data.user;
}).catch( (error) => {
this.error = ''
this.error = error.response.data
})
if(user){
let loginData = {email:this.typeform.email, password:this.typeform.password}
const response = await this.$auth.loginWith('local', { data: loginData})
.then(response => {
this.$auth.setUser(response.data.user) // the user is set without a problem, everything works fine.
return response.data;
}).catch( (error) => {
this.errors = error.response.data
console.log(error.response)
})
}
}
When i console log the state and the user in the first place everything works fine
console.log(this.$store.state.auth.user) // logs all user data i get from the api call. but when i refresh i get an empty object
console.log(this.$store.state.auth.loggedIn) // logs true , and even after i refresh it's still true
please help
Problem solved. what i did is to add to my login function
this.$auth.$storage.setUniversal('user', response.data.user, true)
works like a charm.
I have the samie issue.
After added this.$auth.$storage.setUniversal('user', response.data.user, true), the user is logged out after refreshing the page.
Here is my code :
this.$auth
.loginWith("local", {
data: {
email: this.connexionLogin,
password: this.connexionPassword
}
})
.then( (response) => {
this.$auth.setUser(response.data.user);
this.$auth.$storage.setUniversal('user', response.data.user, true)
this.$emit("connexionOk");
and my nuxt.config :
auth: {
watchLoggedIn: true,
resetOnError: true,
redirect: {
login: "/admin/login",
logout: "/admin/login",
callback: "/callback",
home: '/admin/', // Pour ne pas ĂȘtre redirigĂ© vers la home suite authentification
},
strategies: {
local: {
token: {
property: "tokens.access.token",
},
user: {
property: 'user',
autoFetch: false
},
endpoints: {
login: {
url: "v1/auth/login",
method: "post",
},
logout: false,
},
},
},
},

Getting user email from firebase using Vue.js

I'm building a chat app with Vue.js and Firebase.
I'm new to both vue and firebase and struggeling to get the users email so i can send it to firebase to show along with the chat.
I've tried this solution:
How can i get the user in firebase database, to write from a component with vuejs?
But can't get it to work. I guess I dont really get where, how or when I can access root. Cause when i tried this.$root.something I get an error message.
This code is in my main.js file:
firebase.auth().onAuthStateChanged(function(user) {
if (!app) {
/* eslint-disable no-new */
app = new Vue({
el: '#app',
data: {email: user.email}, //here i want to store the email, which works but I cant access it from other components
template: '<App/>',
components: { App },
router
})
}
});
And this is the script in my main component. It's here I want to accses the root.
<script>
import * as firebase from 'firebase'
export default {
name: 'chat',
data: function(){
return {
room: null,
db: null, // assign Firebase SDK later
messageInput:'', // this is for v-model
messages: [],
}
},
mounted() {
this.db = firebase
// access the location and initilize a Firebase reference
this.init()
},
methods: {
init(){
this.room = this.db.database().ref().child('chatroom/1')
this.messageListener()
this.saveEmail();
},
saveEmail(){
//here i tried to save the email using the onAuthStateChanged method
firebase.auth().onAuthStateChanged(function(user) {
this.$root.email = user.email;
});
},
send(messageInput) {
//A data entry.
let data = {
message: messageInput
//here i want to add it to the database
// user: this.$root.email
};
// Get a key for a new message.
let key = this.room.push().key;
this.room.child('messages/' + key).set(data)
// clean the message
this.messageInput = ''
},
messageListener () {
this.room.child('messages').on('child_added', (snapshot) => {
// push the snapshot value into a data attribute
this.messages.push(snapshot.val())
})
},
logout(){
firebase.auth().signOut().then(() => {
this.$root.email = null;
this.$router.replace('login');
})
},
}
}
</script>
And here is the script in my login component :
<script>
import firebase from 'firebase'
export default {
name: 'login',
data: function(){
return {
email: '',
password: '',
}
},
methods: {
signIn: function(){
firebase.auth().signInWithEmailAndPassword(this.email, this.password).then(
(user) => {
this.$root.email = user.email;
this.$router.replace('chat');
},
(err) => {
alert('Opppps! ' + err.message);
}
);
},
}
}
</script>
Sorry if I'm not being clear. Thanks in advance!
The callback of the onAuthStateChanged method is bind to the wrong this scope. You can easily fix this by using an arrow function like below. When using an arrow function, it will automatically bind to the context it is defined in.
saveEmail() {
firebase.auth().onAuthStateChanged((user) => {
this.$root.email = user.email;
})
}

How to use all functions vue-auth without using its login function

Im new to VueJS and trying to build authorization functions for my website.
First I attempt to use library name Vue-auth to handle authorization. It works fine, here is my code:
Login.vue
login () {
var redirect = this.$auth.redirect()
this.$auth.login({
headers: {
'Content-Type': 'application/json'
},
data: this.data.body,
rememberMe: this.data.rememberMe,
redirect: {name: redirect ? redirect.from.name : 'Home'},
success (res) {
console.log('Auth Success')
},
error (err) {
console.log(err)
}
navbar ():
<div class="nav-right is-flex">
<router-link v-if="!$auth.check()" to="/login" class="nav-item">Login</router-link>
<a v-if="$auth.check()" #click="logout" class="nav-item">Logout</a>
</div>
In router, to restrict access, I use auth property. Something like:
{
path: '/users',
name: 'users',
component: require('./components/pages/Users.vue'),
meta: {auth: ['admin']}
},
{
path: '/users',
name: 'users',
component: require('./components/pages/Users.vue'),
meta: true
}
And in app.js:
Vue.use(VueAuth, {
auth: {
request: function (req, token) {
this.options.http._setHeaders.call(this, req, {Authorization: 'Bearer ' + token})
},
response: function (res) {
// Get Token from response body
return res.data
}
},
http: require('#websanova/vue-auth/drivers/http/axios.1.x.js'),
router: require('#websanova/vue-auth/drivers/router/vue-router.2.x.js'),
loginData: { url: 'http://localhost:6789/login', fetchUser: false },
refreshData: { enabled: false }
})
But now I want to write a service to call axios to API Url myself, not using $auth.login function anymore. I changed my
login () {
var self = this;
_AuthenticationService
.login(this.data.body)
.then(response => {
self.info = response;
console.log(response);
})
.catch(err => {
self.info = err;
});
My service:
import axiosconfigurator from '../axiosconfigurator'
class AuthenticationService {
login (request) {
var self = this
return new Promise((resolve, reject) => {
axios.post('https://reqres.in/api/login', {
username: 'Fred',
password: '123'
})
.then(function (response) {
// get token from this response
var token = response.data.token
self._setAuthToken(token, true)
console.log(token)
// var data = core.Parsers.UserParser.parse(response);
// history.update(data);
// deferred.resolve(history);
})
.catch(function (error) {
console.log(error)
reject(error)
});
})
}
So my question is: I dont want to use the vue-auth library login function anymore, but I still want use its advantages like $auth.ready function, or auth property in router and $auth.user. How can I achieve it?
Based on the date of your question and the fact that the library was changed lately
You can call the login method on the vue-auth object passing the following option
makeRequest:false
You have a solution described there
https://github.com/websanova/vue-auth/issues/256
this.$auth.watch.authenticated = true
this.$auth.watch.loaded = true
this.$user(response.user)
this.$router.push('/dashboard')
I tested it and it was not working so I open a ticket
https://github.com/websanova/vue-auth/issues/563

Can't access Vue from js

I'm trying to create an App with Vue, and Vue-ressource
Actually i need to use ressource to made auth system by an API call.
But in my Auth.js (that i import into my login.vue) console said he can't read $http of undefined. So apparantly i can't reach 'this' (so vue).
Did i missed something ? Or its just a bad use ?
Thank you all
actually my main.js :
import Vue from 'vue'
import VueRouter from 'vue-router'
import VueResource from 'vue-resource'
Vue.use(VueRouter)
Vue.use(VueResource)
import App from './components/App.vue'
import Login from './components/Login.vue'
import Home from './components/Containers.vue'
function requireAuth (to, from, next) {
if (!auth.loggedIn()) {
next({
path: '/',
query: { redirect: to.fullPath }
})
} else {
next()
}
}
const router = new VueRouter({
mode: 'history',
routes: [
{ path: '/home', name: 'home', component: Home, beforeEnter: requireAuth },
{ path: '/', component: Login },
{ path: '/logout',
beforeEnter (to, from, next) {
auth.logout()
next('/')
}}
]
})
new Vue({
el: '#app',
router,
render: h => h(App)
})
the login.vue
import auth from '../utils/auth'
export default {
data () {
return {
email: '',
pass: '',
error: false
}
},
methods: {
login () {
auth.login(this.email, this.pass, loggedIn => {
if (!loggedIn) {
this.error = true
} else {
console.log('good')
this.$router.replace('/home')
}
})
}
}
}
and my auth.js where the vue-ressource post is made :
export default {
login (email, pass, cb) {
cb = arguments[arguments.length - 1]
if (localStorage.token) {
if (cb) cb(true)
this.onChange(true)
return
}
pretendRequest(email, pass, (res) => {
if (res.authenticated) {
localStorage.token = res.token
if (cb) cb(true)
this.onChange(true)
} else {
if (cb) cb(false)
this.onChange(false)
}
})
},
getToken () {
return localStorage.token
},
logout (cb) {
delete localStorage.token
if (cb) cb()
this.onChange(false)
},
loggedIn () {
return !!localStorage.token
},
onChange () {}
}
function pretendRequest (email, pass, cb) {
setTimeout(() => {
this.$http.post('localhost:9000/api/login', {email: email, password: pass}).then(response => {
if (response.status === 200) {
cb({
authenticated: true,
token: Math.random().toString(36).substring(7)
})
} else {
cb({ authenticated: false })
}
}, response => {
console.log('error ' + response.status)
})
}, 0)
}
Replace vue-resource with axios. Easy to do. Vue-resource is not longer maintained by Vue team, so it's bad choice to use it.( https://medium.com/the-vue-point/retiring-vue-resource-871a82880af4#.dwmy5ymjx )
Axios is widely supported. https://github.com/mzabriskie/axios .
Nice laracasts about using axios with vue. You will quickly get it. https://laracasts.com/series/learn-vue-2-step-by-step/episodes/18
It is normal that you can't access Vue instance in your auth module. Try to learn more about using this and you will quickly get it 'why?'
To make ajax requests in your auth module, just import axios and use axios.post / axios.get
Any questions? Comment and I will explain more.

Categories

Resources