277 lines
10 KiB
TypeScript
277 lines
10 KiB
TypeScript
import NextAuth, { NextAuthOptions } from "next-auth"
|
||
import GoogleProvider from "next-auth/providers/google"
|
||
import FacebookProvider from "next-auth/providers/facebook"
|
||
import GithubProvider from "next-auth/providers/github"
|
||
import TwitterProvider from "next-auth/providers/twitter"
|
||
import Auth0Provider from "next-auth/providers/auth0"
|
||
import AppleProvider from "next-auth/providers/apple"
|
||
import EmailProvider from "next-auth/providers/email"
|
||
import CredentialsProvider from "next-auth/providers/credentials"
|
||
import { PrismaAdapter } from "@auth/prisma-adapter"
|
||
import bcrypt from "bcrypt"
|
||
|
||
//microsoft
|
||
import AzureADProvider from "next-auth/providers/azure-ad";
|
||
|
||
// https://next-auth.js.org/getting-started/client
|
||
|
||
const common = require("../../../src/helpers/common");
|
||
import { isLoggedIn, setAuthTokens, clearAuthTokens, getAccessToken, getRefreshToken } from 'axios-jwt'
|
||
import { create } from "domain"
|
||
|
||
|
||
//console.log("appleID:", process.env.APPLE_APP_ID);
|
||
|
||
// console.log(process.env.EMAIL_SERVER)
|
||
// For more information on each option (and a full list of options) go to
|
||
// https://next-auth.js.org/configuration/options
|
||
export const authOptions: NextAuthOptions = {
|
||
// https://next-auth.js.org/configuration/providers/oauth
|
||
|
||
site: process.env.NEXT_PUBLIC_PUBLIC_URL,
|
||
secret: process.env.NEXTAUTH_SECRET, // Ensure you have this set in your .env file
|
||
//adapter: PrismaAdapter(prisma),
|
||
providers: [
|
||
// register new URL at https://console.cloud.google.com/apis/credentials/oauthclient/926212607479-d3m8hm8f8esp3rf1639prskn445sa01v.apps.googleusercontent.com?project=grand-forge-108716
|
||
//Request details: redirect_uri=http://20.101.62.76:8005/api/auth/callback/google https://s.mwitnessingmwitnessing.com/
|
||
GoogleProvider({
|
||
clientId: process.env.GOOGLE_ID,
|
||
clientSecret: process.env.GOOGLE_SECRET,
|
||
authorization: {
|
||
params: {
|
||
prompt: "consent",
|
||
access_type: "offline",
|
||
response_type: "code"
|
||
}
|
||
}
|
||
}),
|
||
AppleProvider({
|
||
// clientId: process.env.APPLE_APP_ID,
|
||
// clientSecret: process.env.APPLE_SECRET
|
||
clientId: process.env.APPLE_APP_ID,
|
||
clientSecret: {
|
||
appleId: process.env.APPLE_APP_ID,
|
||
teamId: process.env.APPLE_TEAM_ID,
|
||
privateKey: process.env.APPLE_PK,
|
||
keyId: process.env.APPLE_KEY_ID,
|
||
}
|
||
}),
|
||
// AzureADProvider({
|
||
// clientId: process.env.AZURE_AD_CLIENT_ID,
|
||
// clientSecret: process.env.AZURE_AD_CLIENT_SECRET,
|
||
// tenantId: process.env.AZURE_AD_TENANT_ID,
|
||
// }),
|
||
CredentialsProvider({
|
||
id: 'credentials',
|
||
// The name to display on the sign in form (e.g. 'Sign in with...')
|
||
name: 'Credentials',
|
||
credentials: {
|
||
username: { label: "Потребител", type: "text", placeholder: "Потребителско име" },
|
||
password: { label: "Парола", type: "password" }
|
||
},
|
||
async authorize(credentials, req) {
|
||
//const user = { id: "1", name: "Администратора", email: "jsmith@example.com" }
|
||
//return user
|
||
// const res = await fetch("/your/endpoint", {
|
||
// method: 'POST',
|
||
// body: JSON.stringify(credentials),
|
||
// headers: { "Content-Type": "application/json" }
|
||
// })
|
||
// const user = await res.json()
|
||
|
||
// // If no error and we have user data, return it
|
||
// if (res.ok && user) {
|
||
// return user
|
||
// }
|
||
// // Return null if user data could not be retrieved
|
||
// return null
|
||
const users = [
|
||
{ id: "1", name: "admin", email: "admin@example.com", password: "admin123", role: "ADMIN", static: true },
|
||
{ id: "2", name: "krasi", email: "krasi@example.com", password: "krasi123", role: "ADMIN", static: true },
|
||
{ id: "3", name: "popov", email: "popov@example.com", password: "popov123", role: "ADMIN", static: true }
|
||
];
|
||
|
||
const user = users.find(user =>
|
||
user.name === credentials.username && user.password === credentials.password
|
||
);
|
||
|
||
if (user) {
|
||
return user;
|
||
}
|
||
else {
|
||
const prisma = common.getPrismaClient();
|
||
const user = await prisma.user.findUnique({ where: { email: credentials.username } });
|
||
if (user) {
|
||
const match = await bcrypt.compare(credentials?.password, user.passwordHashLocalAccount);
|
||
if (match) {
|
||
console.log("User authenticated successfully.");
|
||
//create access token
|
||
user.accessToken = await getAccessToken();
|
||
|
||
return user;
|
||
}
|
||
else {
|
||
console.log("Password mismatch.");
|
||
throw new Error('невалидна парола');
|
||
}
|
||
}
|
||
else {
|
||
const pub = await prisma.publisher.findUnique({ where: { email: credentials.username } });
|
||
if (pub) {
|
||
const passHash = await bcrypt.hash(credentials.password, 10);
|
||
const newUser = await prisma.user.create({
|
||
data: {
|
||
name: credentials.username,
|
||
email: credentials.username,
|
||
passwordHashLocalAccount: passHash
|
||
}
|
||
});
|
||
console.log("New local credential user created for publisher ", pub.firstName, " ", pub.lastName, " (", pub.email, ")");
|
||
return newUser;
|
||
}
|
||
else {
|
||
|
||
throw new Error("Не можем да намерим твоя имейл '" + credentials?.username + "' в участниците в ССОМ. Моля свържи се с нас за да те регистрираме ако искаш да ползваш този имейл.");
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
})
|
||
/*
|
||
EmailProvider({
|
||
server: {
|
||
host: "smtp.mailtrap.io",
|
||
port: 2525,
|
||
auth: {
|
||
user: "8ec69527ff2104",
|
||
pass: "c7bc05f171c96c"
|
||
}
|
||
},
|
||
// server: process.env.EMAIL_SERVER,
|
||
from: "noreply@example.com",
|
||
}),
|
||
|
||
// Temporarily removing the Apple provider from the demo site as the
|
||
// callback URL for it needs updating due to Vercel changing domains
|
||
/*
|
||
|
||
*/
|
||
|
||
//d-popov@abv.bg
|
||
// Auth0Provider({
|
||
// clientId: process.env.AUTH0_ID,
|
||
// clientSecret: process.env.AUTH0_SECRET,
|
||
// issuer: process.env.AUTH0_ISSUER,
|
||
// }),
|
||
],
|
||
theme: {
|
||
colorScheme: "light",
|
||
},
|
||
session: {
|
||
strategy: "jwt"
|
||
},
|
||
callbacks: {
|
||
// https://codevoweb.com/implement-authentication-with-nextauth-in-nextjs-14/
|
||
async signIn({ user, account, profile }) {
|
||
if (account.provider === 'credentials' && user?.static) {
|
||
return true;
|
||
}
|
||
|
||
var prisma = common.getPrismaClient();
|
||
|
||
console.log("[nextauth] signIn:", account.provider, user.email)
|
||
//if (account.provider === 'google' ) {
|
||
|
||
// Check user in your database and assign roles
|
||
const dbUser = await prisma.publisher.findUnique({
|
||
where: { email: user.email }
|
||
});
|
||
|
||
if (dbUser) {
|
||
// Assign roles from your database to the session
|
||
user.role = dbUser.role;
|
||
user.id = dbUser.id;
|
||
//user.permissions = dbUser.permissions;
|
||
const session = { ...user };
|
||
|
||
await prisma.publisher.update({
|
||
where: { id: dbUser.id },
|
||
data: { lastLogin: new Date() }
|
||
});
|
||
return true;
|
||
} else {
|
||
//user nor found in our database. deny access, showing error message. logout and redirect to message page
|
||
//throw new Error(`Твоят имейл '${user.email}' не е регистриран в системата. Моля свържи се с нас за да те регистрираме ако искаш да ползваш този имейл.`);
|
||
throw new Error(`UserNotFound&email=${encodeURIComponent(user?.email)}`);
|
||
}
|
||
|
||
},
|
||
|
||
// async redirect({ url, baseUrl, user }) {
|
||
// // Redirect based on the user or error
|
||
// console.log("[nextauth] redirect", url, baseUrl, user)
|
||
// if (user) {
|
||
// return url;
|
||
// } else if (url.includes('error=UserNotFound')) {
|
||
// // Redirect to a custom error page or display an error
|
||
// return `${baseUrl}/error=UserNotFound&mail=${encodeURIComponent(user?.email)}`;
|
||
// }
|
||
// return baseUrl;
|
||
// },
|
||
|
||
// Persist the OAuth access_token to the token right after signin
|
||
async jwt({ token, user, account, profile, isNewUser }) {
|
||
//!console.log("[nextauth] JWT", token, user)
|
||
//token.userRole = "adminer"
|
||
if (user) {
|
||
token.role = user.role;
|
||
token.id = user.id; //already done in session?
|
||
//token.name = user.name; already done in session (name, email, picture, sub)
|
||
}
|
||
if (account && user) {
|
||
token.accessToken = account.access_token; // Set the access token from the account object
|
||
token.provider = account.provider;
|
||
console.log("[nextauth] setting token.accessToken", token.accessToken);
|
||
setAuthTokens({
|
||
accessToken: account.accessToken,
|
||
refreshToken: account.refreshToken,
|
||
})
|
||
}
|
||
|
||
return token;
|
||
},
|
||
|
||
// Send properties to the client, like an access_token from a provider.
|
||
async session({ session, token, user }) {
|
||
//!console.log("[nextauth] session", token, user)
|
||
if (token) {
|
||
//session.user.role = token.role;
|
||
session.user.id = token.id;
|
||
session.user.role = token.role;
|
||
session.user.name = token.name || token.email;
|
||
}
|
||
if (user?.impersonating) {
|
||
// Add flag to session if user is being impersonated
|
||
session.user.impersonating = true;
|
||
}
|
||
// if (session?.user) {
|
||
// session.user.id = user.id; //duplicate
|
||
// }
|
||
|
||
return {
|
||
...session,
|
||
accessToken: token.accessToken
|
||
};
|
||
},
|
||
},
|
||
pages: {
|
||
signIn: "/auth/signin",
|
||
signOut: "/auth/signout",
|
||
error: "/message", // Error code passed in query string as ?error=
|
||
verifyRequest: "/auth/verify-request", // (used for check email message)
|
||
newUser: null // If set, new users will be directed here on first sign in
|
||
},
|
||
}
|
||
|
||
export default NextAuth(authOptions) |