# NextAuth.js integration (/oauth-nextauth)

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](https://portal.eprospera.com/settings). To request a new client or re-issue a secret, contact [gmembreno@prospera.hn](mailto: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);
```

<Callout type="info">
  * 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.
</Callout>
