mirror of
https://github.com/formbricks/formbricks.git
synced 2026-02-25 00:41:05 -06:00
Rewrite Signup & Signin to make it more robust (#6)
* remove explicit CSRF-token handling * use NEXTAUTH_SECRET secret to better comply with nextAuth standards * update next.js and nextAuth * remove ECR github action * add name to mail-from
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# Modify this variables according to your setup and needs
|
||||
SECRET=RANDOM_STRING
|
||||
NEXTAUTH_SECRET=RANDOM_STRING
|
||||
DATABASE_URL='postgresql://user@localhost:5432/snoopforms?schema=public'
|
||||
NEXTAUTH_URL=http://localhost:3000
|
||||
|
||||
|
||||
49
.github/workflows/docker-image-ecr.yml
vendored
49
.github/workflows/docker-image-ecr.yml
vendored
@@ -1,49 +0,0 @@
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
|
||||
name: Deploy to Amazon ECR
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
env:
|
||||
AWS_REGION: eu-west-1 # set this to your preferred AWS region, e.g. us-west-1
|
||||
ECR_REPOSITORY: snoophub # set this to your Amazon ECR repository name
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy
|
||||
runs-on: ubuntu-latest
|
||||
environment: production
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@13d241b293754004c80624b5567555c4a39ffbe3
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ env.AWS_REGION }}
|
||||
|
||||
- name: Login to Amazon ECR
|
||||
id: login-ecr
|
||||
uses: aws-actions/amazon-ecr-login@aaf69d68aa3fb14c1d5a6be9ac61fe15b48453a2
|
||||
|
||||
- name: Build, tag, and push image to Amazon ECR
|
||||
id: build-image
|
||||
env:
|
||||
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
|
||||
IMAGE_TAG: latest
|
||||
run: |
|
||||
# Build a docker container and
|
||||
# push it to ECR so that it can
|
||||
# be deployed to ECS.
|
||||
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
|
||||
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
|
||||
echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"
|
||||
@@ -30,8 +30,6 @@ export default function BaseLayoutAuthorized({
|
||||
const { data: session, status } = useSession();
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
console.log(status);
|
||||
|
||||
useEffect(() => {
|
||||
if (status !== "loading") {
|
||||
if (!session) {
|
||||
|
||||
@@ -20,9 +20,13 @@ export const sendEmail = async (emailData: sendEmailData) => {
|
||||
user: serverRuntimeConfig.smtpUser,
|
||||
pass: serverRuntimeConfig.smtpPassword,
|
||||
},
|
||||
// logger: true,
|
||||
// debug: true,
|
||||
});
|
||||
const emailDefaults = {
|
||||
from: serverRuntimeConfig.mailFrom || "noreply@snoopforms.com",
|
||||
from: `snoopForms <${
|
||||
serverRuntimeConfig.mailFrom || "noreply@snoopforms.com"
|
||||
}>`,
|
||||
};
|
||||
await transporter.sendMail({ ...emailDefaults, ...emailData });
|
||||
};
|
||||
@@ -30,7 +34,7 @@ export const sendEmail = async (emailData: sendEmailData) => {
|
||||
export const sendVerificationEmail = async (user) => {
|
||||
const token = jwt.sign(
|
||||
{ id: user.id },
|
||||
serverRuntimeConfig.secret + user.email,
|
||||
serverRuntimeConfig.nextauthSecret + user.email,
|
||||
{
|
||||
expiresIn: "1d",
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ const nextConfig = {
|
||||
reactStrictMode: false,
|
||||
serverRuntimeConfig: {
|
||||
// Will only be available on the server side
|
||||
secret: process.env.SECRET,
|
||||
nextauthSecret: process.env.NEXTAUTH_SECRET,
|
||||
nextauthUrl: process.env.NEXTAUTH_URL,
|
||||
mailFrom: process.env.MAIL_FROM,
|
||||
smtpHost: process.env.SMTP_HOST,
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"@editorjs/paragraph": "^2.8.0",
|
||||
"@headlessui/react": "^1.6.1",
|
||||
"@heroicons/react": "^1.0.6",
|
||||
"@prisma/client": "^4.0.0",
|
||||
"@prisma/client": "^4.1.0",
|
||||
"@snoopforms/react": "^0.0.3",
|
||||
"babel-plugin-superjson-next": "^0.4.3",
|
||||
"bcryptjs": "^2.4.3",
|
||||
@@ -47,7 +47,7 @@
|
||||
"eslint": "8.15.0",
|
||||
"eslint-config-next": "12.1.6",
|
||||
"postcss": "^8.4.13",
|
||||
"prisma": "^4.0.0",
|
||||
"prisma": "^4.1.0",
|
||||
"tailwindcss": "^3.0.24",
|
||||
"ts-node": "^10.7.0",
|
||||
"typescript": "4.6.4"
|
||||
|
||||
@@ -23,12 +23,12 @@ export default async function auth(req: NextApiRequest, res: NextApiResponse) {
|
||||
email: {
|
||||
label: "Email Address",
|
||||
type: "email",
|
||||
placeholder: "lisa@example.com",
|
||||
placeholder: "Your email address",
|
||||
},
|
||||
password: {
|
||||
label: "Password",
|
||||
type: "password",
|
||||
placeholder: "Your super secure password",
|
||||
placeholder: "Your password",
|
||||
},
|
||||
},
|
||||
async authorize(credentials, _req) {
|
||||
@@ -66,7 +66,9 @@ export default async function auth(req: NextApiRequest, res: NextApiResponse) {
|
||||
return {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
name: user.name,
|
||||
firstname: user.firstname,
|
||||
lastname: user.firstname,
|
||||
emailVerified: user.emailVerified,
|
||||
};
|
||||
},
|
||||
}),
|
||||
@@ -109,7 +111,7 @@ export default async function auth(req: NextApiRequest, res: NextApiResponse) {
|
||||
const isValid = await new Promise((resolve) => {
|
||||
jwt.verify(
|
||||
credentials?.token,
|
||||
serverRuntimeConfig.secret + user.email,
|
||||
serverRuntimeConfig.nextauthSecret + user.email,
|
||||
(err) => {
|
||||
if (err) resolve(false);
|
||||
if (!err) resolve(true);
|
||||
@@ -150,7 +152,6 @@ export default async function auth(req: NextApiRequest, res: NextApiResponse) {
|
||||
}
|
||||
},
|
||||
},
|
||||
secret: serverRuntimeConfig.secret,
|
||||
pages: {
|
||||
signIn: "/auth/signin",
|
||||
signOut: "/auth/logout",
|
||||
|
||||
@@ -1,17 +1,26 @@
|
||||
import { getCsrfToken } from "next-auth/react";
|
||||
import { useRouter } from "next/router";
|
||||
import { XCircleIcon } from "@heroicons/react/solid";
|
||||
import { GetServerSideProps } from "next";
|
||||
import { signIn } from "next-auth/react";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
interface props {
|
||||
csrfToken: string;
|
||||
}
|
||||
|
||||
export default function SignIn({ csrfToken }: props) {
|
||||
export default function SignInPage() {
|
||||
const router = useRouter();
|
||||
const { error } = router.query;
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
await signIn("credentials", {
|
||||
callbackUrl: router.query.callbackUrl?.toString(),
|
||||
email: e.target.elements.email.value,
|
||||
password: e.target.elements.password.value,
|
||||
});
|
||||
router.push(
|
||||
`/auth/verification-requested?email=${encodeURIComponent(
|
||||
e.target.elements.email.value
|
||||
)}`
|
||||
);
|
||||
};
|
||||
return (
|
||||
<div className="flex min-h-screen bg-ui-gray-light">
|
||||
<div className="flex flex-col justify-center flex-1 px-4 py-12 mx-auto sm:px-6 lg:flex-none lg:px-20 xl:px-24">
|
||||
@@ -49,15 +58,11 @@ export default function SignIn({ csrfToken }: props) {
|
||||
<div className="mt-8">
|
||||
<div className="mt-6">
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
method="post"
|
||||
action="/api/auth/callback/credentials"
|
||||
className="space-y-6"
|
||||
>
|
||||
<input
|
||||
name="csrfToken"
|
||||
type="hidden"
|
||||
defaultValue={csrfToken}
|
||||
/>
|
||||
<div>
|
||||
<label
|
||||
htmlFor="email"
|
||||
@@ -121,10 +126,3 @@ export default function SignIn({ csrfToken }: props) {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const getServerSideProps: GetServerSideProps = async (context) => {
|
||||
const csrfToken = await getCsrfToken(context);
|
||||
return {
|
||||
props: { csrfToken },
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
import { getCsrfToken } from "next-auth/react";
|
||||
import { XCircleIcon } from "@heroicons/react/solid";
|
||||
import { GetServerSideProps } from "next";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { createUser } from "../../lib/users";
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useState } from "react";
|
||||
import { createUser } from "../../lib/users";
|
||||
|
||||
interface props {
|
||||
csrfToken: string;
|
||||
}
|
||||
|
||||
export default function SignIn({ csrfToken }: props) {
|
||||
export default function SignUpPage() {
|
||||
const router = useRouter();
|
||||
const [error, setError] = useState<string>("");
|
||||
|
||||
@@ -74,11 +68,6 @@ export default function SignIn({ csrfToken }: props) {
|
||||
</p>
|
||||
<div className="mt-6">
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
<input
|
||||
name="csrfToken"
|
||||
type="hidden"
|
||||
defaultValue={csrfToken}
|
||||
/>
|
||||
<div>
|
||||
<label
|
||||
htmlFor="firstname"
|
||||
@@ -145,7 +134,6 @@ export default function SignIn({ csrfToken }: props) {
|
||||
id="password"
|
||||
name="password"
|
||||
type="password"
|
||||
autoComplete="current-password"
|
||||
required
|
||||
className="block w-full px-3 py-2 border rounded-md shadow-sm appearance-none placeholder-ui-gray-medium border-ui-gray-medium focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm"
|
||||
/>
|
||||
@@ -174,10 +162,3 @@ export default function SignIn({ csrfToken }: props) {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const getServerSideProps: GetServerSideProps = async (context) => {
|
||||
const csrfToken = await getCsrfToken(context);
|
||||
return {
|
||||
props: { csrfToken },
|
||||
};
|
||||
};
|
||||
|
||||
36
yarn.lock
36
yarn.lock
@@ -235,22 +235,22 @@
|
||||
resolved "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.0.2.tgz"
|
||||
integrity sha512-MSAs9t3Go7GUkMhpKC44T58DJ5KGk2vBo+h1cqQeqlMfdGkxaVB78ZWpv9gYi/g2fa4sopag9gJsNvS8XGgWJA==
|
||||
|
||||
"@prisma/client@^4.0.0":
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@prisma/client/-/client-4.0.0.tgz#ed2f46930a1da0d8ae88d7965485973576b04270"
|
||||
integrity sha512-g1h2OGoRo7anBVQ9Cw3gsbjwPtvf7i0pkGxKeZICtwkvE5CZXW+xZF4FZdmrViYkKaAShbISL0teNpu9ecpf4g==
|
||||
"@prisma/client@^4.1.0":
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@prisma/client/-/client-4.1.0.tgz#7c5341b2276c083821e432536ff97d8cc8f8b936"
|
||||
integrity sha512-MvfPGAd42vHTiCYxwS6N+2U3F+ukoJ48D2QRnX1zSPJHBkh1CBtshl75daKzvVfgQwSouzSQeugKDej5di+E/g==
|
||||
dependencies:
|
||||
"@prisma/engines-version" "3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11"
|
||||
"@prisma/engines-version" "4.1.0-48.8d8414deb360336e4698a65aa45a1fbaf1ce13d8"
|
||||
|
||||
"@prisma/engines-version@3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11":
|
||||
version "3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11"
|
||||
resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11.tgz#4b5efe5eee2feef12910e4627a572cd96ed83236"
|
||||
integrity sha512-PiZhdD624SrYEjyLboI0X7OugNbxUzDJx9v/6ldTKuqNDVUCmRH/Z00XwDi/dgM4FlqOSO+YiUsSiSKjxxG8cw==
|
||||
"@prisma/engines-version@4.1.0-48.8d8414deb360336e4698a65aa45a1fbaf1ce13d8":
|
||||
version "4.1.0-48.8d8414deb360336e4698a65aa45a1fbaf1ce13d8"
|
||||
resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-4.1.0-48.8d8414deb360336e4698a65aa45a1fbaf1ce13d8.tgz#ce00e6377126e491a8b1e0e2039c97e2924bd6d9"
|
||||
integrity sha512-cRRJwpHFGFJZvtHbY3GZjMffNBEjjZk68ztn+S2hDgPCGB4H66IK26roK94GJxBodSehwRJ0wGyebC2GoIH1JQ==
|
||||
|
||||
"@prisma/engines@3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11":
|
||||
version "3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11"
|
||||
resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11.tgz#82f0018153cffa05d61422f9c0c7b0479b180f75"
|
||||
integrity sha512-u/rG4lDHALolWBLr3yebZ+N2qImp3SDMcu7bHNJuRDaYvYEXy/MqfNRNEgd9GoPsXL3gofYf0VzJf2AmCG3YVw==
|
||||
"@prisma/engines@4.1.0":
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-4.1.0.tgz#da8002d4b75c92e3fd564ba5b0bd04847ffb3c4c"
|
||||
integrity sha512-quqHXD3P83NBLVtRlts4SgKHmqgA8GMiyDTJ7af03Wg0gl6F5t65mBYvIuwmD+52vHm42JtIsp/fAO9YIV0JBA==
|
||||
|
||||
"@rushstack/eslint-patch@^1.1.3":
|
||||
version "1.1.3"
|
||||
@@ -2199,12 +2199,12 @@ pretty-format@^3.8.0:
|
||||
resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz"
|
||||
integrity sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==
|
||||
|
||||
prisma@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/prisma/-/prisma-4.0.0.tgz#4ddb8fcd4f64d33aff8c198a6986dcce66dc8152"
|
||||
integrity sha512-Dtsar03XpCBkcEb2ooGWO/WcgblDTLzGhPcustbehwlFXuTMliMDRzXsfygsgYwQoZnAUKRd1rhpvBNEUziOVw==
|
||||
prisma@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/prisma/-/prisma-4.1.0.tgz#5d43597f0f2603a4a75d9586346c74110d8e221f"
|
||||
integrity sha512-iwqpAT6In1uvMSwQAM3PqmaBdhh2OaQ/2t+n3RjpW4vAKP3R7E1T34FZUU4zGOWtMWm5dt0sPThQkT/h87r6gw==
|
||||
dependencies:
|
||||
"@prisma/engines" "3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11"
|
||||
"@prisma/engines" "4.1.0"
|
||||
|
||||
prop-types@^15.8.1:
|
||||
version "15.8.1"
|
||||
|
||||
Reference in New Issue
Block a user