Skip to content

Commit 71caa6d

Browse files
authored
Prevent new account creation on login (#1976)
* Prevent account creation if we're not signin up * remove cookie once logged in, 24 hours expiry, comment * adjust error messages * check signin instead of signup * appendHeader to avoid overwrites, fix typo, use NodeNextRequest to handle cookies * expire cookie if signup
1 parent 4f17615 commit 71caa6d

File tree

3 files changed

+24
-5
lines changed

3 files changed

+24
-5
lines changed

components/login.js

+17-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { signIn } from 'next-auth/react'
22
import styles from './login.module.css'
33
import { Form, Input, SubmitButton } from '@/components/form'
4-
import { useState } from 'react'
4+
import { useState, useEffect } from 'react'
55
import Alert from 'react-bootstrap/Alert'
66
import { useRouter } from 'next/router'
77
import { LightningAuthWithExplainer } from './lightning-auth'
@@ -42,21 +42,34 @@ const authErrorMessages = {
4242
OAuthCallback: 'Error handling OAuth response. Try again or choose a different method.',
4343
OAuthCreateAccount: 'Could not create OAuth account. Try again or choose a different method.',
4444
EmailCreateAccount: 'Could not create Email account. Try again or choose a different method.',
45-
Callback: 'Try again or choose a different method.',
45+
Callback: 'Could not authenticate. Try again or choose a different method.',
4646
OAuthAccountNotLinked: 'This auth method is linked to another account. To link to this account first unlink the other account.',
4747
EmailSignin: 'Failed to send email. Make sure you entered your email address correctly.',
48-
CredentialsSignin: 'Auth failed. Try again or choose a different method.',
48+
CredentialsSignin: 'Could not authenticate. Try again or choose a different method.',
4949
default: 'Auth failed. Try again or choose a different method.'
5050
}
5151

5252
export function authErrorMessage (error) {
5353
return error && (authErrorMessages[error] ?? authErrorMessages.default)
5454
}
5555

56-
export default function Login ({ providers, callbackUrl, multiAuth, error, text, Header, Footer }) {
56+
export default function Login ({ providers, callbackUrl, multiAuth, error, text, Header, Footer, signin }) {
5757
const [errorMessage, setErrorMessage] = useState(authErrorMessage(error))
5858
const router = useRouter()
5959

60+
// signup/signin awareness cookie
61+
useEffect(() => {
62+
const cookieOptions = [
63+
`signin=${!!signin}`,
64+
'path=/',
65+
'max-age=' + (signin ? 60 * 60 * 24 : 0), // 24 hours if signin is true, expire the cookie otherwise
66+
'SameSite=Lax',
67+
process.env.NODE_ENV === 'production' ? 'Secure' : ''
68+
].filter(Boolean).join(';')
69+
70+
document.cookie = cookieOptions
71+
}, [signin])
72+
6073
if (router.query.type === 'lightning') {
6174
return <LightningAuthWithExplainer callbackUrl={callbackUrl} text={text} multiAuth={multiAuth} />
6275
}

pages/api/auth/[...nextauth].js

+6-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { hashEmail } from '@/lib/crypto'
1515
import * as cookie from 'cookie'
1616
import { multiAuthMiddleware } from '@/pages/api/graphql'
1717
import { BECH32_CHARSET } from '@/lib/constants'
18+
import { NodeNextRequest } from 'next/dist/server/base-http/node'
1819

1920
/**
2021
* Stores userIds in user table
@@ -94,6 +95,8 @@ function getCallbacks (req, res) {
9495
*/
9596
async jwt ({ token, user, account, profile, isNewUser }) {
9697
if (user) {
98+
// reset signup cookie if any
99+
res.appendHeader('Set-Cookie', cookie.serialize('signin', '', { path: '/', expires: 0, maxAge: 0 }))
97100
// token won't have an id on it for new logins, we add it
98101
// note: token is what's kept in the jwt
99102
token.id = Number(user.id)
@@ -205,7 +208,8 @@ async function pubkeyAuth (credentials, req, res, pubkeyColumnName) {
205208
if (token?.id && !multiAuth) {
206209
user = await prisma.user.update({ where: { id: token.id }, data: { [pubkeyColumnName]: pubkey } })
207210
} else {
208-
// we're not logged in: create new user with that pubkey
211+
// create a new user only if we're trying to sign up
212+
if (new NodeNextRequest(req).cookies.signin) return null
209213
user = await prisma.user.create({ data: { name: pubkey.slice(0, 10), [pubkeyColumnName]: pubkey } })
210214
}
211215
}
@@ -314,6 +318,7 @@ export const getAuthOptions = (req, res) => ({
314318
adapter: {
315319
...PrismaAdapter(prisma),
316320
createUser: data => {
321+
if (req.cookies.signin) return null
317322
// replace email with email hash in new user payload
318323
if (data.email) {
319324
const { email } = data

pages/login.js

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ export default function LoginPage (props) {
8181
<Login
8282
Footer={() => <LoginFooter callbackUrl={props.callbackUrl} />}
8383
Header={() => <LoginHeader />}
84+
signin
8485
{...props}
8586
/>
8687
</StaticLayout>

0 commit comments

Comments
 (0)