Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/poupryc/authomatic

🔐 Now Serverless Functions + Auth0
https://github.com/poupryc/authomatic

auth auth0 nextjs now serverless zeit

Last synced: 2 months ago
JSON representation

🔐 Now Serverless Functions + Auth0

Awesome Lists containing this project

README

        

# @helloedit/authomatic

Auth0 SDK remix for signing in to your Next.js applications.

## Methods

### Login

```ts
import { NowRequest, NowResponse } from "@now/node";

import { auth } from "../lib/auth";

export default async function login(req: NowRequest, res: NowResponse) {
await auth
.handleLogin({ res, req })
.then(({ url }) => {
res.writeHead(302, { Location: url }).end();
})
.catch(error => {
res.status(500).end(error.message);
});
}
```

### Callback

```ts
import { NowRequest, NowResponse } from "@now/node";

import { auth } from "../lib/auth";

export default async function callback(req: NowRequest, res: NowResponse) {
await auth
.handleCallback({ req, res })
.then(({ redirectTo }) => {
res.writeHead(302, { Location: redirectTo }).end();
})
.catch(error => {
res.writeHead(500, error).end();
});
}
```

### Profile

```ts
import { NowRequest, NowResponse } from "@now/node";

import { auth } from "../lib/auth";

export default async function me(req: NowRequest, res: NowResponse) {
await auth
.handleProfile({ req, res })
.then(data => {
res.json({ ...data, authenticated: true }).end();
})
.catch(error => {
res.json({ authenticated: false }).end();
});
}
```

🎩

---

# @auth0/nextjs-auth0

Auth0 SDK for signing in to your Next.js applications.

> Note: This library is currently in an experimental state and support is best effort.

