Reputation: 72
I have a Next.JS app where I implemented auth0 login using the code from the documentation:
// pages/api/auth/[...auth0].js
import { handleAuth } from '@auth0/nextjs-auth0';
export default handleAuth();
// pages/index.js
import { useUser } from '@auth0/nextjs-auth0';
export default function Profile() {
const { user, error, isLoading } = useUser();
if (isLoading) return <div>Loading...</div>;
if (error) return <div>{error.message}</div>;
return (
user && (
<div>
<img src={user.picture} alt={user.name} />
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
)
);
}
The code is working and I am able to login. When I understand that correctly, my index.js is now protected.
Then I added an API application in auth0.
Now I created a little server in node.js:
const express = require("express");
const cors = require("cors");
const morgan = require("morgan");
const helmet = require("helmet");
const jwt = require("express-jwt");
const jwks = require("jwks-rsa");
const authConfig = require("./auth_config.json");
const app = express();
const port = process.env.API_PORT || 3001;
const appPort = process.env.SERVER_PORT || 3000;
const appOrigin = authConfig.appOrigin || `http://localhost:${appPort}`;
if (!authConfig.domain || !authConfig.audience) {
throw new Error(
"Please make sure that auth__config.json is in place and poplated"
);
}
const jwtCheck = jwt({
secret: jwks.expressJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: `https://${authConfig.domain}/.well-known/jwks.json`,
}),
audience: authConfig.audience,
issuer: `http://${authConfig.domain}`,
algorithms: ["RS256"],
});
app.use(morgan("dev"));
app.use(helmet());
app.use(cors({ origin: appOrigin }));
app.use(jwtCheck);
app.get("/api/protected", (reg, res) => {
res.send({
msg: "You called the protected endpoint!",
});
});
app.listen(port, () => console.log(`API server listening on port ${port}`));
My question now is: How can I call the api/protected
path from the index.js?
Upvotes: 0
Views: 1618
Reputation: 1719
The way I've done this is as follows.
pages/api/myendpoint.ts
import { getAccessToken, withApiAuthRequired } from '@auth0/nextjs-auth0';
import axios, { AxiosRequestConfig } from 'axios';
export default withApiAuthRequired(async function myendpoint(req, res) {
try {
const { accessToken } = await getAccessToken(req, res, {
scopes: []
});
const baseURL = 'http://localhost:3000';
const config: AxiosRequestConfig = {
headers: { Authorization: `Bearer ${accessToken}` }
};
const response = await axios.post(baseURL + '/api/protected', {
'someThing': req.query.someThing,
'comment': 'string'
}, config
);
res.status(response.status || 200).json(response.data);
} catch (error: any) {
console.error(error);
res.status(error.status || 500).json({
code: error.code,
error: error.message
});
}
});
export default function Article(params: { blog: any, id: string }) {
const handleSubmit = async (event: any) => {
event.preventDefault();
// Get data from the form.
const postData = {
comment: event.target.comment.value,
page: event.target.page.value
};
// Send the data to the server in JSON format.
const JSONdata = JSON.stringify(postData);
// API endpoint where we send form data.
const endpoint = '/api/myendpoint';
// Form the request for sending data to the server.
const options = {
// The method is POST because we are sending data.
method: 'POST',
// Tell the server we're sending JSON.
headers: {
'Content-Type': 'application/json'
},
// Body of the request is the JSON data we created above.
body: JSONdata
};
// Send the form data to our forms API on Vercel and get a response.
const response = await fetch(endpoint, options);
// Get the response data from server as JSON.
// If server returns the name submitted, that means the form works.
const result = await response.json();
// do something with result
};
return (<form onSubmit={handleSubmit}>
<input type='hidden' name='key' value={someValue} />
<textarea name='someThing' className='px-3 py-2 border text-sm h-16 pt-2 pr-3 pb-2 pl-3 w-full text-gray-700 dark:text-white border-gray-300 rounded-md
placeholder-gray-600 dark:placeholder-gray-200 focus:shadow-outline'
placeholder='Enter some text' required></textarea>
<button type='submit'
className='inline-flex w-full justify-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-base font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 sm:text-sm'>Submit
</button>
</form>);
Seems a bit redundant to call an internal API method to make an external API call but I could only find an example that followed this design. Happy to be corrected if theres a better way!
Upvotes: 0
Reputation: 69681
Take a look at the example useFetchUser
hook.
Here an HTTP call to /api/me
endpoint is only sent if user is logged in.
Inside the example homepage, the user is loaded by calling the hook:
const { user, loading } = useFetchUser()
You would do something similar, however it would be slightly different since you won't need to conditionally redirect in the body of useProtectedInfo
or whatever you decide to call your hook.
The structure would be broadly similar to the example.
Upvotes: 0
Reputation: 761
If I understand correctly, you are asking how to make an api call inside your component? If yes, below is an example.
import axios from "axios";
const yourfunctionName = async (email, password) => {
try {
const response = await axios.get(`http://localhost:3000/api/protected`, {
data
});
return response.data
} catch (error) {
console.log(error.message);
}
};
Upvotes: 1