supertest test with jwt header token - express

I'm have some issue in my test with superagent and express.js.
it('should 200 with valid login', (done) => {
console.log(createdUser[`${validUser.email}`]['token']);
// JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1ODAwZDllZmNiM2VkMzBhOGZmMDUyOGUiLCJmaXJzdE5hbWUiOiJoYW5zIiwibGFzdE5hbWUiOiJvdHRvIiwiZW1haWwiOiJvdHRvQGV4YW1wbGUuZGUiLCJyb2xlIjoiVXNlciIsImlhdCI6MTQ3NjQ1MDc5OSwiZXhwIjoxNDc2NDYwODc5fQ.OlO_dVMCV6bm7XSyzKLFTgb-efOeyU1TniHEcIY7AHU
request(app)
.get('/api/protected')
.set('Authorization', createdUser[`${validUser.email}`]['token'])
.expect(200)
.end((err, res)=> {
if (err) done(err);
console.log(res.header);
// assert(true, 'asdfasdf');
// done();
});
});
I can't access to the protected path over superagent.
When I'm accessing the path over Postman it is working and I can access the protected path with the suited jwt.
What do have to change in the code?
I want to test different paths.
thanks

Bearer keyword is missing while setting the token
.set('Authorization', `Bearer ${createdUser[`${validUser.email}`]['token']}`)

There is some information missing but here are some possible answers:
You do show how you created your app. If you are using a middleware like express-jwt it needs to be configured before running your test. (app.use(expressJWt...)
Typically, the jwt is sent through the Authorization header using the Bearer schema. ( i.e. Authorization: Bearer eyJhbGciOiJI... )

You can use superagent’s auth function with { type: ‘bearer’ } option:
request.auth(jwt, { type: 'bearer' })

Related

Google Identity Services : How to refresh access_token for Google API after one hour?

I have implemented the new Google Identity Services to get an access_token to call the Youtube API.
I try to use this on an Angular app.
this.tokenClient = google.accounts.oauth2.initTokenClient({
client_id: googleApiClientId,
scope: 'https://www.googleapis.com/auth/youtube.readonly',
callback: (tokenResponse) => {
this.accessToken = tokenResponse.access_token;
},
});
When I call this.tokenClient.requestAccessToken(), I can get an access token and use the Youtube API, that works.
But after one hour, this token expires. I have this error : "Request had invalid authentication credentials."
How can I get the newly refreshed access_token transparently for the user ?
There are two authorization flows for the Google Identity Services (GIS) library:
The implicit flow, which is client-side only and uses .requestAccessToken()
The authorization code flow, which requires a backend (server-side) as well and uses .requestCode()
With the implicit flow (which is what you are using), there are no refresh tokens. It is up to the client to detect tokens aging out and to re-run the token request flow. Here is some sample code from google's examples for how to handle this:
// initialize the client
tokenClient = google.accounts.oauth2.initTokenClient({
client_id: 'YOUR_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
prompt: 'consent',
callback: '', // defined at request time in await/promise scope.
});
// handler for when token expires
async function getToken(err) {
if (err.result.error.code == 401 || (err.result.error.code == 403) &&
(err.result.error.status == "PERMISSION_DENIED")) {
// The access token is missing, invalid, or expired, prompt for user consent to obtain one.
await new Promise((resolve, reject) => {
try {
// Settle this promise in the response callback for requestAccessToken()
tokenClient.callback = (resp) => {
if (resp.error !== undefined) {
reject(resp);
}
// GIS has automatically updated gapi.client with the newly issued access token.
console.log('gapi.client access token: ' + JSON.stringify(gapi.client.getToken()));
resolve(resp);
};
tokenClient.requestAccessToken();
} catch (err) {
console.log(err)
}
});
} else {
// Errors unrelated to authorization: server errors, exceeding quota, bad requests, and so on.
throw new Error(err);
}
}
// make the request
function showEvents() {
// Try to fetch a list of Calendar events. If a valid access token is needed,
// prompt to obtain one and then retry the original request.
gapi.client.calendar.events.list({ 'calendarId': 'primary' })
.then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
.catch(err => getToken(err)) // for authorization errors obtain an access token
.then(retry => gapi.client.calendar.events.list({ 'calendarId': 'primary' }))
.then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
.catch(err => console.log(err)); // cancelled by user, timeout, etc.
}
Unfortunately GIS doesn't handle any of the token refreshing for you the way that GAPI did, so you will probably want to wrap your access in some common retry logic.
The important bits are that the status code will be a 401 or 403 and the status will be PERMISSION_DENIED.
You can see the details of this example here, toggle to the async/await tab to see the full code.
To refresh the access token in a transparent way for the end-user you have to use the Refresh Token, This token will also come in the response to your call.
With this token, you can do a POST call to the URL: https://www.googleapis.com/oauth2/v4/token with the following request body
client_id: <YOUR_CLIENT_ID>
client_secret: <YOUR_CLIENT_SECRET>
refresh_token: <REFRESH_TOKEN_FOR_THE_USER>
grant_type: refresh_token
refresh token never expires so you can use it any number of times. The response will be a JSON like this:
{
"access_token": "your refreshed access token",
"expires_in": 3599,
"scope": "Set of scope which you have given",
"token_type": "Bearer"
}
#victor-navarro's answer is correct, but I think the URL is wrong.
I made a POST call to https://oauth2.googleapis.com/token with a body like this and it worked for me:
client_id: <YOUR_CLIENT_ID>
client_secret: <YOUR_CLIENT_SECRET>
refresh_token: <REFRESH_TOKEN_FOR_THE_USER>
grant_type: refresh_token

Auth0 refresh token in React Native fails with 401

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
})