[![License](https://img.shields.io/:license-mit-blue.svg?style=flat)](https://opensource.org/licenses/MIT)

## Table of Contents

- [Installation](#installation)
- [Getting Started](#getting-started)
- [Contributing](#contributing)
- [Support + Feedback](#support--feedback)
- [Frequently Asked Questions](#frequently-asked-questions)
- [Vulnerability Reporting](#vulnerability-reporting)
- [What is Auth0](#what-is-auth0)
- [License](#license)

## Installation

Using [npm](https://npmjs.org):

```sh
npm install @auth0/nextjs-auth0
```

Using [yarn](https://yarnpkg.com):

```sh
yarn add @auth0/nextjs-auth0
```

> Note that this package supports the following versions of Node.js: `^10.13.0 || >=12.0.0`

## Getting Started

### Auth0 Configuration

Create a **Regular Web Application** in the [Auth0 Dashboard](https://manage.auth0.com/). If you're using an existing application you'll want to verify that the following settings are configured as follows:

- **Json Web Token Signature Algorithm**: `RS256`
- **OIDC Conformant**: `True`

Go ahead and configure the URLs for your application:

- **Allowed Callback URLs**: http://localhost:3000/api/callback
- **Allowed Logout URLs**: http://localhost:3000/

Take note of the **Client ID**, **Client Secret** and **Domain** of your application because you'll need it in the next step.

### Runtime Configuration

And then create an instance of the Auth0 plugin (eg: under `/utils/auth0.js`):

```js
import { initAuth0 } from "@auth0/nextjs-auth0";
import config from "./config";

export default initAuth0({
domain: "",
clientId: "",
clientSecret: "",
scope: "openid profile",
redirectUri: "http://localhost:3000/api/callback",
postLogoutRedirectUri: "http://localhost:3000/",
session: {
// The secret used to encrypt the cookie.
cookieSecret: "",
// The cookie lifetime (expiration) in seconds. Set to 8 hours by default.
cookieLifetime: 60 * 60 * 8,
// (Optional) The cookie domain this should run on. Leave it blank to restrict it to your domain.
cookieDomain: "your-domain.com",
// (Optional) SameSite configuration for the session cookie. Defaults to 'lax', but can be changed to 'strict' or 'none'. Set it to false if you want to disable the SameSite setting.
cookieSameSite: "lax",
// (Optional) Store the id_token in the session. Defaults to false.
storeIdToken: false,
// (Optional) Store the access_token in the session. Defaults to false.
storeAccessToken: false,
// (Optional) Store the refresh_token in the session. Defaults to false.
storeRefreshToken: false
},
oidcClient: {
// (Optional) Configure the timeout in milliseconds for HTTP requests to Auth0.
httpTimeout: 2500,
// (Optional) Configure the clock tolerance in milliseconds, if the time on your server is running behind.
clockTolerance: 10000
}
});
```

> Note that when you have configured a Custom Domain in your Auth0 account you should be using that domain (eg: `login.acme.com` instead of `acme.auth0.com`) as the AUTH0_DOMAIN. [You might also need to make changes to your Login page](https://auth0.com/docs/custom-domains/additional-configuration).

### Login

In order to sign in the user we'll first need a link to the login route.

```html
Login
```

Create an [API Route](https://nextjs.org/docs#api-routes) for this route (`/pages/api/login.js`) which uses the client:

```js
import auth0 from "../../utils/auth0";

export default async function login(req, res) {
try {
await auth0.handleLogin(req, res);
} catch (error) {
console.error(error);
res.status(error.status || 400).end(error.message);
}
}
```

This will redirect the user to Auth0. After the transaction is completed Auth0 will redirect the user back to your application. This is why the callback route (`/pages/api/callback.js`) needs to be created which will create a session cookie:

```js
import auth0 from "../../utils/auth0";

export default async function callback(req, res) {
try {
await auth0.handleCallback(req, res, { redirectTo: "/" });
} catch (error) {
console.error(error);
res.status(error.status || 400).end(error.message);
}
}
```

You can optionally send extra parameters to Auth0 to influence the transaction, for example:

- Showing the login page
- Filling in the user's email address
- Exposing information to the custom login page (eg: to show the signup tab)
- Using a custom `state`

```js
import auth0 from "../../utils/auth0";

export default async function login(req, res) {
try {
await auth0.handleLogin(req, res, {
authParams: {
login_hint: "[email protected]",
ui_locales: "nl",
scope: "some other scope",
state: "a custom state",
foo: "bar"
}
});
} catch (error) {
console.error(error);
res.status(error.status || 400).end(error.message);
}
}
```

### Logout

For signing the user out we'll also need a logout link:

```html
Logout
```

Create an [API Route](https://nextjs.org/docs#api-routes) for this route (`/pages/api/logout.js`) which uses the client:

```js
import auth0 from "../../utils/auth0";

export default async function logout(req, res) {
try {
await auth0.handleLogout(req, res);
} catch (error) {
console.error(error);
res.status(error.status || 400).end(error.message);
}
}
```

### User Profile

If you want to expose a route which returns the user profile to the client you can create an additional route (eg: `/pages/api/me.js`):

```js
import auth0 from "../../utils/auth0";

export default async function me(req, res) {
try {
await auth0.handleProfile(req, res);
} catch (error) {
console.error(error);
res.status(error.status || 500).end(error.message);
}
}
```

You can then load the user after the page has been rendered on the server:

```js
async componentDidMount() {
const res = await fetch('/api/me');
if (res.ok) {
this.setState({
session: await res.json()
})
}
}
```

If you need to access the user's session from within an API route or a Server-rendered page you can use `getSession`. Note that this object will also contain the user's `access_token` and `id_token`.

```js
Profile.getInitialProps = async ({ req, res }) => {
if (typeof window === "undefined") {
const { user } = await auth0.getSession(req);
if (!user) {
res.writeHead(302, {
Location: "/api/login"
});
res.end();
return;
}

return { user };
}
};
```

### Calling an API

It's a common pattern to use Next.js API Routes and proxy them to external APIs. When doing so these APIs typically require an `access_token` to be provided. These APIs can then be configured in Auth0.

In order to get an access_token for an API you'll need to configure the `audience` on the Auth0 plugin and configure it to store the `access_token` in the cookie:

```js
import { initAuth0 } from '@auth0/nextjs-auth0';

export default initAuth0({
domain: ''
clientId: '',
clientSecret: '',
audience: 'https://api.mycompany.com/',
scope: 'openid profile',
redirectUri: 'http://localhost:3000/api/callback',
postLogoutRedirectUri: 'http://localhost:3000/',
session: {
cookieSecret: '',
cookieLifetime: 60 * 60 * 8,
cookieDomain: 'https://mycompany.com',
storeAccessToken: true
}
});
```

Then you could create a route (eg: `/pages/api/customers.js`) which can call an external API (eg: `https://api.mycompany.com`) using the user's `access_token`.

```js
import auth0 from "../../utils/auth0";

export default async function getCustomers(req, res) {
try {
const { accessToken } = await auth0.getSession(req);

const apiClient = new MyApiClient(accessToken);
return apiClient.getCustomers();
} catch (error) {
console.error(error);
res.status(error.status || 500).end(error.message);
}
}
```

### Requiring Authentication

If you have API routes for which you want to require the user to be authenticated you can use the `requireAuthentication` handler:

```js
import auth0 from "../../lib/auth0";

export default auth0.requireAuthentication(async function billingInfo(
req,
res
) {
const { user } = await auth0.getSession(req);
res.json({
email: user.email,
country: "United States",
paymentMethod: "Paypal"
});
});
```

If the user is authenticated then your API route will simply execute, but if the user is not authenticated an error (401) will be returned:

```json
{
"error": "not_authenticated",
"description": "The user does not have an active session or is not authenticated"
}
```

## Documentation

### Cookies

All cookies will be set as `HttpOnly, SameSite=Lax` cookies and will be forced to HTTPS (`Secure`) if the application is running with `NODE_ENV=production` and not running on localhost.

The `HttpOnly` setting will make sure that client-side javascript is unabled to access the cookie to reduce the attack surface of XSS attacks while `SameSite=Lax` will help mitigate CSRF attacks. Read more about SameSite [here](https://auth0.com/blog/browser-behavior-changes-what-developers-need-to-know/).

## Troubleshooting

### Error `id_token issued in the future, now 1570650460, iat 1570650461`

Increase the clock tolerance for id_token validation:

```js
import { initAuth0 } from '@auth0/nextjs-auth0';

export default initAuth0({
...
session: {
...
},
oidcClient: {
// Eg: increase the tolerance to 10 seconds.
clockTolerance: 10000
}
});
```

## Contributing

Run NPM install first to install the dependencies of this project:

```bash
npm install
```

In order to build a release you can run the following commands and the output will be stored in the `dist` folder:

```bash
npm run clean
npm run lint
npm run build
```

Additionally you can also run tests:

```bash
npm run test
npm run test:watch
```

## Support + Feedback

This SDK is in Early Access and support is best effort. Open an issue in this repository to get help or provide feedback.

## Vulnerability Reporting

Please do not report security vulnerabilities on the public GitHub issue tracker. The [Responsible Disclosure Program](https://auth0.com/whitehat) details the procedure for disclosing security issues.

## What is Auth0?

Auth0 helps you to easily:

- implement authentication with multiple identity providers, including social (e.g., Google, Facebook, Microsoft, LinkedIn, GitHub, Twitter, etc), or enterprise (e.g., Windows Azure AD, Google Apps, Active Directory, ADFS, SAML, etc.)
- log in users with username/password databases, passwordless, or multi-factor authentication
- link multiple user accounts together
- generate signed JSON Web Tokens to authorize your API calls and flow the user identity securely
- access demographics and analytics detailing how, when, and where users are logging in
- enrich user profiles from other data sources using customizable JavaScript rules

[Why Auth0?](https://auth0.com/why-auth0)

## License

This project is licensed under the MIT license. See the [LICENSE](https://github.com/auth0/nextjs-auth0/blob/master/LICENSE) file for more info.