Added password confimation during registration
This commit is contained in:
@@ -4,8 +4,9 @@ import { NextResponse } from "next/server";
|
||||
import { auth } from "firebase-admin";
|
||||
import { signInWithEmailAndPassword } from "firebase/auth";
|
||||
// Lib Imports
|
||||
import { auth as authConfig } from "../firebase-config";
|
||||
import { app, auth as authConfig } from "../firebase-config";
|
||||
import { customInitApp } from "../firebase-admin";
|
||||
import { getDatabase, ref, get as firebaseGet } from "firebase/database";
|
||||
|
||||
// Needs to "init" on each call to the API
|
||||
customInitApp();
|
||||
@@ -16,9 +17,32 @@ async function handleEmailAndPassword(email, password) {
|
||||
var userCredential = await signInWithEmailAndPassword(authConfig,email,password);
|
||||
if (userCredential.user.accessToken) {
|
||||
var token = await auth().verifyIdToken(userCredential.user.accessToken);
|
||||
var expiresIn = 20 * 60 * 1000; // 20 minutes
|
||||
var sessionCookie = await auth().createSessionCookie(userCredential.user.accessToken, {expiresIn,});
|
||||
if (token) {
|
||||
var expiresIn = 20 * 60 * 1000; // 20 minutes
|
||||
var sessionCookie = await auth().createSessionCookie(userCredential.user.accessToken, {expiresIn,});
|
||||
var database = getDatabase(app)
|
||||
var user = await firebaseGet(ref(database, `users/${userCredential.user.uid}`));
|
||||
if (!user.exists()) {
|
||||
var userOptions = {
|
||||
name: "user",
|
||||
value: JSON.stringify({defined: false, uid: userCredential.user.uid}),
|
||||
maxAge: expiresIn, // 20 mins
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
};
|
||||
} else {
|
||||
var userData = user.val()
|
||||
userData.uid = userCredential.user.uid
|
||||
userData.defined = true
|
||||
var userOptions = {
|
||||
name: "user",
|
||||
value: JSON.stringify(userData),
|
||||
maxAge: expiresIn, // 20 mins
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
};
|
||||
}
|
||||
cookies().set(userOptions);
|
||||
var options = {
|
||||
name: "session",
|
||||
value: sessionCookie,
|
||||
@@ -27,14 +51,13 @@ async function handleEmailAndPassword(email, password) {
|
||||
secure: true,
|
||||
};
|
||||
cookies().set(options);
|
||||
var uid_options = {
|
||||
cookies().set({
|
||||
name: "uid",
|
||||
value: userCredential.user.uid,
|
||||
maxAge: expiresIn, // 20 mins
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
};
|
||||
cookies().set(uid_options);
|
||||
});
|
||||
return NextResponse.json({ options }, { status: 200 });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,15 +3,8 @@ import { NextResponse } from "next/server";
|
||||
|
||||
|
||||
export async function GET(req) {
|
||||
cookies().set({
|
||||
name: "session",
|
||||
value: "",
|
||||
maxAge: -1,
|
||||
});
|
||||
cookies().set({
|
||||
name: "firstName",
|
||||
value: "",
|
||||
maxAge: -1,
|
||||
});
|
||||
cookies().delete('user')
|
||||
cookies().delete('session')
|
||||
cookies().delete('uid')
|
||||
return NextResponse.json({}, { status: 200 });
|
||||
}
|
||||
@@ -1,37 +1,7 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { cookies } from "next/headers";
|
||||
import { app } from "../firebase-config";
|
||||
import { getDatabase, ref, get as firebaseGet } from "firebase/database";
|
||||
|
||||
export async function POST(req,res) {
|
||||
var uid = await req?.json()
|
||||
var database = getDatabase(app)
|
||||
var user = await firebaseGet(ref(database, `users/${uid}`));
|
||||
if (!user.exists()) {
|
||||
return NextResponse.json({
|
||||
firstName: "not-found",
|
||||
lastName: "not-found",
|
||||
uid: "not-found",
|
||||
});
|
||||
} else {
|
||||
cookies().set("firstName",user.val()?.firstName)
|
||||
cookies().set("lastName",user.val()?.lastName)
|
||||
cookies().set("uid",uid)
|
||||
return NextResponse.json({
|
||||
firstName: user.val()?.firstName,
|
||||
lastName: user.val()?.lastName,
|
||||
uid: uid,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export async function GET(req) {
|
||||
var uid = cookies().get("uid")?.value
|
||||
var database = getDatabase(app)
|
||||
var user = await firebaseGet(ref(database, `users/${uid}`));
|
||||
return NextResponse.json({
|
||||
firstName: user.val()?.firstName,
|
||||
lastName: user.val()?.lastName,
|
||||
uid: cookies().get("uid")?.value,
|
||||
})
|
||||
var userData = cookies().get("user")?.value || false
|
||||
return userData != false? NextResponse.json(JSON.parse(userData)): NextResponse.json({},{status: 203})
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
export function Header() {
|
||||
return (
|
||||
<div className="m-2 rounded-lg h-[60px] bg-white shadow-2xl">
|
||||
<a href="/"><img src="/logos/logo_transparent_inverse.png" className="h-[60px]"></img></a>
|
||||
<a href="/"><img src="/logos/logo_transparent_inverse.png" className="h-[60px]"/></a>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import "../globals.css"
|
||||
function Login() {
|
||||
var router = useRouter();
|
||||
//var { register, handleSubmit } = useForm();
|
||||
var { register, control, setError, formState: { errors } } = useForm()
|
||||
var { register, control, setError, formState: { errors, isSubmitting, isSubmitted } } = useForm()
|
||||
return (
|
||||
<div>
|
||||
<div className="grid h-screen place-items-center">
|
||||
@@ -32,7 +32,15 @@ function Login() {
|
||||
>
|
||||
<input type="email" id="email" className={(errors.email && errors.password) && "err"} {...register("email", { required: true })} placeholder="Enter Email Address"/><br/>
|
||||
<input type="password" id="password" name="password" className={(errors.email && errors.password) && "err"} {...register("password", { required: true })} placeholder="Enter Password"/><br/>
|
||||
<button className="bg-[#dee0e0] m-5 bg-cyan-500 text-white font-bold py-2 px-4 rounded-full">Log In</button>
|
||||
<button className="inline-flex items-center px-4 py-2 transition ease-in-out duration-150 bg-[#dee0e0] m-5 bg-cyan-500 text-white font-bold py-2 px-4 rounded-full">
|
||||
{(isSubmitting || isSubmitted) && <span className="inline-block">
|
||||
<svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
</span> }
|
||||
Log In
|
||||
</button>
|
||||
<br/>Need an account? <a href="/register">Sign Up</a><br/>
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
"use client"
|
||||
import { useState, useEffect } from 'react'
|
||||
|
||||
|
||||
function Home() {
|
||||
|
||||
const [statusCode, setData] = useState(null)
|
||||
useEffect(() => {
|
||||
fetch('/api/user')
|
||||
.then((res) => res.status)
|
||||
.then((status) => {
|
||||
setData(status)
|
||||
})
|
||||
}, [])
|
||||
return (
|
||||
<div>
|
||||
<div className="grid h-screen place-items-center">
|
||||
@@ -9,10 +20,14 @@ function Home() {
|
||||
Chat with friends!
|
||||
</span>
|
||||
<div className="m-5">
|
||||
<a href="/login"><button className="bg-cyan-500 text-white font-bold py-2 px-4 rounded-full">
|
||||
Login</button></a>
|
||||
<a href="/register"><button className="bg-cyan-500 text-white font-bold py-2 px-4 rounded-full">
|
||||
Signup</button></a>
|
||||
{statusCode == 203 &&
|
||||
<div>
|
||||
<a href="/login"><button className="bg-cyan-500 text-white font-bold py-2 px-4 rounded-full">Login</button></a>
|
||||
<a href="/register"><button className="bg-cyan-500 text-white font-bold py-2 px-4 rounded-full">Sign Up</button></a>
|
||||
</div>
|
||||
}
|
||||
{statusCode == 200 && <a href="/app"><button className="bg-cyan-500 text-white font-bold py-2 px-4 rounded-full">Continue to App</button></a>}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,11 @@ import { useState } from "react";
|
||||
import { data } from "autoprefixer";
|
||||
|
||||
function Register() {
|
||||
<<<<<<< HEAD
|
||||
var { register, control, setError, handleSubmit, formState: { errors } } = useForm()
|
||||
=======
|
||||
var { register, control, setError, formState: { errors, isSubmitting, isSubmitted } } = useForm()
|
||||
>>>>>>> main
|
||||
var router = useRouter();
|
||||
var emailRegex = /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/
|
||||
var [passwordMismatch, setPasswordMismatch] = useState(false);
|
||||
@@ -46,10 +50,22 @@ function Register() {
|
||||
>
|
||||
<input type="email" {...register("email", {required: true, pattern: emailRegex})} className={errors.email && "err"} placeholder="Enter Email Address"/><br/>
|
||||
<input type="password" {...register("password", {required: true})} className={errors.password && errors.password.type == 'required' && "err"} placeholder="Enter Password"/><br/>
|
||||
<<<<<<< HEAD
|
||||
<input type ="password" {...register("passwordCheck", {required: false})} className ={errors.passwordCheckheck && errors.passwordCheck.type == 'required' && "err"} placeholder="Re-enter Password"/><br/>
|
||||
{passwordMismatch && <p className="text-red-500">Passwords do not match</p>}
|
||||
<button type="submit" className="bg-[#dee0e0] m-5 bg-cyan-500 text-white font-bold py-2 px-4 rounded-full">
|
||||
Register</button><br/>
|
||||
=======
|
||||
<button className="inline-flex items-center px-4 py-2 transition ease-in-out duration-150 bg-[#dee0e0] m-5 bg-cyan-500 text-white font-bold py-2 px-4 rounded-full">
|
||||
{(isSubmitting || isSubmitted) && <span className="inline-block">
|
||||
<svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
</span> }
|
||||
Register
|
||||
</button><br/>
|
||||
>>>>>>> main
|
||||
Have an account? <a href="/login">Log In</a>
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
@@ -3,40 +3,53 @@ import { NextResponse } from "next/server";
|
||||
import { cookies } from "next/headers";
|
||||
|
||||
export async function middleware(req, res) {
|
||||
const session = req.cookies.get("session");
|
||||
// Login if not logged in
|
||||
if (!session) {
|
||||
return NextResponse.redirect(new URL("/login", req.url));
|
||||
}
|
||||
//Call the authentication endpoint
|
||||
const responseAPI = await fetch(new URL("/api/login", req.url), {
|
||||
headers: {
|
||||
Cookie: `session=${session?.value}`,
|
||||
},
|
||||
});
|
||||
const session = await req.cookies.get("session");
|
||||
if (req.nextUrl.pathname !== "/login" && req.nextUrl.pathname != "/register") {
|
||||
// Login if not logged in
|
||||
if (!session) {
|
||||
return NextResponse.redirect(new URL("/login", req.url));
|
||||
}
|
||||
//Call the authentication endpoint
|
||||
const responseAPI = await fetch(new URL("/api/login", req.url), {
|
||||
headers: {
|
||||
Cookie: `session=${session?.value}`,
|
||||
},
|
||||
});
|
||||
|
||||
// Login if unauthorized
|
||||
if (responseAPI.status !== 200) {
|
||||
return NextResponse.redirect(new URL("/login", req.url));
|
||||
}
|
||||
// Login if unauthorized
|
||||
if (responseAPI.status !== 200) {
|
||||
return NextResponse.redirect(new URL("/login", req.url));
|
||||
}
|
||||
|
||||
// If new user, redirect to onboarding
|
||||
var { uid } = await responseAPI.json()
|
||||
var user = await fetch(new URL("/api/user", req.url), {
|
||||
method: "POST",
|
||||
body: JSON.stringify(uid ? uid : {}),
|
||||
});
|
||||
user = await user.json();
|
||||
if (user.firstName !== "not-found") {
|
||||
return NextResponse.next();
|
||||
// If new user, redirect to onboarding
|
||||
var user = JSON.parse(req.cookies.get("user").value)
|
||||
if (user.defined) {
|
||||
return NextResponse.next();
|
||||
} else {
|
||||
return NextResponse.redirect(new URL("/onboarding", req.url));
|
||||
}
|
||||
} else {
|
||||
return NextResponse.redirect(new URL("/onboarding", req.url));
|
||||
// Currently in the /login or /register, if user is authenticated, go ahead and direct them to the app
|
||||
if (session) {
|
||||
const responseAPI = await fetch(new URL("/api/login", req.url), {
|
||||
headers: {
|
||||
Cookie: `session=${session?.value}`,
|
||||
},
|
||||
});
|
||||
if (responseAPI.status == 200) {
|
||||
return NextResponse.redirect(new URL("/app", req.url))
|
||||
} else {
|
||||
return NextResponse.next() // Unauthenticated, continue
|
||||
}
|
||||
} else {
|
||||
return NextResponse.next() // Not logged in, direct to login
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Protected routes
|
||||
export const config = {
|
||||
matcher: ['/((?!login|register|onboarding|api|_next/static|_next/image|auth|favicon.ico|robots.txt|images|logo|$).*)',],
|
||||
matcher: ['/((?!onboarding|api|_next/static|_next/image|auth|favicon.ico|robots.txt|images|logo|$).*)',],
|
||||
missing: [
|
||||
{ type: 'header', key: 'next-router-prefetch' },
|
||||
{ type: 'header', key: 'purpose', value: 'prefetch' },
|
||||
|
||||
Reference in New Issue
Block a user