I have a react native app authenticated with Auth0.
I have an API that uses react native.
When a user signs in, i take the accessToken that is given for that user, and I make request to the API with the accessToken set as the authorization header.
I do so like this:
const requestHeader = {
headers: {
Authorization: `Bearer ${accessToken}`,
}
}
axios.post(API_BASE + '/api/example/', requestHeader)
The accessToken is something short like this: aBQdd0kOvb1pNj-9XDj_C6bKWkMg9D_q
When I try to validate the request with the API, I get this error:
UnauthorizedError: jwt malformed
I know i'm getting this error because the access token isn't a JWT.
I'm validating in the API like this:
exports.checkJwt = jwt({
secret: jwksRsa.expressJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: 'https://dev-0p1doq9r.auth0.com/.well-known/jwks.json'
}),
audience: 'ddasdsfasdfasd',
issuer: 'safsdfasdfasdfafsdf',
algorithms: ['RS256']
});
I know that accessToken needs to be transformed into a JWT on the client, BUT HOW? I have not found any documentation for this; I have also not found what other properties need to be included in the JWT for validation.
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 am using react-native-app-auth library and passing in grant type: authorization code with PKCE and client credentials
const config = {
issuer: "***",
clientId: "***",
clientSecret: '***',
redirectUrl: '***:/oauthredirect',
additionalParameters: {},
scopes: ['***']
}
const newAuthState = await authorize(config);
Able to enter credentials and redirect to react native app but getting error of client_id and client_secret is missing or has an incorrect value
client_id, client_secret and scope are correct. And scope, redirectUrl are registered on server.
https://github.com/FormidableLabs/react-native-app-auth
clientAuthMethod - (string) ANDROID Client Authentication Method. Can be either basic (default) for Basic Authentication or post for HTTP POST body Authentication
passing clientAuthMethod as post worked for me.
I'm trying to migrate my app from auth0 to auth0-spa.js. I've been able to get it almost working, and the code is definitely simpler with this new lib so I'd like to keep using it but I also need a valid jwt token for the backend.
I use the following middleware on my node server (express-jwt)
export const jwtCheckMiddleware = jwt({
secret: '....',
getToken: function (req) {
if (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') {
return req.headers.authorization.split(' ')[1];
}
},
issuer: `https://${environment.auth.auth0Domain}/`,
algorithm: 'RS256'
});
Previous I would pass the idToken from auth0 and it worked. Now I get a token via await auth0.getTokenSilently(), however passing that to the middleware gives me "jwt malformed".
How can I get a valid JWT token from auth0-spa.js? Also, how would I ensure that the token I'm passing to the middlware is never expired?
Ok so I was able to get auth-spa.js to give me a jwt token by registering a custom API with Auth0 and then passing the API identifier as the audience.
More info here: https://auth0.com/docs/getting-started/set-up-api
const auth0 = createAuth0Client({
audience: environment.auth.audience, <-----API identifier of custom API in Auth0
client_id: environment.auth.clientId,
domain: environment.auth.clientDomain
});
After adding the audience getTokenSilently() gives me a JWT token which I pass to node. Then I had to add the audience in my jwt middleware:
export const jwtCheckMiddleware = jwt({
secret: jwks.expressJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: `https://${environment.auth.auth0Domain}/.well-known/jwks.json`
}),
audience: environment.auth.auth0ApiAudience, <!--- API identifier
issuer: `https://${environment.auth.auth0Domain}/`,
algorithms: ['RS256']
});
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
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.