I am trying to get a long lived access token from facebook... according to the documentation, I need to fetch from the server side for security. If I fetch from the client side it works fine - but I should follow the guidelines.. Here is what I am doing - can you tell me why I get the server side error "Reference error: fetch is not defined"?
First I created a route from the front end to request the long lived token. To get the long lived token I need to use the short lived token so I send the short lived token in the req params. The variable userAccessTokenShort is valid and defined.
const newLongLivedUserAccessToken = await fetch(`/api/autoquotegenerators/longLivedUserToken/${userAccessTokenShort}`, {
method: 'GET',
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json; charset=UTF-8",
},
})
const newLongUserTokenRes = await newLongLivedUserAccessToken.json()
console.log(newLongUserTokenRes)
Then, on my express server, I made a route that handles the fetch request to the Facebook Graph API. This is where I get the reference error.
//Get Long Lived User Access Token on Backend /express route
router.get('/longLivedUserToken/:shortLived', (req, res) => {
try {
const getLongToken = fetch(`https://graph.facebook.com/v7.0/oauth/access_token?grant_type=fb_exchange_token&client_id=#############&client_secret=################&fb_exchange_token=${req.params.shortLived}`)
.then(token => res.send(token))
} catch (error) {
console.log(error)
}
})
If all goes well, the new token should be sent back to the client.
Thanks for your help!
There is no fetch() function built into node.js. If you want something that looks pretty much like fetch() in the browser, you can look at the node-fetch module in NPM.
Or, there are lots of modules you can choose from in node.js. My favorite is got().
FYI, the built-in interface for fetching http requests is http.request() or http.get(), but they are lower level and require more lines of code to do something simple than any of the above named modules.
Related
In my React Native app -- init app not Expo -- I'm trying to refresh the access_token but my POST call is failing with 401. I'm testing this functionality so I make the POST call some 30 seconds after I login so not sure if this plays a role or not.
In my initial login, I do get a refresh_token along with a valid access_token. I then tell my app to wait 30 seconds and make a POST call that looks like this:
const url = 'https://mydomain.auth0.com/oauth/token';
const postOptions = {
method: 'POST',
url: url,
headers: {
"content-type": 'application/x-www-form-urlencoded'
},
form: {
grant_type: 'refresh_token',
client_id: 'MY_CLIENT_ID',
refresh_token: 'REFRESH_TOKEN_RECEIVED_DURING_LOG_IN'
}
};
fetch(url, postOptions)
.then((response) => {
debugger;
// this is where I get response.status 401
})
Any idea what the issue is here?
Also want to mention that under my application settings, Refresh Token is checked under "Grant Types" but refresh token rotation or expiration are NOT enabled.
I figured this out and sharing it in case others need it in the future.
First, Auth0 documentation is misleading at best. They keep mentioning a regular POST call which doesn't work.
In my React Native app, I use their react-native-auth0 library. This library does offer a refreshToken() method which is what I ended up using.
Before I share the code, here are a couple of really important points:
Be sure to include offline_access in the scope of your initial authentication call for the user. Without including offline_access in your scope, you won't get a refresh_token. Once you receive it along with your access_token and id_token, store it as you'll use it many times. This brings me to the second point.
Unless you set it otherwise, your refresh_token doesn't expire. Therefore, store it some place secure and NOT just in AsyncStorage. As mentioned above, unless, you set it otherwise or it gets revoked, your refresh_token doesn't expire and you use it again and again.
With that said, here's the code. Please keep in mind that at start up, I initialize auth0 as a global variable so that I can access it in different parts of my app.
Here's what my initialization looks like in index.js:
import Auth0 from 'react-native-auth0';
global.auth0 = new Auth0({
domain: "MY_DOMAIN.auth0.com",
clientId: "MY_CLIENT_ID",
});
And here's how I use the refreshToken() method:
// First, retrieve the refresh_token you stored somewhere secure after your initial authentication call for the user
global.auth0.auth.refreshToken({ refreshToken: 'MY_REFRESH_TOKEN' })
.then(result => {
// If you're doing it right, the result will include a new access_token
})
you probably need to add the authorization header with your access_token:
const url = 'https://mydomain.auth0.com/oauth/token';
const postOptions = {
method: 'POST',
url: url,
headers: {
"content-type": 'application/x-www-form-urlencoded',
"Authorization" 'bearer '+access_token,
},
body: JSON.stringify({
grant_type: 'refresh_token',
client_id: 'MY_CLIENT_ID',
refresh_token: 'REFRESH_TOKEN_RECEIVED_DURING_LOG_IN'
});
};
fetch(url, postOptions)
.then((response) => {
debugger;
// this is where I get response.status 401
})
I have read many articles in stackoverflow and have seen lots of youtube videos, but failed to find the example code which is demonstrating about the flow of saving jwt to localstorage - send back to server with authorization header for verifying.
Here is what I want to do.
When the client logs in to the server, server gives token and saves it to the client localStorage (or sessionStorage).
Whenever the client calls an api which can be accessed only with the token,
client retrieves the token back from the localStorage, and send that token with the authorization header (req.headers.[x-access-token] or req.headers.[authorization]) to the server.
But all of the articles I've been read is explaining this issue with the Postman which does not show how to store it to the localStorage and put it in the authorization header.
Do I have to use localStorage.setItem when the server gives the token to the client, and use and localStorage.getItem and new Headers() with append() or axios before sending that token back to the server?
Examples don't have to be for the express user, but I'd like to get the glimpse of ideas.
You can store your jwt token in localstorage and when ever you make a API call you can add the token to headers as token. if you are using axios you can attach you token to headers like this. Here the token is stored in localstorage with the key 'jwtToken'
axios.post('http://yourendpoint',data,{ headers: { Authorization:localStorage.getItem('jwtToken') } })
.then(response=> console.log(response))
.catch(error => console.log(error));
};
it's easy just Follow me
First of all you have to save the Token(or access token) to the local storage,
in the login component when you are sending request for login do the below:
signin:function() {
axios.post('http://Somthing/log-in/',{
username: this.username,
password: this.password,
})
.then( (response) => {
let token = response.data.access;
localStorage.setItem("SavedToken", 'Bearer ' + token);
axios.defaults.headers.common['Authorization'] = 'Bearer ' + token;
(this.$router.push({name:'HomePage'}));
})
So now the problem is whenever you refresh the Homepage you got 401 error and the solution is : just add this :
{ headers: { Authorization:localStorage.getItem('SavedToken') }}
to the end of each request that need the Token in its header, like below:
axios.get('http://Something/', { headers: { Authorization:localStorage.getItem('SavedToken') }})
.then(response =>{
//something
})
Notice that the token that i used in this explanation was SIMPLEJWT , if you are using somthing else maybe you have to change 'Bearer' to somthing else.
First you have to create or Generate Token through Jwt (jsonWebTokens) then either store it in local Storage or through Cookie or through Session. I generally prefer local storage because it is easier to store token in local storage through SET and retrieve it using GET method. and after retrieving it through get you can verify it through jwt and also authenticate it with bearer authentication..
And for headers add Authorization
fetch("/users", {
method: "Get",
headers: {
"content-type": "application/json",
Authorization: "Bearer" + localStorage.getItem("token")
}
JWTs should never be stored in your localStorage
In fact, they shouldn't even be stored in your cookies, unless you are able to implement very strict CSRF protection
Checkout this for motivation
JWT as an id_token is like your user credentials
JWT as an access_token is like your session token
One option is in-memory. Checkout this for a deep dive
Currently I am using JWT-Auth on my Laravel back-end to protect my API routes with a token. However, after a certain time the token gets invalid and I get the error 401 Unauthorized. So I guess I have to refresh the token somewhere. When would be the best time to do this? I read about doing it every time you make a request but I want to be sure that’s the right way to do so. I used this guide from their docs: https://jwt-auth.readthedocs.io/en/develop/quick-start/#create-the-authcontroller. In here they make a function to fresh a token. But how would I implement this every time I make a request? Do I just call this function in the controller with an Axios request or call it in another controller or something? Any tips are greatly appreciated.
I have a Vue.js front-end by the way.
With Tymon/JWTAuth you have two options:
You can add the jwt.refresh middleware to your api routes, which will refresh the token everytime a request is made. The downside of this solution is that this could be abused. The upside is that you do not really need to worry about the token in your application, especially if you do not have a frontend or do not develop the frontend yourself.
You parse the token client side. The first two parts of a jwt token are completely public and are base64-encoded. You don't really need to know if this token was signed by the server client-side, so you can safely ignore the last part. This solution is relatively easy if you have a wrapper around api calls that handles common logic for api calls (e.g. adding the authorization header to begin with).
const token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImlzcyI6Imh0dHBzOi8vZXhhbXBsZS5jb20iLCJpYXQiOjE1NTUzNDkxMjYsImV4cCI6MTU1NTM3NzkyNiwibmJmIjoxNTU1MzQ5MTI2LCJqdGkiOiJtZEdTNGE2ZDJnNHM5NzRnNSJ9.TygbG5smlhAapE8fy4rgXlLVYW-qOcWtLYnnbgJCIKg";
function shouldRefreshToken(token) {
const currentTime = 1555350309829; // Date.now()
const universalTimestamp = currentTime / 1000;
const gracePeriod = 60 * 60 * 8; // 8 hours
const tokenParts = token.split('.');
const payload = JSON.parse(atob(tokenParts[1]));
if (payload.iat > universalTimestamp) {
console.log("This monstrosity was issued in the future O_o");
}
if (payload.nbf > universalTimestamp) {
console.log("This token is not valid yet. Refreshing it does not yield anything useful. Maybe we still have some previous token?");
}
if (payload.exp < universalTimestamp) {
console.log("This token has expired. We should try to refresh it before doing anything else.");
} else if (payload.exp - gracePeriod < universalTimestamp) {
console.log("This token is about to expire. We can refresh it asynchronously.");
} else {
console.log("Nah, we are fine!");
}
}
shouldRefreshToken(token);
In the end you would want to send a request to a refresh endpoint that does something like this, which is then parsed by the frontend:
$myNewToken = JWTAuth::refresh(JWTAuth::getToken());
response()->header('Authorization', "Bearer {$myNewToken}");
To get it to work, you can do something like this:
import store from '../store';
import { shouldRefreshToken } from '../helpers/auth';
const someBaseUrl = 'https://example.com';
export function request(options = {}) {
// Hopefully you rewrite that function above to return a boolean ;-)
if (shouldRefreshToken(store.state.auth.token)) {
refreshToken();
}
const config = {
method: options.method,
url: `${someBaseUrl}/${options.resource}`,
credentials: 'include',
headers: {
...(options.headers || {}),
Authorization: `Bearer ${store.state.auth.token}`,
'Content-Type': 'application/json'
},
data: options.data
}
return axios(config).then(parseResponse)
}
function parseResponse(axiosResponse) {
// Probably want to get the token and do something with it
}
function refreshToken() {
axios({
method: 'POST',
url: `${someBaseUrl}/refresh`
}).then(parseResponse)
}
My react web application uses axios to make an API post request.
The API needs a parameter called token for each post request.
Is there a way to always add the token parameter for each post request I do, so I don't have to add it manually every time, and where to save this token in a secure location?
I feel what I do now is a bit redundant. Example:
axios.post('apiUrl.com', {
token: 'abcdefg12345678',
userId: 1
}).then(() => {//do something});
Use axios interceptors. If you add a request interceptor, you can make a change (add token) to each request:
axios.interceptors.request.use(function(config) {
config.data = config.data || {};
config.data.token = 'abcdefg12345678';
return config;
});
I'm new to react native and I need some help.
I'm writing an app for android with react native.
I had already implemented the login Screen and all screens that should be shown when the loggin process completed successfully.
I don't know to to make a http request with bearer auth to my localhost website.The Request Method is GET. In my app i have to enter username and password and send it to the https:/localhost/.../login.
This is working so far: I get the tipped user and password from the TextInput of the loginscreen and send both to my function called httpRequest.
function httpRequest(name, password) {
var httpResponse = null;
// not implemented yet
}
I don't know know how to start ... should i start with a fetch-Get mehtod that i can find on react-native docs ? But how should i do it with bearer token (auth)
This is a common issue newcomers face when dealing with authentication.
I recommend you to give this a good read https://auth0.com/blog/adding-authentication-to-react-native-using-jwt/
You need a bit of advanced knowledge to implement it but you will learn with it, anyways.
You'll have to send your username and password to your backend with a POST request NOT a GET. So you can attach the name and password data to the body of the request. Also you'll want to use fetch to make the request.
You can do it like this:
function httpRequest(name, password) {
const user = {
name,
password,
};
fetch('https://mywebsite.com/endpoint/', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(user)
})
.then(res => res.json())
.then(data => {
console.log(data);
// data should contain a JWT token from your backend
// which you can save in localStorage or a cookie
})
.catch(err => console.log(err));
}
Also check out my answer on this question about a fetch helper function for easily generating headers. It includes a piece in there for easily adding a JWT token to your requests.
How to post a json array in react native