How to store jwt token in localStorage and send it back to the server with header in express?

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

Implementation JWT based authentication without Oauth and custom token scheme

I am working on a Web API where I implemented JWT based authentication. I am not using neither PasswordJS middlware nor Oauth protocol. Its basically JWT npm which I use to sign and verify tokens.
The whole concept of token are pretty clear, but I very much confused with the term 'token scheme' and cannot understand what it is used for.
What I would like to understand is: do I need to use some sort or custom 'JWT' scheme and validate it when token is send back to server for further requests, or this concept is used only by Oauth, and what I need is only send the plain token?
var accessToken = jwt.sign({
userID: user.id,
isAdmin: user.isAdmin
}, config.userSecret, {
expiresIn: 600
});
res.json({
success: true,
user: {
id: user._id,
name: user.name,
username: user.username,
accessToken: 'JWT ' + accessToken,
}
});
jwt.verify(accessToken, secret, function(err, token){...}); //throws error when token is passed with the custom scheme
Exactly what scheme you are using isn't that important in this case, because you are parsing the content of the Authorization header manually anyway.
Basically, the token is sent from the client to the server on an HTTP header called Authorization. In front of the token you put the name of the scheme. So the Authorization header might look something like this:
Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
(The list of allowed names is here. For JWT it's usually Bearer. You are technically not following the OAuth 2.0 bearer scheme according to RFC6749, but it's usually called Bearer anyway.)
You have to manually take the token (ey...) and verify it with jwt.verify() to get its payload.
const headerExists = req.headers.authorization
if (headerExists) {
let token = req.headers.authorization.split(' ')[1];
jwt.verify(token, auth.secretjwtkey, function (err, decoded) {
if (err) {
res.status(HttpStatus.UNAUTHORIZED).json('Unauthorized');
} else if (decoded.role === 'admin') {
next();
} else {
res.status(HttpStatus.UNAUTHORIZED).json('Unauthorized');
}
})
} else {
res.status(HttpStatus.FORBIDDEN).json('No token');
}
You can see from the example middleware above that I don't care about the Bearer string on the Authorization header, only the token itself. You could, of course, check that it actually was Bearer and not something else though.
So the moral of the story is that:
You send the token from client to the server on the Authorization header. You have to set up the front-end so that happens.
You prepend Bearer in front of the token (or one of the other in the allowed list, but bearer is recommended).
You decode the token by reading the second part of the string that is on the Authorization header and then feed it to jwt.verify().
See here for more details.

react-native - Bearer Token auth - httpReqest

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