Add Microsoft Auth and update Auth UI
This commit is contained in:
parent
aff9222f5f
commit
c7fc01b782
@ -35,6 +35,8 @@ The application requires the following environment variables:
|
|||||||
- `DATABASE_URL`: PostgreSQL connection string
|
- `DATABASE_URL`: PostgreSQL connection string
|
||||||
- `NEXTAUTH_SECRET`: Secret for NextAuth.js
|
- `NEXTAUTH_SECRET`: Secret for NextAuth.js
|
||||||
- `NEXT_PUBLIC_BASE_URL`: Public URL of the application
|
- `NEXT_PUBLIC_BASE_URL`: Public URL of the application
|
||||||
|
- `MICROSOFT_CLIENT_ID`: Azure AD Application (client) ID for Microsoft Login
|
||||||
|
- `MICROSOFT_CLIENT_SECRET`: Azure AD Application secret for Microsoft Login
|
||||||
|
|
||||||
### Database Configuration
|
### Database Configuration
|
||||||
|
|
||||||
|
|||||||
11
package-lock.json
generated
11
package-lock.json
generated
@ -10,6 +10,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@auth/prisma-adapter": "^2.11.1",
|
"@auth/prisma-adapter": "^2.11.1",
|
||||||
|
"@next-auth/prisma-adapter": "^1.0.7",
|
||||||
"@prisma/client": "^5.22.0",
|
"@prisma/client": "^5.22.0",
|
||||||
"@types/bcryptjs": "^2.4.6",
|
"@types/bcryptjs": "^2.4.6",
|
||||||
"@types/nodemailer": "^7.0.11",
|
"@types/nodemailer": "^7.0.11",
|
||||||
@ -1955,6 +1956,16 @@
|
|||||||
"@tybys/wasm-util": "^0.10.0"
|
"@tybys/wasm-util": "^0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@next-auth/prisma-adapter": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@next-auth/prisma-adapter/-/prisma-adapter-1.0.7.tgz",
|
||||||
|
"integrity": "sha512-Cdko4KfcmKjsyHFrWwZ//lfLUbcLqlyFqjd/nYE2m3aZ7tjMNUjpks47iw7NTCnXf+5UWz5Ypyt1dSs1EP5QJw==",
|
||||||
|
"license": "ISC",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@prisma/client": ">=2.26.0 || >=3",
|
||||||
|
"next-auth": "^4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@next/env": {
|
"node_modules/@next/env": {
|
||||||
"version": "14.2.35",
|
"version": "14.2.35",
|
||||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.35.tgz",
|
"resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.35.tgz",
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@auth/prisma-adapter": "^2.11.1",
|
"@auth/prisma-adapter": "^2.11.1",
|
||||||
|
"@next-auth/prisma-adapter": "^1.0.7",
|
||||||
"@prisma/client": "^5.22.0",
|
"@prisma/client": "^5.22.0",
|
||||||
"@types/bcryptjs": "^2.4.6",
|
"@types/bcryptjs": "^2.4.6",
|
||||||
"@types/nodemailer": "^7.0.11",
|
"@types/nodemailer": "^7.0.11",
|
||||||
|
|||||||
@ -50,6 +50,10 @@ function LoginContent() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<p className="weekly-auth-recommended">
|
||||||
|
Recommended: Log in with email
|
||||||
|
</p>
|
||||||
|
|
||||||
{/* Login Form */}
|
{/* Login Form */}
|
||||||
<form onSubmit={handleCredentialsSignIn} className="weekly-auth-form">
|
<form onSubmit={handleCredentialsSignIn} className="weekly-auth-form">
|
||||||
<div className="weekly-auth-field">
|
<div className="weekly-auth-field">
|
||||||
@ -85,7 +89,7 @@ function LoginContent() {
|
|||||||
|
|
||||||
{/* Divider */}
|
{/* Divider */}
|
||||||
<div className="weekly-auth-divider">
|
<div className="weekly-auth-divider">
|
||||||
<span>or</span>
|
<span>or trust US Big Tech</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Google Sign In */}
|
{/* Google Sign In */}
|
||||||
@ -118,6 +122,20 @@ function LoginContent() {
|
|||||||
Continue with Apple
|
Continue with Apple
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
{/* Microsoft Sign In */}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => { setIsLoading(true); signIn('azure-ad', { callbackUrl }); }}
|
||||||
|
disabled={isLoading}
|
||||||
|
className="weekly-auth-button"
|
||||||
|
style={{ marginTop: '0.75rem', backgroundColor: '#0078D4', color: '#fff', border: '1px solid #0078D4' }}
|
||||||
|
>
|
||||||
|
<svg className="microsoft-icon" viewBox="0 0 21 21" width="18" height="18" fill="currentColor">
|
||||||
|
<path d="M10 0H0v10h10V0zM21 0H11v10h10V0zM10 11H0v10h10V11zM21 11H11v10h10V11z" />
|
||||||
|
</svg>
|
||||||
|
Continue with Microsoft
|
||||||
|
</button>
|
||||||
|
|
||||||
{/* Links */}
|
{/* Links */}
|
||||||
<div className="weekly-auth-links">
|
<div className="weekly-auth-links">
|
||||||
<Link href="/auth/forgot-password" className="weekly-auth-link">
|
<Link href="/auth/forgot-password" className="weekly-auth-link">
|
||||||
|
|||||||
@ -91,6 +91,10 @@ export default function SignupPage() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<p className="weekly-auth-recommended">
|
||||||
|
Recommended: Sign up with email
|
||||||
|
</p>
|
||||||
|
|
||||||
{/* Signup Form */}
|
{/* Signup Form */}
|
||||||
<form onSubmit={handleSignup} className="weekly-auth-form">
|
<form onSubmit={handleSignup} className="weekly-auth-form">
|
||||||
<div className="weekly-auth-field">
|
<div className="weekly-auth-field">
|
||||||
@ -150,7 +154,7 @@ export default function SignupPage() {
|
|||||||
|
|
||||||
{/* Divider */}
|
{/* Divider */}
|
||||||
<div className="weekly-auth-divider">
|
<div className="weekly-auth-divider">
|
||||||
<span>or</span>
|
<span>or trust US Big Tech</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Google Sign Up */}
|
{/* Google Sign Up */}
|
||||||
@ -183,6 +187,20 @@ export default function SignupPage() {
|
|||||||
Sign up with Apple
|
Sign up with Apple
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
{/* Microsoft Sign Up */}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => { setIsLoading(true); signIn('azure-ad', { callbackUrl: '/tasks' }); }}
|
||||||
|
disabled={isLoading}
|
||||||
|
className="weekly-auth-button"
|
||||||
|
style={{ marginTop: '0.75rem', backgroundColor: '#0078D4', color: '#fff', border: '1px solid #0078D4' }}
|
||||||
|
>
|
||||||
|
<svg className="microsoft-icon" viewBox="0 0 21 21" width="18" height="18" fill="currentColor">
|
||||||
|
<path d="M10 0H0v10h10V0zM21 0H11v10h10V0zM10 11H0v10h10V11zM21 11H11v10h10V11z" />
|
||||||
|
</svg>
|
||||||
|
Sign up with Microsoft
|
||||||
|
</button>
|
||||||
|
|
||||||
{/* Links */}
|
{/* Links */}
|
||||||
<div className="weekly-auth-links">
|
<div className="weekly-auth-links">
|
||||||
<span className="weekly-auth-text">Already have an account?</span>
|
<span className="weekly-auth-text">Already have an account?</span>
|
||||||
|
|||||||
@ -186,6 +186,14 @@ h3 {
|
|||||||
color: #64748b;
|
color: #64748b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.weekly-auth-recommended {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: #475569;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
.time-indicator {
|
.time-indicator {
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
color: #3b82f6;
|
color: #3b82f6;
|
||||||
@ -330,7 +338,6 @@ h3 {
|
|||||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Auth Form */
|
|
||||||
.auth-form {
|
.auth-form {
|
||||||
background: white;
|
background: white;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
import { NextAuthOptions } from "next-auth";
|
import { NextAuthOptions } from "next-auth";
|
||||||
import GoogleProvider from "next-auth/providers/google";
|
import GoogleProvider from "next-auth/providers/google";
|
||||||
|
import AzureADProvider from "next-auth/providers/azure-ad";
|
||||||
import AppleProvider from "next-auth/providers/apple";
|
import AppleProvider from "next-auth/providers/apple";
|
||||||
import { PrismaAdapter } from "@auth/prisma-adapter";
|
import { PrismaAdapter } from "@next-auth/prisma-adapter";
|
||||||
import CredentialsProvider from "next-auth/providers/credentials";
|
import CredentialsProvider from "next-auth/providers/credentials";
|
||||||
import { compare } from "bcryptjs";
|
import { compare } from "bcryptjs";
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
|
|
||||||
export const authOptions: NextAuthOptions = {
|
export const authOptions: NextAuthOptions = {
|
||||||
adapter: PrismaAdapter(prisma) as any,
|
adapter: PrismaAdapter(prisma),
|
||||||
providers: [
|
providers: [
|
||||||
GoogleProvider({
|
GoogleProvider({
|
||||||
clientId: process.env.GOOGLE_CLIENT_ID || "",
|
clientId: process.env.GOOGLE_CLIENT_ID || "",
|
||||||
@ -17,7 +18,8 @@ export const authOptions: NextAuthOptions = {
|
|||||||
params: {
|
params: {
|
||||||
prompt: "consent",
|
prompt: "consent",
|
||||||
access_type: "offline",
|
access_type: "offline",
|
||||||
response_type: "code"
|
response_type: "code",
|
||||||
|
scope: "openid profile email https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/calendar.events https://www.googleapis.com/auth/tasks"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
@ -26,6 +28,18 @@ export const authOptions: NextAuthOptions = {
|
|||||||
clientSecret: process.env.APPLE_SECRET || "",
|
clientSecret: process.env.APPLE_SECRET || "",
|
||||||
allowDangerousEmailAccountLinking: true,
|
allowDangerousEmailAccountLinking: true,
|
||||||
}),
|
}),
|
||||||
|
AzureADProvider({
|
||||||
|
clientId: process.env.MICROSOFT_CLIENT_ID || "",
|
||||||
|
clientSecret: process.env.MICROSOFT_CLIENT_SECRET || "",
|
||||||
|
tenantId: "common",
|
||||||
|
allowDangerousEmailAccountLinking: true,
|
||||||
|
authorization: {
|
||||||
|
params: {
|
||||||
|
prompt: "consent",
|
||||||
|
scope: "openid profile email offline_access user.read Calendars.ReadWrite Tasks.ReadWrite"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}),
|
||||||
CredentialsProvider({
|
CredentialsProvider({
|
||||||
name: "credentials",
|
name: "credentials",
|
||||||
credentials: {
|
credentials: {
|
||||||
@ -70,6 +84,7 @@ export const authOptions: NextAuthOptions = {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
|
debug: true,
|
||||||
session: {
|
session: {
|
||||||
strategy: "jwt"
|
strategy: "jwt"
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user