I am using laravel passport for authentication in my laravel and vue.js ecommerce project.
After successful login, I want to redirect user to his/her dashboard.
Here is the vue dashboard page:
<template>
<div class="content-center">
<h1>Dashboard my account</h1>
<p>
{{userData.name}}
</p>
</div>
</template>
<script>
import Axios from "axios";
export default {
data() {
return {
userData: "",
authToken: ""
}
},
async beforeMount() {
let res = await Axios.get("http://localhost:8000/api/user-details", {
headers: {
Authorization: "Bearer " + this.authToken,
Accept: 'application/json'
},
});
this.userData = res.data;
// let token = await Axios.get("http://localhost:8000/api/user-login")
// this.authToken = res.data.data.auth_token
//let res = await Axios.get("http://localhost:8000/api/user-details");
},
};
</script>
Everytime I login to different user accounts, I have to set the value of authToken manually copy and pasting from Postman. I want to set this token automatically when a user logs in. How can I do this ?
Here is my api controller:
class AuthApiController extends Controller
{
public function userDetails(){
return auth()->user();
}
public function login(Request $request){
$user = User::where('email',$request->email)->first();
if (!$user || !Hash::check($request->password, $user->password)) {
return response()->json([
'success'=>false,
'data'=>[],
'message'=>'Login failed',
'errors'=>[]
]);
}else{
return response()->json([
'success'=>true,
'data'=>['user'=> $user, 'auth_token' => $user->createToken('AuthToken')->accessToken],
'message'=>'Login success',
'errors'=>[]
]);
}
}
Updates:
dashboard.vue
<template>
<div class="content-center">
<h1>Dashboard my account</h1>
<p>
{{userData.name}}
</p>
</div>
</template>
<script>
import Axios from "axios";
export default {
data() {
return {
userData: "",
authToken: ""
}
},
async beforeMount() {
let res = await Axios.get("http://localhost:8000/api/user-details", {
headers: {
Authorization: "Bearer " + this.authToken,
Accept: 'application/json'
},
});
this.userData = res.data;
let token = await $api.get("http://localhost:8000/api/user-login")
this.authToken = res.data.data.auth_token
},
};
</script>
Picture:
enter image description here
What should I write to import api.js ?
import $api from ./../api.js or anything else ?
Well, you can store your token in LocalStorage. And whenever you request just get it from the local storage and pass it to the request header.
If you are using Axios then you can use interceptors and just intercept your every request and pass token in the header.
Step 1.
Create a file called api.js or you can call it whatever you want.
Step 2.
Create an Axios instance in the api.js file.
import axios from 'axios';
// Put your backend url here
export const API_URL = `http://localhost:5000/api`
const $api = axios.create({
withCredentials: true,
baseURL: API_URL
})
$api.interceptors.request.use((config) => {
config.headers.Authorization = `Bearer ${localStorage.getItem('token')}`
return config;
})
export default $api;
Step 3: Where ever you are using Axios use this exported instance so in your component you would do like this:
const userdata = await $api.get("http://localhost:8000/api/user-details");
Here you can see, we are using the $api Axios instance which we created in the api.js file instead of Axios direct.
Add also don't forget to store your token in your local storage when you getting that.
localStorage.setItem('token', "Your token goes here...");
I hope this will give you an idea.
This way, Token will be sent with every request automatically, if it exists in the localStorage.
UPDATE:
<template>
<div class="content-center">
<h1>Dashboard my account</h1>
<p>
{{userData.name}}
</p>
</div>
</template>
<script>
// import Axios from "axios";
import $api from 'put relative path of your api.js file'
export default {
data() {
return {
userData: "",
authToken: ""
}
},
async beforeMount() {
let res = await $api.get("/user-details");
this.userData = res.data;
let res = await $api.get("/user-login")
localStorage.setItem('token', res.data.data.auth_token);
},
};
</script>
Related
So basicaly I want to fetch the data from Laravel server to next js api server and this seems to be working fine for the other atributes like title but the image is not fetching and return error 500 and 'ECONNREFUSED'
Here is the code for courses inside the api colder pages/api/courses.ts
import { NextApiRequest, NextApiResponse } from "next";
import axios from "axios";
import Course from "../../models/course";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const courses = await Course.fetchAll();
res.status(200).json(courses);
}
Code for the api route on laravel
Route::get('/courses', function () {
$courses = Courses::all();
// allow to remote access
header('Access-Control-Allow-Origin: *');
return response()->json(['courses' => $courses], 200);
});
Code for the API call
const fetchCourses = async () => {
const courses = await axios.get("http://localhost:3000/api/courses", {
headers: {
"Content-Type": "application/json",
// allow cors
"Access-Control-Allow-Origin": "*",
},
});
setCourses(courses.data);
};
The image appears like that
The error that appears on image url
I fixed it by replacing the NextImage tag with normal image tag and it worked
I have used breeze-next as a boilerplate.
User register and login work perfectly but when I create a custom hook to interact with the server, Axios sends requests to front-end address, instead of the server.
I have declared the server address in .env file:
NEXT_PUBLIC_BACKEND_URL=http://localhost:8000
Axios configuration:
import Axios from 'axios'
const axios = Axios.create({
baseURL: process.env.NEXT_PUBLIC_BACKEND_URL,
headers: {
'X-Requested-With': 'XMLHttpRequest',
},
withCredentials: true,
})
export default axios
My custom hook:
export const useAccount = () => {
const csrf = () => axios.get('/sanctum/csrf-cookie')
const {data: user, error, mutate} = useSWR('/api/user', () =>
axios
.get('/api/user')
.then(res => res.data)
.catch(error => {
if (error.response.status !== 409) throw error
router.push('/verify-email')
}),
)
const start = async ({setErrors, setStatus, ...props}) => {
await csrf() // <-- Fails Here
axios.post('/user/account/start', props)
.then(() => mutate())
.catch(error => {
setErrors(Object.values(error.response.data.errors).flat())
})
}
return {
start
}
}
When axios sends a get request it sends the request to http://localhost:3000/sanctum/csrf-cookie which is the front-end address.
The problem was with wrong import.
I didn't pay attention to what file is IDE importing as axios into account Hook.
It was like this:
import axios from "axios"
So I changed it to:
import axios from "#/lib/axios"
I'm trying to authenticate to Xero's API. I get a 'code' which is then exchanged for an access_token. I'm still new to NextJS and React so I'm likely not thinking about this correctly.
The code I have results in the right data being returned, however I don't know how to use it effectively in the rest of the app. I couldn't figure out how to use NextAuth in a custom provider so tried to roll my own.
The user clicks the button 'Connect to Xero' - this is a href to initiate the process and takes the user to Xero to login in the browser. User authenticates. Xero calls the callback
the callback at /api/callback responds
I extract the 'code' and then make the subsequent request to Xero to swap it for an access token.
This is where I get stuck - because the initial action is a href redirect, I'm not sure how to get the end API result back into my code as state/something usable. In effect Xero is calling the api/callback page and that's where the user is left.
I've tried to put useState hooks into the api/callback however that breaks the rule of hooks.
Any pointers greatly appreciated.
Code;
pages/index.js
import React from 'react'
import Layout from '../components/Layout'
import TopNav from '../components/TopNav'
import Link from 'next/link';
export default function Main(props) {
const test = props.URL
return (
<>
<Layout>
<TopNav name="Main page"/>
<p>this is the main page</p>
<Link href={test} passHref={true}>
<button className=' w-40 border rounded-md py-3 px-3 flex items-center justify-center text-sm font-medium sm:flex-1'>
Connect to Xero
</button>
</Link>
</Layout>
</>
)
}
export async function getStaticProps() {
const XeroAuthURL = "https://login.xero.com/identity/connect/authorize?response_type=code&client_id="
const client_ID = process.env.XERO_CLIENT_ID
const redirect_uri = process.env.XERO_REDIRECT_URI
const scope = "offline_access openid profile email accounting.settings"
const URL = `${XeroAuthURL}${client_ID}&redirect_uri=${redirect_uri}&scope=${scope}`
return {
props: {
URL: URL
},
};
}
/api/callback.js
import axios from "axios"
const qs = require('qs');
export default async function callback(req, res) {
try {
//callback from Xero will deliver the code, scope + state (if given)
//https://developer.xero.com/documentation/guides/oauth2/auth-flow/#2-users-are-redirected-back-to-you-with-a-code
console.log(`REQ = ${JSON.stringify(req.query)}`)
//exchange code for tokens - https://developer.xero.com/documentation/guides/oauth2/auth-flow/#3-exchange-the-code
var data = qs.stringify({
'code': req.query.code,
'grant_type': 'authorization_code',
'redirect_uri': 'http://localhost:3000/api/callback'
});
var config = {
method: 'post',
url: 'https://identity.xero.com/connect/token',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic **put your authorisation result here**'
},
data : data
};
try {
const response = await axios(config)
//response has the data I want to put into State
console.log(JSON.stringify(response.data));
//save data off here somehow???
//tried redirecting but unsure if can pass the result
res.redirect(307, '/')
} catch (error) {
console.error(error)
res.status(error.status || 500).end(error.message)
}
} catch (error) {
console.error(error)
res.status(error.status || 500).end(error.message)
}
}
Added a not-secure cookie that I can use while testing. Do not use this in production as the cookie is not httpOnly and not secure.
import axios from "axios"
import Cookies from 'cookies'
const qs = require('qs');
export default async function callback(req, res) {
const cookies = new Cookies(req,res)
try {
var data = qs.stringify({
'code': req.query.code,
'grant_type': 'authorization_code',
'redirect_uri': 'http://localhost:3000/api/callback'
});
var config = {
method: 'post',
url: 'https://identity.xero.com/connect/token',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic **YOUR AUTH CODE HERE**'
},
data : data
};
try {
var response = await axios(config)
response.data.expires_at = Date.now() + response.data.expires_in*1000
//save data off
//TO DO - THIS IS REALLY BAD - ONLY USE THIS TEMPORARILY UNTIL HAVE GOT PERMSTORAGE SETUP
cookies.set('myCookieName', JSON.stringify(response.data), {
secure: false,
httpOnly: false
}
)
res.redirect(307, '/')
//return ({ data: response.data })
} catch (error) {
console.error(error)
res.status(error.status || 500).end(error.message)
}
} catch (error) {
console.error(error)
res.status(error.status || 500).end(error.message)
}
}
Then in the index;
import React from 'react'
import Layout from '../components/Layout'
import TopNav from '../components/TopNav'
import Link from 'next/link';
import { getCookie } from 'cookies-next';
export default function Main(props) {
//check for cookie
//TO DO THIS IS REALLY BAD; CHANGE WHEN GET PERM STORAGE ORGANISED
const cookie = getCookie('myCookieName');
const URL = props.URL
return (
<>
<Layout>
<TopNav name="Main page"/>
<p>this is the main page</p>
<Link href={URL} passHref={true}>
<button className=' w-40 border rounded-md py-3 px-3 flex items-center justify-center text-sm font-medium sm:flex-1'>
Connect to Xero
</button>
</Link>
<p>{cookie ? cookie : 'waiting for cookie...'}</p>
</Layout>
</>
)
}
export async function getStaticProps() {
const XeroAuthURL = "https://login.xero.com/identity/connect/authorize?response_type=code&client_id="
const client_ID = process.env.XERO_CLIENT_ID
const redirect_uri = process.env.XERO_REDIRECT_URI
const scope = "offline_access openid profile email accounting.settings"
//console.log(`URL - ${XeroAuthURL}${client_ID}&redirect_uri=${redirect_uri}&scope=${scope}`)
const URL = `${XeroAuthURL}${client_ID}&redirect_uri=${redirect_uri}&scope=${scope}`
return {
props: {
URL: URL,
},
};
}
I am trying to show client information details in the modal. After clicking #click="showDetails(props.row.id)".
I am using axios.get in method and returning the data. Now, It's returning the data as PromiseValue object. How to access PromiseValue to show the value in HTML. Would someone help me please to solve the problem! I am trying like below -
<button #click="showDetails(props.row.id)"><i class="fas fa-eye"></i></button>
And in script-
<script type="text/javascript">
import axios from 'axios';
export default {
data(){
return{
leftPanelVisiblity: false,
singleData: '', }
},
methods:{
showDetails(id){
let b = axios.get('/api/clients/'+id)
.then(function (response) {
return response.data;
}).catch(error => {
alert(error);
});
//console.log(b);
this.singleData = b;
this.leftPanelVisiblity = true
},
}
}
</script>
And finally, I want to access or show the data in the leftPanelVisiblity modal like -
<p>Name: {{ this.singleData.name }}</p>
Or
<p>Name: {{ this.singleData.email }}</p>.
You cannot assign the Axios call to a variable while using Promises (unless you are using await/async).
Instead you should be running the logic within the then callback. Otherwise to the synchronous nature of JavaScript it will run before the request has completed. Your code should look something like this:
methods:{
showDetails(id){
axios.get('/api/clients/'+row.id).then(response => {
//Logic goes here
this.singleData = response.data
this.leftPanelVisibility = true
}).catch(error => {
alert(error);
});
}
}
You need to assign a variable the response of your axios:
showDetails(id){
axios.get('/api/clients/'+id)
.then(function (response) {
this.singleData = response.data;
}).catch(error => {
alert(error);
});
console.log(this.sigleData);
this.leftPanelVisiblity = true
},
I've created the most basic react app possible and am trying to do a simple GET request. It throws a TypeError and states, 'name.toUppercase is not a function'. I only have the one function. Any ideas what is causing this or how to debug?
import React, { Component } from 'react';
import axios from 'axios';
import logo from './logo.svg';
import './App.css';
class App extends Component {
state = {
order_id: Number,
order_date: '',
size: '',
crust: '',
toppings: [],
};
componentDidMount() {
return axios
.get('https://59b6v76zci.execute-api.us-west-
2.amazonaws.com/nr/example', {
method: 'GET',
mode: 'cors',
headers: 'Access-Control-Allow-Origin',
})
.then(response => this.setState({ order_id: response.order_id }))
.catch(err => console.log('err', err));
}
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
</div>
);
}
}
export default App;
This is the what is returned in the console
err TypeError: name.toUpperCase is not a function
at processHeader (normalizeHeaderName.js:7)
at Object.forEach (utils.js:218)
at normalizeHeaderName (normalizeHeaderName.js:6)
at transformRequest (defaults.js:32)
at transform (transformData.js:16)
at Object.forEach (utils.js:224)
at transformData (transformData.js:15)
at dispatchRequest (dispatchRequest.js:37)
at <anonymous>
Try changing your axios request to this:
axios
.get('https://59b6v76zci.execute-api.us-west-2.amazonaws.com/nr/example', {
method: 'GET',
mode: 'cors',
headers: { 'Access-Control-Allow-Origin': true },
})
.then(response => this.setState({ order_id: response.data.order_id }))
.catch(err => console.log('err', err));
You got two things wrong - headers should be an object, and the data in the response should be under response.data.
Also, on a side-note, Access-Control-Allow-Origin header usually comes as a response header and not on the request.