I am getting a token to access an API endpoint and I want to send this token to my server-side app (expressJS) to retreive the data.
I have the following for my react app:
export default class Account extends React.Component {
constructor() {
super();
this.state = {
token: null,
response: {
}
};
this.getCurrentlyPlaying = this.getCurrentlyPlaying.bind(this);
}
componentDidMount() {
// Set token
let _token = hash.access_token;
if (_token) {
this.setState({
token: _token
});
const cookies = new Cookies();
cookies.set('token', _token, { path: '/' });
console.log(cookies.get('token'));
this.getCurrentlyPlaying(_token);
}
}
getCurrentlyPlaying() {
fetch(`http://localhost:3001/account`)
.then(res => res.json())
.then(data => {
this.setState ({
response: data
})
console.log(data);
});
}
render() {
if (this.state.response[0].is_playing === true) {
return (
<p> Something is playing</p>
);
}
else {
return (
<p> Nothing is playing</p>
);
}
}
}
In my express app, I have the cookie being gotten but I'm not sure if it actually is getting the cookie created by the react app:
router.get('/account', (req, res) => {
const config = {
headers: {
'Authorization': `Bearer ${req.session.token}`
}
};
fetch(`${CONFIG.spotifyUrl}/me/player/currently-playing `, config)
.then(html => html.json())
.then(json => {
res.json(json);
});
});
module.exports = router;
Can someone tell me where I'm going wrong please?
To parse cookies in backend with express, a good choice is to use the https://github.com/expressjs/cookie-parser middleware.
Provided you are using setup something similar to below
const cookieParser = require('cookie-parser');
app.use(cookieParser());
Every Request object on server will have cookies information in the req.cookies property. So in your case it should be req.cookies.token
Related
I have created signalR connection in my ReactJS application, whenever i load page for the first time then i get an error "Error: Failed to complete negotiation with the server: Error: Unauthorized" but when i reload the page again then it works fine i.e. it get connected properly.
I just want to connect the signalR connection properly when page load for the first time without the need to reload it again
Here is my code for signalR connection:
export default class Dashboard extends Component {
constructor(props) {
super(props)
this.state = {
signalRURL: 'https://****/?hub=broadcast',
accessToken: '',
alertData: {}
}
}
getURL = () => {
return new Promise((resolve, reject) => {
return axios({
url: 'https://*****/api/SignalRConnection',
method: "get",
headers: {
"content-type": "application/json",
"Access-Control-Allow-Origin": "*"
},
})
//Get the SignalR connection information which contains Url and Access token,
//by calling the SignalRConnection API.
.then(response => {
localStorage.setItem("access_key", response.data.accessToken)
console.log("response", response)
resolve(response);
})
.catch(error => {
reject(error);
});
});
}
componentDidMount = () => {
this.getURL().then(data => {
console.log("dataaa", data)
})
.catch(err => {
console.log("error", err)
})
//Create the Hub connection using SignalR.HubConnectionBuilder.
const options = {
accessTokenFactory: () => localStorage.getItem("access_key")
};
const hubConnection = new SignalR.HubConnectionBuilder()
.withUrl(this.state.signalRURL, options)
.configureLogging(SignalR.LogLevel.Information)
.build();
hubConnection.on('notify', data => {
this.setState({alertData: data})
console.log("state data",this.state.alertData)
console.log(data);
});
hubConnection
.start()
.catch(
error => console.error(error)
);
hubConnection.serverTimeoutInMilliseconds = 6000000;
hubConnection.keepAliveIntervalInMilliseconds = 3000000;
hubConnection.onclose((error) => {hubConnection.start();
console.error(`Something went wrong: ${error}`); });
}
render() {
return (
<div>
</div>
)
}
}
This is the error message i get everytime when i load the page for the first time
After reading the following post, https://dev.to/chrsgrrtt/easy-user-authentication-with-next-js-18oe and consulting the following question Using next-iron-session's "withIronSession" with Next.JS to perform simple authentication, I am still unable to access the session using req.session.get('user'). Below is my implementation in a Next.js project:
Create a util
import {withIronSession} from 'next-iron-session';
const cookie = {
cookieName: process.env.COOKIE_NAME,
password: process.env.COOKIE_SECRET,
cookieOptions: {secure: process.env.NODE_ENV === 'production'},
};
export const guard = (handler) => {
return withIronSession(handler, cookie);
};
export default cookie;
Create an API endpoint
const zlib = require('zlib');
import cookie from '#/utils/cookie';
const fetch = require('node-fetch');
import {withIronSession} from 'next-iron-session';
export default withIronSession(
async (req, res) => {
if (req.method === 'POST') {
try {
const request = await fetch(
process.env.NEXT_PUBLIC_API_BASE_URL + '/api/login',
{
method: 'post',
body: req.body,
headers: {
'Content-Type': 'application/json',
'Origin': req.headers.host || req.headers.origin,
},
}
);
const response = await request.text();
const {success, data, message} = JSON.parse(response);
// set JWT in session
compressor(data, (x) => req.session.set('user', x));
// persist session value
await req.session.save();
// console.log(req.session.get('user'));
return res.status(201).json({success, message});
} catch (error) {
console.log(error);
}
}
return res.status(404).json('Not found');
},
cookie
);
Access session data in a page
export const getServerSideProps = guard(async (ctx) => {
const {req} = ctx;
const session = req.session.get();
console.log({session});
return {redirect: {destination: '/sign-in', permanent: false}};
});
The above terminal log gives an empty object. Is there something am doing wrong??
Try the following:
export const getServerSideProps = guard(async function ({
req,
res,
query,
}) {
//Assuming you have "user" session object
const user = req.session.get("user");
...
});
Harel
Hi so the problem i'm struggling with is i have an api with an accesskey and i don't know how to setup the header inside the component with that api access key, i'm using a default fetch random user api in example below but i want to know how and where should i add that header with access key, thanks in advance.
import React from 'react';
export default class FetchRandomUser extends React.Component {
async componentDidMount() {
const url = "https://api.randomuser.me/"
const response = await fetch(url)
const data = await response.json();
this.setState({ person: data.results[0], loading: false })
}
render() {
return <div>
{this.state.loading || !this.state.person ? (<div>Loading...</div>) : (<div>{this.state.person.name.first}</div>)}
</div>
}
}
fetch(url, {
method: 'GET',
headers: {
authorization: youKEY,
Accept: 'application/json',
},
});
This is how you can pass your api key in url https://randomapi.com/api/qcol88t8?key=TCGJ-8B0M-33L6-UX5Q;`
Code
export default class FetchRandomUser extends React.Component {
state = {
loading: true,
person: {}
};
async componentDidMount() {
const url = `https://randomapi.com/api/qcol88t8?key=TCGJ-8B0M-33L6-UX5Q`;
const response = await fetch(url);
const data = await response.json();
this.setState({ person: data.info, loading: false });
}
render() {
return (
<div>
{this.state.loading || !this.state.person ? (
<div>Loading...</div>
) : (
<h2>{this.state.person.user.username}</h2>
)}
</div>
);
}
}
0
fetch(your_url,a_json_object) Here,json_object has one element called headers,just use your custom header in it. But most noobies forget to add the header in backend.I am showing a correct example:
front end:
fetch('fdf.api/getid',{
method:'post',
headers:{"a_custom_header":"custom_value"}
})
backend:
const express = require('express')
const app = express()
app.use(function(req,res,next){
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS,
PUT,PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type,a_custom_header'); //notice here carefully
res.setHeader('Access-Control-Allow-Credentials', true);
next();
})
Im trying to set the state with the data coming back from the axios get.But I keep getting this error TypeError: Cannot read property 'setState' of undefined.
class Page extends React.Component {
constructor(props) {
super(props);
this.authenticated = props.authenticated;
//this.handleClick = this.handleClick.bind(this);
}
state ={
page : []
}
componentDidMount() {
let config = null;
//let token = null;
app.auth().currentUser.getIdToken(true).then(function(idToken) {
config = {
headers: {'Authorization': idToken}
};
console.log(config);
axios.get('http://localhost:4001/api/v1/page',config)
.then(res => {
console.log(res.data);
const page = res.data;
this.setState( page );
}).catch((err)=>{
console.log(err);
});
})
}
render () {
const authenticated = this.authenticated;
console.log(authenticated);
console.log(this.state);
return (
<h1> test 123</h1>
);
}
}
this inside axios refers to a different thing, store the value of this in a variable and use that variable
componentDidMount = () => {
let config = null;
//let token = null;
const current = this; // here save this in current variable
app
.auth()
.currentUser.getIdToken(true)
.then(function(idToken) {
config = {
headers: { Authorization: idToken }
};
console.log(config);
axios
.get('http://localhost:4001/api/v1/page', config)
.then(res => {
console.log(res.data);
const page = res.data;
current.setState(page); // use current here
})
.catch(err => {
console.log(err);
});
});
}
I have a JS file within my React application, which connects to the server, sends username and password, receives an oauth token from the server and stores the token in the local storage.
However before the token received by react, the react sends the next request before token stored in the local storage. Which leads to 401 unauthorized access.
AuthService.js
login(username, password) {
console.log(username);
return this.fetch(`${this.domain}/api/AuthAPI/getCredentials`, {
headers: {
'Access-Control-Allow-Origin': "*"
}
}).then(res => {
this.fetch(`${this.domain}/Token`, {
method: 'POST',
body: 'grant_type=password&username=' + res[0]
}).then(response => {
var date_token_issue = new Date();
this.setToken(response.access_token,response.expires_in, date_token_issue) // Setting the token in localStorage
return Promise.resolve(response);
})
})
}
setToken(idToken,expires, date_token_issue ) {
localStorage.setItem('id_token', idToken)
localStorage.setItem('expires', expires)
localStorage.setItem('date_token_issue', date_token_issue)
}
SignIn.jsx
import React, { Component } from 'react'
import AuthService from '../comonents/AuthService';
import Orders from '../../app/orders/orders'
import { Redirect, Switch, Route} from "react-router-dom";
export default function SignIn(AuthComponent){
const Auth = new AuthService('http://localhost:53050');
return class AuthWrapped extends Component {
constructor() {
super();
this.state = {
user: null,
loggedIn: false
}
}
async componentDidMount() {
if (!Auth.loggedIn()) {
const promise = await Auth.login('m.dawaina', 'm.dawaina');
console.log(promise)
this.setState({loggedIn: true});
}
else {
try {
this.setState({loggedIn: true})
const profile = Auth.getProfile()
this.setState({
user: profile
})
}
catch(err){
Auth.logout()
//this.props.history.replace('/login')
}
}
}
render() {
if (this.state.loggedIn) {
return (
<div>
<Redirect to='/orders'/>
<Switch>
<Route path="/orders" component={Orders} />
</Switch>
</div>
)
}
else {
return (
<AuthComponent history={this.props.history} user={this.state.user} />
)
}
}
}
}
I need a way to force react wait for the JS receives the token and stores it in the local storage, and prevent react sending the next request until it finds the token stored in the local storage.
login(username, password) {
console.log(username);
return this.fetch(`${this.domain}/api/AuthAPI/getCredentials`, {
headers: {
'Access-Control-Allow-Origin': "*"
}
}).then(res => {
// Add a return here
return this.fetch(`${this.domain}/Token`, {
method: 'POST',
body: 'grant_type=password&username=' + res[0]
}).then(response => {
var date_token_issue = new Date();
this.setToken(response.access_token,response.expires_in, date_token_issue) // Setting the token in localStorage
return Promise.resolve(response);
})
})
You need to add a return to the then function so that await will wait for the inner promise to resolve.