Comments (4)
Here's a workable solution I ended up with today.
//auth.js
import NextAuth from "next-auth"
import AzureAD from "next-auth/providers/azure-ad"
import Credentials from "next-auth/providers/credentials"
var providers = [];
if (process.env.NODE_ENV === "development") {
providers.push(
Credentials({
id: "password",
name: "Password",
credentials: {
password: { label: "", type: "password" },
},
authorize: (credentials) => {
if (credentials.password === "password") {
return {
email: "[email protected]",
name: "Test User",
image: "https://avatars.githubusercontent.com/u/67470890?s=200&v=4",
}
}
},
})
)
} else {
providers.push(AzureAD({
clientId: process.env.AUTH_AZURE_AD_ID,
clientSecret: process.env.AUTH_AZURE_AD_SECRET,
tenantId: process.env.AUTH_AZURE_AD_TENANT_ID,
token: {
url: `https://login.microsoftonline.com/${process.env.AUTH_AZURE_AD_TENANT_ID}/oauth2/v2.0/token`,
},
userinfo: {
url: "https://graph.microsoft.com/oidc/userinfo",
},
authorization: {
url: `https://login.microsoftonline.com/${process.env.AUTH_AZURE_AD_TENANT_ID}/oauth2/v2.0/authorize`,
params: {
scope: "openid email User.Read"
}
},
async profile(profile, tokens) {
const response = await fetch(
`https://graph.microsoft.com/v1.0/me`,
{ headers: { Authorization: `Bearer ${tokens.access_token}` } }
)
const json = await response.json()
return {
id: profile.sub,
name: profile.name,
email: json.userPrincipalName,
}
},
}))
}
export const config = {
debug: true,
theme: {
logo: "https://next-auth.js.org/img/logo/logo-sm.png",
},
providers: providers,
callbacks: {
authorized({ auth, request }) {
//Allow unauthorized access to main page, /signin page
//Users are redirected to /signin on logout or auth failures
//https://next-auth.js.org/getting-started/client#signin
//https://next-auth.js.org/getting-started/client#signout
const whitelistURLs = ['/signin','/'];
const { pathname } = request.nextUrl
const isLoggedIn = !!auth?.user;
if(!auth && pathname === '/signin'){
return true;
}
if(!auth && !whitelistURLs.includes(pathname)){
return false;
}
return true
}
}
}
export const { handlers, auth, signIn, signOut } = NextAuth(config)
// /app/api/auth/[...nextauth]/route.js
import NextAuth from "next-auth"
import AzureAD from "next-auth/providers/azure-ad";
import Credentials from "next-auth/providers/credentials"
var providers = [];
if(process.env.ENV === 'development'){
providers.push(Credentials)
} else {
providers.push(AzureAD);
}
import { handlers } from "../../../../auth"
export const { GET, POST } = handlers
With these two in place i can pass the session down from the layout to the child components. Typescript was causing huge issues and changing auth.ts
and [...nextauth].ts
to javascript resolved all of the problems I had around types. There was no additional code required, in fact all I had to do was remove a few type statements. It took a lot of trial and error moving the provider configs between the [...nextauth].js
and auth.js
. Lack of examples in the docs that show the different use cases / possibilities is the issue here.
// /app/components/header.jsx
"use client"
import Link from 'next/link';
import Logo from './logo';
import { useState } from 'react';
import { Dialog, Menu } from '@headlessui/react';
import SignOutButton from './SignOutButton';
import SignInButton from './SignInButton';
import LocalSignInButton from './LocalSignInButton';
const navigation = [
{ name: 'Users', href: '/users', dropdown: false },
{ name: 'Organizations', href: '/organizations', dropdown: false },
];
export default function Header({ session }) {
//From the template / component the layout started with
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
const isLocalDev = ( process.env.ENV === 'development' ? true : false);
//visual indicator for dev / local (red dev, blue prod)
const signInElement = (isLocalDev ? <LocalSignInButton/> : <SignInButton/>);
// /src/app/layout.js
import { Inter } from 'next/font/google'
import './globals.css'
import Header from './components/header'
import Footer from './components/footer'
import { auth } from "../auth"
const inter = Inter({ subsets: ['latin'] })
export default async function RootLayout({ children }) {
const session = await auth()
if(session) session.environment = process.env.ENV
return (
<html lang="en">
<body className={inter.className}>
<Header session={session}/>
<main className="mt-28 grid justify-center max-h-max">
{children}
</main>
<Footer/>
</body>
</html>
)
}
One of the most painful parts of this was the piecemeal nature of the information I needed to form this solution. I referenced both the v4 and v5 docs, it was extremely difficult to find more documentation on the auth options and in which files the config or just the imports belong.
The v5 docs need some sort of review from the perspective of "can somebody go through this page and actually use it".
What I have provided above is a complete enough solution that someone can get it working without spending days bouncing between v4 and v5 docs.
I hope someone can determine what from my solution is appropriate to add to the docs to address the concerns I raised above.
from next-auth.
Sorry you had such a hard time getting this setup, it looks like you've got some v4 and v5 things mixed up.
For v5 if you follow the docs step-by-step starting with a "clean" (i.e. remove all previous auth.js/next-auth related stuff) Next.js project from the "Installation" page, you should be good to go.
In v5, the .../auth/[...nextauth]/route.ts
should only be 2 lines more or less:
import { handlers } from "@/auth" // Referring to the auth.ts we just created
export const { GET, POST } = handlers
The rest of the config goes in your ./auth.ts
file, where you export the methods returned from NextAUth
to be used elsewhere (like in the route file ^^). Also yuo dont need the callbacks for anything, that's all optional advanced stuff.
Also we have an example app you can always look at here
from next-auth.
For your testing use-case, I think you were on the right track.
Basically if NODE_ENV === 'development'
, push Credentials({ .. })
into your providers
array as shown in the testing page.
from next-auth.
Also did you need to overwrite some AzureAD
provider configuration for your specific use-case? If not, you can simplify that part to the following if you name your env vars as expected.
AUTH_AZURE_AD_ID
AUTH_AZURE_AD_SECRET
AUTH_AZURE_AD_TENANT_ID
// auth.ts
import NextAuth from "next-auth"
import AzureAD from "next-auth/providers/azure-ad"
import Credentials from "next-auth/providers/credentials"
import type { Provider } from "@auth/sveltekit/providers"
var providers: Provider[] = [];
if (process.env.NODE_ENV === "development") {
providers.push(
Credentials({
id: "password",
name: "Password",
credentials: {
password: { label: "", type: "password" },
},
authorize: (credentials) => {
if (credentials.password === "password") {
return {
email: "[email protected]",
name: "Test User",
image: "https://avatars.githubusercontent.com/u/67470890?s=200&v=4",
}
}
},
})
)
} else {
providers.push(AzureAD)
}
export const { handlers, auth, signIn, signOut } = NextAuth({
debug: true,
providers,
})
I would do the authorized
/ session
checking in the pages themselves. See: https://authjs.dev/getting-started/session-management/protecting
This is all just following the examples mostly in the "Installation", "Session Management/*" and "Testing" pages 😊
EDIT: Promise this is the last follow-up / FYI haha - we released an "Microsoft Entra ID" provider (which is mostly just a rebadged "AzureAD" provider) in [email protected]
the other day
from next-auth.
Related Issues (20)
- GetToken() not working in middleware.ts HOT 1
- Invalid Callback URL "android-app://com.google.android.googlequicksearchbox/" HOT 1
- Invalid Callback URL "android-app://com.google.android.googlequicksearchbox/"
- Middleware breaks when using next-auth with Firestore Adapter HOT 1
- Update Edge Compatibility section for Middleware
- URL Redirection Error on Authentication Failure (Middleware file) HOT 1
- URL Redirection Error on Authentication Failure (Middleware file) HOT 1
- Discord Link invalid HOT 1
- Outdated Next-Auth v4 MongoDB adapter which is broken with MongoDB nodejs driver v6+ HOT 1
- Outdated Next-Auth v4 MongoDB adapter which is broken with MongoDB nodejs driver v6+
- Route "[...nextauth]/route.ts" does not match the required types of a Next.js Route. Invalid configuration "GET": HOT 3
- discord community link expired HOT 1
- Custom Provider broken by V5 HOT 5
- How to ignore / edit provider response format
- Undocumented Changes to provider fields
- DrizzleKit Adapter not respecting $defaultFn for user.id
- FusionAuth - Provider Type Conflict
- `AdapterUser.id` is a string, but pg-adapter uses an `integer` HOT 1
- [useSession] Calling update() does nothing when unauthenticated HOT 1
- Sveltekit docs referers to NextAuth in some places. HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from next-auth.