PeterPan0
PeterPan0

Reputation: 72

How to call auth0 api after log in in Next.JS?

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

Answers (3)

Real World
Real World

Reputation: 1719

The way I've done this is as follows.

  1. Add an API call to your server by creating a file in 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
    });
  }
});
  1. Call the API method from your frontend
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

quickshiftin
quickshiftin

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

Deniz Karadağ
Deniz Karadağ

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

Related Questions