@newskit-render/auth
A package for the authentication of protected pages in your Next.js application. We are currently supporting Okta as a provider but there are also other options for authentication. You can see example usage with a preview article here: @newskit-render/core
Getting started
Before starting, either locally or on deployed enviroments, you will need the following in your .env.local
file / CircleCi Config:
- OKTA_CLIENT_ID - client id for OKTA app
- OKTA_CLIENT_SECRET - client secret for OKTA app
-
OKTA_DOMAIN - domain of OKTA app i.e
https://newscorp.okta.com
-
NEXTAUTH_URL - domain of your app i.e on local
http://localhost:3000
or on some environmenthttps://newskit-render.prod.ceng.newsuk.tech
-
NEXTAUTH_SECRET - A random string is used to hash tokens, sign/encrypt cookies and generate cryptographic keys. You can quickly create a good value on the command line via this openssl command.
openssl rand -base64 32
To get this information you need to raise a ticket with ServiceDesk for the attention of IAM and Collaboration team. You need to request they set up OKTA apps for each of your environments.
IMPORTANT For each each environment the OKTA app's sign-in and sign-out urls need to be modified:
local
sign-in - http://localhost:3000/api/auth/callback/okta
sign-out - http://localhost:300
Other environment
sign-in - {your domain / NEXTAUTH_URL}/api/auth/callback/okta
sign-out - {your domain / NEXTAUTH_URL}
The IAM and Collaboration team team need to set all this up. They also need to add you and anyone else you need as users on the apps. They will then send you the credentials OKTA_CLIENT_ID, OKTA_CLIENT_SECRET, OKTA_DOMAIN
. With this you can test locally (.env.local
) and once added to your CircleCi config on environments (Render is set up to pass the credentials so you just need to add them and then rebuild).
Any issues contact the newskit-render team for help.
Add it as a dependency:
npm install @newskit-render/auth
or
yarn add @newskit-render/auth
Add the provider
In your main _app.jsx/tsx
:
import { SessionProvider } from '@newskit-render/auth'
Wrap all the content and pass the pageProps as a prop to the provider:
<SessionProvider pageProps={pageProps}>{Content goes here...}</SessionProvider>
Create authentication route
Under your /pages
folder create an /api
folder and an /auth
folder inside the latter. Inside the /auth
folder create a file called [...nextauth].ts
.
The path should be as follows: /pages/api/auth/[...nextauth].ts
Create the route and pass your Okta credentials:
import createAuthRoute from '@newskit-render/auth/providers'
import { NextApiRequest, NextApiResponse } from 'next'
const { OKTA_CLIENT_ID, OKTA_CLIENT_SECRET, OKTA_DOMAIN } = process.env
export default (req: NextApiRequest, res: NextApiResponse) =>
createAuthRoute(req, res, {
clientId: OKTA_CLIENT_ID,
clientSecret: OKTA_CLIENT_SECRET,
issuer: OKTA_DOMAIN,
})
Wrap your protected page with PageWithAuth component
Import the following in your page component:
import { PageWithAuth, getSession, signIn, signOut } from '@newskit-render/auth'
Wrap all of your page component content with PageWithAuth. It will accept onDenied
and isLoading
props. You can use these to show content for the user when he is not authenticated or when the content is still loading.
<PageWithAuth onDenied={accessDeniedPage} isLoading={showOnLoading}></PageWithAuth>
You can call the signIn and signOut functions to initiate or terminate the authentication for the user. When using singIn set the provider so you don't have an extra login page signIn('okta').
The last step is to get the session using the getSession hook.
Add the hook under the getServerSideProps
function and then include the result as a prop inside the props that will be returned.
export async function getServerSideProps(context) {
const session = await getSession(context)
return {
props: {
...some props
session,
},
}
}
You can add some additional logic here if you want to prevent unnecessary requests or any other logic execution if the user is not authenticated:
export async function getServerSideProps(context) {
const session = await getSession(context)
if (!session) {
return {
props: {},
}
}
const { data } = await apolloClient.query({
query: GET_DATA,
})
return {
props: {
data: data,
session,
},
}
}
signOut should really be dealt with by your CMS but for testing purposes you will want a sign out button. We have added a CookieView component to the the package that only shows children if you set a cookie with the following:
document.cookie = `nextAuthShowLogOut=true; Path=/`; location.reload();
You can change the cookie name if you want.
For the full page example see preview page
Preview Pages
To see Preview pages uses the following pattern:
{site-domain}/preview/{article-id}/version/{version-id}