npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

next-auth-static-site

v0.11.0

Published

Authentication solution for static sites build with Next.js (static HTML export / next export) and a custom API authentication endpoint

Downloads

9

Readme

JWT authentication with a custom API

This package brings authentication to secure your private routes on your static sites build with the next export future from Next.js. Your custom API is used to handle the JWT authentication.

A JWT token is used for authentication and as a cookie refresh token.

  • Authentication token gets stored in localStorage to access private routes and for authenticated API requests
  • Refresh token is stored as a cookie

Installation

npm install --save next-auth-static-site

Configuration

You have to set a few environment variables to define your REST API endpoints. This can be done for example in .env.local or next.config.js.

Check the options reference for the configuration variables.

Usage

Implement the SessionProvider like this in your _app.js:

import { SessionProvider } from "next-auth-static-site";
import "./styles.css";

const App = ({ Component, pageProps: { ...pageProps } }) => {
  return (
    <SessionProvider>
      <Component {...pageProps} />
    </SessionProvider>
  );
};

export default App;

Now you can secure private/protected sites that requires authentication easily with useSession():

const { status, session, token } = useSession();
  • status: Can be "loading", "authenticated" or "unauthenticated".
  • session: Provides the session/user object returned from the login request.
    • If status is "loading", session will be undefined.
    • If status is "unauthenticated", session will be null.
    • If status is "authenticated", session will be object.
    • Provides the stored object returned from the login request (e.g. the username, email,...).
  • token: Returns the current JWT auth token.

The /dashboard page is a private page example.

API requirements

next-auth-static-site will send some data to your API and awaits a specific answer.

It's up to you to handle all the requests on your API!

So you will need a few routes on your API:

An minimal example API with the required routes is included in this monorepo and is located in apps/api/.

Login route

POST /auth/login

This request body object (Content-Type: application/json) will be sent when performing the login request to the API:

{
  "email": "[email protected]",
  "password": "123456"
}

Handle the login request and on your API server and return on success:

  • JWT auth token (with the header)
  • JWT refresh token (as a cookie)
  • Body with user data (for the session object, can be accessed by the client)

The JWT token must contain at least iat, exp and the user_id.

Bearer token

The API has to send the bearer token with the Authorization header:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Refresh token

Don't forget to set the JWT refresh token as a refresh_token cookie. Otherwise the client will be unauthenticated after the Bearer token expires because the token can't be refreshed.

Body

The Body content must be Content-Type: application/json and should contain some user data to display the values on the page. This could be changed, but the example uses email in a few components (dashboard.tsx page and authInfo.tsx component).

{
  "user_id": "userId",
  "email": "[email protected]"
}

Example response snippet from an express server:

res.setHeader("Access-Control-Expose-Headers", "Authorization");
res.setHeader("Authorization", "Bearer " + jwtToken);

res.cookie("refresh_token", jwtRefreshToken, {
  path: "/",
  maxAge: parseInt(process.env.JWT_REFRESH_TOKEN_LIFETIME) * 1000,
  httpOnly: true, // Client can't access this cookie with javascript
  sameSite: "Lax",
  secure: process.env.NODE_ENV === "production" ? true : false, // Forces to use https in production
});

res.status(200).json({ email: email, user_id: user_id });

Refresh route

GET /auth/refresh

Same as login, but you can skip the body object.

Return:

Logout Route

GET /auth/logout

  • Clear the refresh_token cookie
  • Any response error will delete the auth token stored in localStorage

Example

This monorepo provides a API and a web example:

Feel free to clone the monorepo and start the examples!

Install all dependencies:

npm ci

Start the development mode

npm run dev

Now you can access the web example on http://localhost:3000/ and the API will listen on port 5000.