Next.js
Check out our Hellō Next.js Sample where you will be logging in with Hellō in less than a minute.
Follow the Next.js Quickstart directions to add Hellō to your application in minutes.
Setup
Following are the steps required to setup this package:
1. Package Installation
npm i @hellocoop/nextjspnpm add @hellocoop/nextjsyarn add @hellocoop/nextjsbun add @hellocoop/nextjsHellō Quickstart will perform steps 2 - 5 for you
App Router (Recommended)
npx @hellocoop/quickstart@latest --nextjs_app_routerPages Router
npx @hellocoop/quickstart@latest --nextjs_pages_router2. HELLO_COOKIE_SECRET
The environment variable HELLO_COOKIE_SECRET must be set to 64 char (32 byte) random hex string is required to encrypt cookies used by this package. This can be in .env.local for local development.
You can generate new values with:
node -e "console.log(crypto.randomBytes(32).toString('hex'))"Remember to set a unique HELLO_COOKIE_SECRET in each of your deployed environments.
See Environment Vars for additional values that can be set.
The .env.local file should not be checked into your repository, and should be in your .gitignore file.
3. client_id
If not using Hellō Quickstart, you will need to create an application at the Hellō Developer Console and get a client_id.
4. hello.config.js
The convention is to create a hello.config.js file in the root of your project for configuration. This file is imported into the hellocoop.js file and passed to the pageAuth() function for configuration. Below is a basic configuration file. See for additional configuration.
const config = {
client_id: 'your-client_id-here'
}
module.exports = configThis file should be checked into your repository.
See hello.config.js for additional configuration.
5. API Route
The default route is /api/hellocoop, which should not conflict with any existing route. There is one endpoint for all functionality. Query parameters (login,logout,auth) are used for routing within the package. With configuration at the project root in hello.config.js, the API route is handled by:
App Router (Recommended)
import config from '../../../hello.config'
import { appAuth } from '@hellocoop/nextjs'
export const { GET } = appAuth(config)Pages Router
import config from '../../hello.config'
import { pageAuth } from '@hellocoop/nextjs'
export default pageAuth(config)6. Image Component Config
To use the Image Component to display profile pictures add the Hellō and Gravatar domains to the images section of your next.config.js file:
const nextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'cdn.hello.coop'
},
{
protocol: 'https',
hostname: 'pictures.hello.coop'
},
{
protocol: 'https',
hostname: 'gravatar.com'
}
]
}
}7. Hellō Button Stylesheet
App Router (Recommended)
To provide the styling for Hellō buttons, add the below code to the <Head> section of your _document.tsx or _document.jsx file in the pages directory:
export default function RootLayout({ children }) {
return (
<html lang="en">
<head>
<link rel="stylesheet" href="https://cdn.hello.coop/css/hello-btn.css"/>
</head>
</html>
);
}Here is a summary of setup:
project-directory/
├─ .env.local 2. HELLO_COOKIE_SECRET
├─ hello.config.js 3. client_id
├─ next.config.js 6. Image Component Config
└─ app/
├─ layout.js 7. Hellō Button Stylesheet
└─ api/
└─ hellocoop
└─ route.js 5. API Route Pages Router
To provide the styling for Hellō buttons, add the below code to the <Head> section of your _document.tsx or _document.jsx file in the pages directory:
import { Html, Head, Main, NextScript } from 'next/document'
export default function Document() {
return (
<Html>
<Head>
<link rel="stylesheet" href="https://cdn.hello.coop/css/hello-btn.css"/>
</Head>
</Html>
)
}See Next.js Custom Document for details.
To ensure the button styles are available, client-side rendered buttons check if the stylesheet has been included in the document head, and if not the stylesheet is injected. Injecting into the head is not recommended and creates a button rendering glitch.
Here is a summary of setup:
project-directory/
├─ .env.local 2. HELLO_COOKIE_SECRET
├─ hello.config.js 3. client_id
├─ next.config.js 6. Image Component Config
└─ pages/
├─ _document.jsx 7. Hellō Button Stylesheet
└─ api/
└─ hellocoop.js 5. API Route Buttons
The following buttons are available:
import {
ContinueButton,
LoginButton,
UpdateProfileButton
} from '@hellocoop/nextjs'Note they are available from
@hellocoop/nextjs
See the SDK Reference | React for details.
Components
The following React components are available:
import {
HelloProvider,
LoggedIn,
LoggedOut,
} from '@hellocoop/nextjs'Note they are available from
@hellocoop/nextjs
See the SDK Reference | React for details.
Client APIs
useAuth()
import { useAuth } from '@hellocoop/nextjs'
const {
isLoading, // useSWR response, true if still loading call to
isLoggedIn,
auth: undefined | {
isLoggedIn, // always returned
iat, // returned if isLoggedIn == true
sub, // use as user identifier - returned if isLoggedIn == true
// additional claims - following are defaults
name,
email,
picture
}
} = useAuth()logOut()
import { logOut, getLogOutRoute } from '@hellocoop/nextjs'logOut() - function to logout user, loads getLogOutRoute
getLogOutRoute - provides route to logout
Server APIs
App Router (Recommended)
auth()
import { auth } from '@hellocoop/nextjs'
// returns same shape as useAuth().auth
const {
isLoggedIn, // always returned
iat, // returned if isLoggedIn == true
sub, // use as user identifier - returned if isLoggedIn == true
// additional properties set in auth cookie - following are defaults
name,
email,
picture
} = await auth()Pages Router
getAuth( req )
import { getAuth } from '@hellocoop/nextjs'
// returns same shape as useAuth().auth
const {
isLoggedIn, // always returned
iat, // returned if isLoggedIn == true
sub, // use as user identifier - returned if isLoggedIn == true
// additional properties set in auth cookie - following are defaults
name,
email,
picture
} = await getAuth( req )Used in page routes to get the auth object.
getServerSideProps()
<HelloProvider auth={auth}> </HelloProvider>
If you want to get the auth object from the auth cookie sever side, export getServerSideProps() and wrap your content in <HelloProvider auth={auth}>
import { HelloProvider, LoggedIn, LoggedOut, ContinueButton, getServerSideProps } from '@hellocoop/nextjs'
export default function MyPage({auth}) {
const { name } = auth
return(
<HelloProvider auth={auth}> {/* auth must be passed to HelloProvider */}
<LoggedIn>
Hellō {name}
</LoggedIn>
<LoggedOut>
<ContinueButton/>
</LoggedOut>
</HelloProvider>
)
}
// This is a convenience wrapper around `getAuth()`
export { getServerSideProps }loginSync()
loginSync( LoginSyncParams ): LoginSyncResponse
This is a callback you provide in the pageAuth() config that can do any logic you need when a user logs in. For example:
- Determine if the user has access
- Add roles or other properties to the
authcookie
See callback.login for details
import type { LoginSyncParams, LoginSyncResponse } from '@hellocoop/nextjs'
export default async loginSyncCallback ({
token, // ID Token in compact, unparsed format
payload, // parsed ID Token payload
target_uri, // target URI for redirect
req, // NextApiRequest
res // NextApiResponse
}: LoginSyncParams): Promise<LoginSyncResponse> => {
// use sub claim as user identifier
const { sub: id } = payload
const user = await readUserTable(id)
const role: Role = getUserRole(id)
// auth cookie will not be set
if (!isRoleAuthorized(role))
return {accessDenied: true}
const { email, name, picture } = payload
return {
// add role to auth object
updatedAuth: { email, name, picture, role }
}
}