-
Notifications
You must be signed in to change notification settings - Fork 397
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to get accesstoken client-side #67
Comments
I wish I had a better solution, but could not find one and ended up storing the idToken in a cookie. |
I would suggest you to avoid using the idToken on the client side. If you need to authentify http/ws calls I would suggest you to proxify your calls putting the bearer token on server side. For example you can have a |
That's a good suggestion. I hope I can put some time in fixing my public repo soon. Thanks! |
@vgrafe if you struggle on this feel free to ask :) I have some code samples |
@matthieuh I'd love to see that! I can't spend lots of time on this repo these days, and since it has a few stars I'd love some help providing best practices rather than something that is not recommended. Feel free to post on my repo's issue or here. |
Hello @vgrafe I have a import proxy from 'http-proxy-middleware';
import express from 'express';
import auth0 from '../../utils/auth0';
const app = express();
app.use('*', async (req, _, next) => {
const session = = await auth0.getSession(req);
return proxy({
target: process.env.GRAPHQL_URL,
changeOrigin: true,
proxyTimeout: 5000,
secure: false,
headers: {
Connection: 'keep-alive'
},
pathRewrite: {
'^/api/graphql': ''
},
onError: (err, req, res) => {
console.log('err', err, res.data);
res.writeHead(500, {
'Content-Type': 'text/plain'
});
res.end(
'Something went wrong. And we are reporting a custom error message.'
);
},
onProxyReq: async (proxyReq, req, res) => {
if (session) {
proxyReq.setHeader('Authorization', `Bearer ${session.idToken}`);
}
if (req.body) {
let bodyData = JSON.stringify(req.body);
// incase if content-type is application/x-www-form-urlencoded -> we need to change to application/json
proxyReq.setHeader('Content-Type', 'application/json');
proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
// stream the content
proxyReq.write(bodyData);
}
}
})(req, _, next);
});
export default app; Then you just need to call Something to note is that this proxy will not work with subscription which are using websocket. So to make it works I added an other file import proxy from 'http-proxy-middleware';
import express from 'express';
import auth0 from '../../utils/auth0';
const app = express();
app.use('*', async (req, _, next) => {
const session = await auth0.getSession(req);
const wsProxy = proxy({
target: process.env.GRAPHQL_URL,
changeOrigin: true,
logLevel: 'debug',
ws: true,
timeout: 30000,
proxyTimeout: 30000,
pathRewrite: {
'^/api/graphql-ws': ''
},
onProxyReqWs: proxyReq => {
if (session) {
proxyReq.setHeader('Authorization', `Bearer ${session.idToken}`);
}
}
});
app.on('upgrade', wsProxy.upgrade);
return wsProxy(req, _, next);
});
export default app;` |
Thanks for the above code @matthieuh. Any chance you can provide the client side code? |
Wow! Thank you. I'll update my repo sometime this week. |
@matthieuh does this work with the Next.js serverless target? |
Hi, https://gist.github.com/jagyas/a120fa57349e2f7f854f97d18c4dfd87 I have created above code mainly for hiding Graphql endpoint. If we will fetch session in same code and then pass it to graphql endpoint, I think it will also help to hide idToken. Let me know your views @vgrafe @matthieuh @Pytal |
Hi everyone, with the new v1.0.0-beta.0 release we have included a way to use an access token from the frontend. However, keep in mind that it is less secure than proxying the requests through API routes, as the access token could be stolen via XSS. |
Sorry, I couldn't access the token on the client side, could you provide an example? ty |
Hi @mathiasfc - we've removed the advice on the recommendation of our security experts, but you can still find it here #245 Also checkout #201 (comment) |
Hey, I built a middleware for our graphql requests that can pickup the token and send it through (found the code when googling but I forget where): import request from 'request';
import util from 'util';
import { getAccessToken } from '@auth0/nextjs-auth0';
const graphql = async (req, res) => {
try {
const { accessToken } = await getAccessToken(req, res, {
audience: process.env.AUTH0_AUDIENCE,
});
const headers = {
// Attach token to header
Authorization: accessToken ? `Bearer ${accessToken}` : '',
// Set content type to JSON
'Content-Type': 'application/json',
};
console.log(headers);
const asyncReqPost = util.promisify(request.post);
// Send request
const graphQLApiResponse = await asyncReqPost({
url: process.env.GRAPHQL_URL,
headers,
json: req.body,
timeout: 5000, // give queries more time to run
gzip: true,
});
// Set response header
res.setHeader('Content-Type', 'application/json');
// Send response
res.end(JSON.stringify(graphQLApiResponse.body));
} catch (error) {
console.error(error);
res.status(error.status || 500).end(error.message);
}
};
export default graphql; But we do a lot of requests, and we get a Too Many Requests exception at /userinfo |
You don't need a complicated config. Just follow this answer: vercel/next.js#11036 (reply in thread) Also export this from your API handler: export const config = {
api: {
bodyParser: false,
externalResolver: true,
},
}; |
I'm adding to this same question - I'm also trying to create a thin proxy, using
I also tried mocking the |
thanks for this example, could you show how you are calling your websocket proxy route my websocket looks like this
|
Did you ever find a way to do this proxy with the websocket url? We are facing the same issue now and due to the library only accepting websocket URLs we cannot proxy any of the traffic through nextjs api/rewrites/middleware. |
So I am using graphql and instantiating apollo-client in a hoc wrapped around
app.js
. Here I am passing theaccessToken
I get fromconst session = await auth0.getSession(ctx.ctx.req)
as Header to my client so it gets send to the server and the request can be verified. Now I get the error:Error in error page
getInitialProps: Error: "The getSession method can only be used from the server side"
So I am wondering how I should be able to get the accessToken on the client side. I guess I could store the accessToken on a cookie, but that wouldnt feel rightThe text was updated successfully, but these errors were encountered: