Skip to content

NextAuth.js integration

Use Auth.js / NextAuth with e-Próspera as a custom OIDC provider.

If you already have an OAuth client, the client ID and redirect URIs are visible in Settings > Developer. To request a new client or re-issue a secret, contact gmembreno@prospera.hn.

javascript
import NextAuth from "next-auth";

async function refreshEProsperaToken(token) {
  const response = await fetch("https://portal.eprospera.com/api/oauth/token", {
    method: "POST",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",
      Authorization:
        "Basic " +
        Buffer.from(
          `${process.env.EPROSPERA_CLIENT_ID}:${process.env.EPROSPERA_CLIENT_SECRET}`,
        ).toString("base64"),
    },
    body: new URLSearchParams({
      grant_type: "refresh_token",
      refresh_token: token.refreshToken,
    }),
  });

  const refreshed = await response.json();

  if (!response.ok) throw refreshed;

  return {
    ...token,
    accessToken: refreshed.access_token,
    accessTokenExpires: Date.now() + refreshed.expires_in * 1000,
    refreshToken: refreshed.refresh_token ?? token.refreshToken,
  };
}

export const authOptions = {
  providers: [
    {
      id: "eprospera",
      name: "eProspera",
      type: "oauth",
      wellKnown:
        "https://portal.eprospera.com/.well-known/openid-configuration",
      authorization: {
        params: {
          scope: "openid email profile offline_access",
        },
      },
      idToken: true,
      checks: ["pkce", "nonce", "state"],
      profile(profile) {
        return {
          id: profile.sub,
          name: profile.name,
          email: profile.email,
          image: profile.picture,
        };
      },
      options: {
        clientId: process.env.EPROSPERA_CLIENT_ID,
        clientSecret: process.env.EPROSPERA_CLIENT_SECRET,
      },
    },
  ],
  callbacks: {
    async jwt({ token, account }) {
      if (account) {
        return {
          ...token,
          accessToken: account.access_token,
          accessTokenExpires: Date.now() + account.expires_in * 1000,
          refreshToken: account.refresh_token,
        };
      }

      if (Date.now() < token.accessTokenExpires) {
        return token;
      }

      return refreshEProsperaToken(token);
    },
  },
};

export default NextAuth(authOptions);

TIP

  • Request offline_access if your server needs refresh tokens.
  • e-Próspera rotates refresh tokens — always persist the newest one from the token response.
  • Only request eprospera:* scopes if your app calls the /api/v1/me/* resource endpoints.