OpenSaasAU / keystone-nextjs-auth

A package that add social auth to Keystone-6 (https://keystonejs.com/) by using next-authjs (https://next-auth.js.org/)
MIT License
75 stars 11 forks source link

Azure AD not logging user in #267

Closed earthwytch closed 1 year ago

earthwytch commented 1 year ago

I am about 80% through getting an Azure Active Directory user to log in after working through #238 ๐Ÿ™‚

At this point I am redirected back to http://localhost:3000/admin/api/auth/signin with the sign in button visible. I can't go anywhere without being redirected back to this page again. I can't see any errors or 404s in the browser inspector.

I am still receiving the following message in the console, though not sure if this is what is causing the issue:

[next-auth][error][CLIENT_FETCH_ERROR] 
https://next-auth.js.org/errors#client_fetch_error invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0 {
  error: {
    message: 'invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0',
    stack: 'FetchError: invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0\n' +
      '    at /home/enablenz/projects/enzweb/api/node_modules/next/dist/compiled/node-fetch/index.js:1:51220\n' +
      '    at processTicksAndRejections (node:internal/process/task_queues:96:5)',
    name: 'FetchError'
  },
  url: 'http://localhost:3000/api/auth/session',
  message: 'invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0'
}

These are my files.

keystone.ts

import * as dotenv from 'dotenv';
dotenv.config();

import { config } from '@keystone-6/core';
import { KeystoneContext } from '@keystone-6/core/types';
import { lists } from './schema';
import { withAuth, session } from './auth';

export default withAuth(
  config({
    db: {
      provider: 'mysql',
      url: process.env.DATABASE_URL,
      useMigrations: true,
      idField: { kind: 'uuid' },
      enableLogging: true,
    },
    ui: {
      isAccessAllowed: (context: KeystoneContext) => !!context.session,
    },
    lists,
    session,
  })
);

auth.ts


import { randomBytes } from 'crypto';
import { createAuth } from '@opensaas/keystone-nextjs-auth';
import AzureADProvider from "@opensaas/keystone-nextjs-auth/providers/azure-ad";
import { statelessSessions } from '@keystone-6/core/session';

let sessionSecret = process.env.SESSION_SECRET;
if (!sessionSecret && process.env.NODE_ENV !== 'production') {
  sessionSecret = randomBytes(32).toString('hex');
}

const { withAuth } = createAuth({
  listKey: 'User',
  identityField: 'subjectId',
  sessionData: `id name email`,
  sessionSecret: sessionSecret,
  autoCreate: true,
  resolver: async ({user, profile, account}) => {
    console.log(user);
    console.log(profile);
    console.log(account);
    const name = user.name as string;
    const email = user.email as string;
    return { email, name };
  },
  keystonePath: '/admin',
  providers: [
    AzureADProvider({
      clientId: process.env.AZURE_AD_CLIENT_ID,
      clientSecret: process.env.AZURE_AD_CLIENT_SECRET,
      tenantId: process.env.AZURE_AD_TENANT_ID,
    }),    
  ]
});

const sessionMaxAge = 60 * 60 * 24 * 30;

// you can find out more at https://keystonejs.com/docs/apis/session#session-api
const session = statelessSessions({
  maxAge: sessionMaxAge,
  secret: sessionSecret!,
});

export { withAuth, session };

This is how the user table is set up in schema.ts:

  User: list({
    access: allowAll,
    fields: {
      name: text({ validation: { isRequired: true } }),
      email: text({
        validation: { isRequired: true },
        isIndexed: 'unique',
      }),
      subjectId: text({ isIndexed: 'unique' }),
      createdAt: timestamp({
        defaultValue: { kind: 'now' },
      }),
    },
  }),

And finally, these are the env vars I have set:

AZURE_AD_CLIENT_ID=<secret squirrel>
AZURE_AD_CLIENT_SECRET=<secret squirrel>
AZURE_AD_TENANT_ID=<secret squirrel>
DATABASE_URL=<secret squirrel>
NEXTAUTH_URL=http://localhost:3000/admin/api/auth
NODE_ENV=development
SESSION_SECRET=<secret squirrel>

Is there anything I am missing? Thanks for your patience ๐Ÿ‘

earthwytch commented 1 year ago

Ok, I fixed it by removing the keystonePath: '/admin', line from createAuth and changing all the relevant settings to match the removal of the /admin path:

Azure AD app registration callback url

http://localhost:3000/api/auth/callback/azure-ad

env variable

NEXTAUTH_URL=http://localhost:3000/api/auth

This fixed the CLIENT_FETCH_ERROR and allowed me to log in ๐ŸŽˆ

borisno2 commented 1 year ago

Thanks for the update @earthwytch

I have just released the latest version which should hopefully resolve your issue with using keystonePath it is also know using @keystone-6/core@4

Let me know how you go. Thanks