Skip to content

Commit

Permalink
fix bcrypt getting included in the client
Browse files Browse the repository at this point in the history
  • Loading branch information
kentcdodds committed Oct 6, 2023
1 parent 765f435 commit 6d158e0
Show file tree
Hide file tree
Showing 135 changed files with 205 additions and 139 deletions.
33 changes: 30 additions & 3 deletions exercises/04.password/03.problem.signup/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,36 @@

<EpicVideo url="https://www.epicweb.dev/workshops/authentication-strategies-and-implementation/password/enhancing-user-creation-by-adding-passwords/" />

👨‍💼 Let's create a password record when we create a new user so that can be used
when the user logs in. Jump into <InlineFile file="app/routes/_auth+/signup.tsx" />
and follow the emoji.
<callout-warning>
🦉 Our Remix routes are used to create both a client-side and a server-side
bundle. Remix is pretty good and splitting those things up for us, but using
modules that really should only be used on the server can potentially cause
issues.
</callout-warning>

You can read all about
[Server vs. Client Code Execution](https://remix.run/docs/en/main/discussion/server-vs-client)
in the Remix docs if you like. We're going to take advantage of Remix's feature
to explicitly label a module as server-only by creating a file with `.server` in
the name.

We don't want `bcryptjs` to appear in the client at all (it requires `crypto`
anyway). 🐨 So please
create <InlineFile file="app/utils/auth.server.ts" /> and stick this in there:

```tsx
import bcrypt from 'bcryptjs'

export { bcrypt }
```

Then in the client build `auth.server.ts` will be an empty module so none of the
`bcryptjs` code or `crypto` code will be included in the client bundle.

👨‍💼 Great! Thanks Olivia! Now, let's create a password record when we create a
new user so that can be used when the user logs in.
Jump into <InlineFile file="app/routes/_auth+/signup.tsx" /> and follow the
emoji.

Once you've done that, head to <LinkToApp to="/signup" /> and try signing up a
new account. It should allow you to sign in and then you can check the database
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { z } from 'zod'
import { CheckboxField, ErrorList, Field } from '#app/components/forms.tsx'
import { Spacer } from '#app/components/spacer.tsx'
import { StatusButton } from '#app/components/ui/status-button.tsx'
// 🐨 import bcrypt from your new #app/utils/auth.server.ts file here
import { validateCSRF } from '#app/utils/csrf.server.ts'
import { prisma } from '#app/utils/db.server.ts'
import { checkHoneypot } from '#app/utils/honeypot.server.ts'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import {
type MetaFunction,
} from '@remix-run/node'
import { Form, useActionData } from '@remix-run/react'
import bcrypt from 'bcryptjs'
import { AuthenticityTokenInput } from 'remix-utils/csrf/react'
import { HoneypotInputs } from 'remix-utils/honeypot/react'
import { z } from 'zod'
import { CheckboxField, ErrorList, Field } from '#app/components/forms.tsx'
import { Spacer } from '#app/components/spacer.tsx'
import { StatusButton } from '#app/components/ui/status-button.tsx'
import { bcrypt } from '#app/utils/auth.server.ts'
import { validateCSRF } from '#app/utils/csrf.server.ts'
import { prisma } from '#app/utils/db.server.ts'
import { checkHoneypot } from '#app/utils/honeypot.server.ts'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import bcrypt from 'bcryptjs'

export { bcrypt }
4 changes: 2 additions & 2 deletions exercises/05.login/01.problem.login/README.mdx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Login

<EpicVideo url="https://www.epicweb.dev/workshops/authentication-strategies-and-implementation/login/securing-ui-elements" />
<EpicVideo url="https://www.epicweb.dev/workshops/authentication-strategies-and-implementation/login/secure-password-authentication-with-bcrypt-compare-in-nodejs" />

👨‍💼 Let's verify the password now!

```ts
import bcrypt from 'bcryptjs'
import { bcrypt } from '#app/utils/auth.server.ts'

const isValid = await bcrypt.compare(password, hash)
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
import { ErrorList, Field } from '#app/components/forms.tsx'
import { Spacer } from '#app/components/spacer.tsx'
import { StatusButton } from '#app/components/ui/status-button.tsx'
// 🐨 import bcrypt from #app/utils/auth.server.ts
import { validateCSRF } from '#app/utils/csrf.server.ts'
import { prisma } from '#app/utils/db.server.ts'
import { checkHoneypot } from '#app/utils/honeypot.server.ts'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import {
type MetaFunction,
} from '@remix-run/node'
import { Form, useActionData } from '@remix-run/react'
import bcrypt from 'bcryptjs'
import { AuthenticityTokenInput } from 'remix-utils/csrf/react'
import { HoneypotInputs } from 'remix-utils/honeypot/react'
import { z } from 'zod'
import { CheckboxField, ErrorList, Field } from '#app/components/forms.tsx'
import { Spacer } from '#app/components/spacer.tsx'
import { StatusButton } from '#app/components/ui/status-button.tsx'
import { bcrypt } from '#app/utils/auth.server.ts'
import { validateCSRF } from '#app/utils/csrf.server.ts'
import { prisma } from '#app/utils/db.server.ts'
import { checkHoneypot } from '#app/utils/honeypot.server.ts'
Expand Down
3 changes: 3 additions & 0 deletions exercises/05.login/01.problem.login/app/utils/auth.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import bcrypt from 'bcryptjs'

export { bcrypt }
2 changes: 1 addition & 1 deletion exercises/05.login/01.solution.login/README.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Login

<EpicVideo url="https://www.epicweb.dev/workshops/authentication-strategies-and-implementation/login/securing-ui-elements/solution" />
<EpicVideo url="https://www.epicweb.dev/workshops/authentication-strategies-and-implementation/login/secure-password-authentication-with-bcrypt-compare-in-nodejs/solution" />

👨‍💼 Stellar! Now we can really be sure the user is who they say they are when
they log in. Next, let's add some utilities that will make it much easier to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import {
type MetaFunction,
} from '@remix-run/node'
import { Form, Link, useActionData } from '@remix-run/react'
import bcrypt from 'bcryptjs'
import { AuthenticityTokenInput } from 'remix-utils/csrf/react'
import { HoneypotInputs } from 'remix-utils/honeypot/react'
import { z } from 'zod'
import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
import { ErrorList, Field } from '#app/components/forms.tsx'
import { Spacer } from '#app/components/spacer.tsx'
import { StatusButton } from '#app/components/ui/status-button.tsx'
import { bcrypt } from '#app/utils/auth.server.ts'
import { validateCSRF } from '#app/utils/csrf.server.ts'
import { prisma } from '#app/utils/db.server.ts'
import { checkHoneypot } from '#app/utils/honeypot.server.ts'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import {
type MetaFunction,
} from '@remix-run/node'
import { Form, useActionData } from '@remix-run/react'
import bcrypt from 'bcryptjs'
import { AuthenticityTokenInput } from 'remix-utils/csrf/react'
import { HoneypotInputs } from 'remix-utils/honeypot/react'
import { z } from 'zod'
import { CheckboxField, ErrorList, Field } from '#app/components/forms.tsx'
import { Spacer } from '#app/components/spacer.tsx'
import { StatusButton } from '#app/components/ui/status-button.tsx'
import { bcrypt } from '#app/utils/auth.server.ts'
import { validateCSRF } from '#app/utils/csrf.server.ts'
import { prisma } from '#app/utils/db.server.ts'
import { checkHoneypot } from '#app/utils/honeypot.server.ts'
Expand Down
3 changes: 3 additions & 0 deletions exercises/05.login/01.solution.login/app/utils/auth.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import bcrypt from 'bcryptjs'

export { bcrypt }
2 changes: 1 addition & 1 deletion exercises/05.login/02.problem.ui-utils/README.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# UI Utils

<EpicVideo url="https://www.epicweb.dev/workshops/authentication-strategies-and-implementation/login/secure-password-authentication-with-bcrypt-compare-in-nodejs" />
<EpicVideo url="https://www.epicweb.dev/workshops/authentication-strategies-and-implementation/login/securing-ui-elements" />

👨‍💼 The user's information is something we'll want to access throughout the app
UI. So I want you to create a couple of handy utilities to help us do that.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import {
type MetaFunction,
} from '@remix-run/node'
import { Form, Link, useActionData } from '@remix-run/react'
import bcrypt from 'bcryptjs'
import { AuthenticityTokenInput } from 'remix-utils/csrf/react'
import { HoneypotInputs } from 'remix-utils/honeypot/react'
import { z } from 'zod'
import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
import { ErrorList, Field } from '#app/components/forms.tsx'
import { Spacer } from '#app/components/spacer.tsx'
import { StatusButton } from '#app/components/ui/status-button.tsx'
import { bcrypt } from '#app/utils/auth.server.ts'
import { validateCSRF } from '#app/utils/csrf.server.ts'
import { prisma } from '#app/utils/db.server.ts'
import { checkHoneypot } from '#app/utils/honeypot.server.ts'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import {
type MetaFunction,
} from '@remix-run/node'
import { Form, useActionData } from '@remix-run/react'
import bcrypt from 'bcryptjs'
import { AuthenticityTokenInput } from 'remix-utils/csrf/react'
import { HoneypotInputs } from 'remix-utils/honeypot/react'
import { z } from 'zod'
import { CheckboxField, ErrorList, Field } from '#app/components/forms.tsx'
import { Spacer } from '#app/components/spacer.tsx'
import { StatusButton } from '#app/components/ui/status-button.tsx'
import { bcrypt } from '#app/utils/auth.server.ts'
import { validateCSRF } from '#app/utils/csrf.server.ts'
import { prisma } from '#app/utils/db.server.ts'
import { checkHoneypot } from '#app/utils/honeypot.server.ts'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import bcrypt from 'bcryptjs'

export { bcrypt }
2 changes: 1 addition & 1 deletion exercises/05.login/02.solution.ui-utils/README.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# UI Utils

<EpicVideo url="https://www.epicweb.dev/workshops/authentication-strategies-and-implementation/login/secure-password-authentication-with-bcrypt-compare-in-nodejs/solution" />
<EpicVideo url="https://www.epicweb.dev/workshops/authentication-strategies-and-implementation/login/securing-ui-elements/solution" />

👨‍💼 Great! Now we have a nice utility for our UI to allow us to easily get the
user in any component and render things based on their authentication state.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import {
type MetaFunction,
} from '@remix-run/node'
import { Form, Link, useActionData } from '@remix-run/react'
import bcrypt from 'bcryptjs'
import { AuthenticityTokenInput } from 'remix-utils/csrf/react'
import { HoneypotInputs } from 'remix-utils/honeypot/react'
import { z } from 'zod'
import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
import { ErrorList, Field } from '#app/components/forms.tsx'
import { Spacer } from '#app/components/spacer.tsx'
import { StatusButton } from '#app/components/ui/status-button.tsx'
import { bcrypt } from '#app/utils/auth.server.ts'
import { validateCSRF } from '#app/utils/csrf.server.ts'
import { prisma } from '#app/utils/db.server.ts'
import { checkHoneypot } from '#app/utils/honeypot.server.ts'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import {
type MetaFunction,
} from '@remix-run/node'
import { Form, useActionData } from '@remix-run/react'
import bcrypt from 'bcryptjs'
import { AuthenticityTokenInput } from 'remix-utils/csrf/react'
import { HoneypotInputs } from 'remix-utils/honeypot/react'
import { z } from 'zod'
import { CheckboxField, ErrorList, Field } from '#app/components/forms.tsx'
import { Spacer } from '#app/components/spacer.tsx'
import { StatusButton } from '#app/components/ui/status-button.tsx'
import { bcrypt } from '#app/utils/auth.server.ts'
import { validateCSRF } from '#app/utils/csrf.server.ts'
import { prisma } from '#app/utils/db.server.ts'
import { checkHoneypot } from '#app/utils/honeypot.server.ts'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import bcrypt from 'bcryptjs'

export { bcrypt }
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import {
type MetaFunction,
} from '@remix-run/node'
import { Form, Link, useActionData } from '@remix-run/react'
import bcrypt from 'bcryptjs'
import { AuthenticityTokenInput } from 'remix-utils/csrf/react'
import { HoneypotInputs } from 'remix-utils/honeypot/react'
import { z } from 'zod'
import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
import { ErrorList, Field } from '#app/components/forms.tsx'
import { Spacer } from '#app/components/spacer.tsx'
import { StatusButton } from '#app/components/ui/status-button.tsx'
import { bcrypt } from '#app/utils/auth.server.ts'
import { validateCSRF } from '#app/utils/csrf.server.ts'
import { prisma } from '#app/utils/db.server.ts'
import { checkHoneypot } from '#app/utils/honeypot.server.ts'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import {
type MetaFunction,
} from '@remix-run/node'
import { Form, useActionData } from '@remix-run/react'
import bcrypt from 'bcryptjs'
import { AuthenticityTokenInput } from 'remix-utils/csrf/react'
import { HoneypotInputs } from 'remix-utils/honeypot/react'
import { z } from 'zod'
import { CheckboxField, ErrorList, Field } from '#app/components/forms.tsx'
import { Spacer } from '#app/components/spacer.tsx'
import { StatusButton } from '#app/components/ui/status-button.tsx'
import { bcrypt } from '#app/utils/auth.server.ts'
import { validateCSRF } from '#app/utils/csrf.server.ts'
import { prisma } from '#app/utils/db.server.ts'
import { checkHoneypot } from '#app/utils/honeypot.server.ts'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import bcrypt from 'bcryptjs'

export { bcrypt }
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import {
type MetaFunction,
} from '@remix-run/node'
import { Form, Link, useActionData } from '@remix-run/react'
import bcrypt from 'bcryptjs'
import { AuthenticityTokenInput } from 'remix-utils/csrf/react'
import { HoneypotInputs } from 'remix-utils/honeypot/react'
import { z } from 'zod'
import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
import { ErrorList, Field } from '#app/components/forms.tsx'
import { Spacer } from '#app/components/spacer.tsx'
import { StatusButton } from '#app/components/ui/status-button.tsx'
import { bcrypt } from '#app/utils/auth.server.ts'
import { validateCSRF } from '#app/utils/csrf.server.ts'
import { prisma } from '#app/utils/db.server.ts'
import { checkHoneypot } from '#app/utils/honeypot.server.ts'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import {
type MetaFunction,
} from '@remix-run/node'
import { Form, useActionData } from '@remix-run/react'
import bcrypt from 'bcryptjs'
import { AuthenticityTokenInput } from 'remix-utils/csrf/react'
import { HoneypotInputs } from 'remix-utils/honeypot/react'
import { z } from 'zod'
import { CheckboxField, ErrorList, Field } from '#app/components/forms.tsx'
import { Spacer } from '#app/components/spacer.tsx'
import { StatusButton } from '#app/components/ui/status-button.tsx'
import { bcrypt } from '#app/utils/auth.server.ts'
import { validateCSRF } from '#app/utils/csrf.server.ts'
import { prisma } from '#app/utils/db.server.ts'
import { checkHoneypot } from '#app/utils/honeypot.server.ts'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import bcrypt from 'bcryptjs'

export { bcrypt }
4 changes: 2 additions & 2 deletions exercises/06.logout/02.problem.expiration/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ expiration (you can configure the
session storage object to have an expiration). Instead, we need to set the
expiration when we commit the session in the login and signup routes.

🐨 To promote reusability, let's create a variable in a new
file <InlineFile file="app/utils/auth.server.ts" /> called
🐨 To promote reusability, let's create a variable
in <InlineFile file="app/utils/auth.server.ts" /> called
`SESSION_EXPIRATION_TIME` that's set to 30 days in milliseconds which is
`1000 * 60 * 60 * 24 * 30`. You can then make a `getSessionExpirationDate` which
returns a new date that is `Date.now() + SESSION_EXPIRATION_TIME`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import {
type MetaFunction,
} from '@remix-run/node'
import { Form, Link, useActionData } from '@remix-run/react'
import bcrypt from 'bcryptjs'
import { AuthenticityTokenInput } from 'remix-utils/csrf/react'
import { HoneypotInputs } from 'remix-utils/honeypot/react'
import { z } from 'zod'
import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
import { CheckboxField, ErrorList, Field } from '#app/components/forms.tsx'
import { Spacer } from '#app/components/spacer.tsx'
import { StatusButton } from '#app/components/ui/status-button.tsx'
import { bcrypt } from '#app/utils/auth.server.ts'
import { validateCSRF } from '#app/utils/csrf.server.ts'
import { prisma } from '#app/utils/db.server.ts'
import { checkHoneypot } from '#app/utils/honeypot.server.ts'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import {
type MetaFunction,
} from '@remix-run/node'
import { Form, useActionData } from '@remix-run/react'
import bcrypt from 'bcryptjs'
import { AuthenticityTokenInput } from 'remix-utils/csrf/react'
import { HoneypotInputs } from 'remix-utils/honeypot/react'
import { z } from 'zod'
import { CheckboxField, ErrorList, Field } from '#app/components/forms.tsx'
import { Spacer } from '#app/components/spacer.tsx'
import { StatusButton } from '#app/components/ui/status-button.tsx'
import { bcrypt } from '#app/utils/auth.server.ts'
import { validateCSRF } from '#app/utils/csrf.server.ts'
import { prisma } from '#app/utils/db.server.ts'
import { checkHoneypot } from '#app/utils/honeypot.server.ts'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import bcrypt from 'bcryptjs'

export { bcrypt }

// 🐨 create a SESSION_EXPIRATION_TIME variable here
// 🐨 export a simple function that returns a new date that's the current time plus the SESSION_EXPIRATION_TIME
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@ import {
type MetaFunction,
} from '@remix-run/node'
import { Form, Link, useActionData } from '@remix-run/react'
import bcrypt from 'bcryptjs'
import { AuthenticityTokenInput } from 'remix-utils/csrf/react'
import { HoneypotInputs } from 'remix-utils/honeypot/react'
import { z } from 'zod'
import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
import { CheckboxField, ErrorList, Field } from '#app/components/forms.tsx'
import { Spacer } from '#app/components/spacer.tsx'
import { StatusButton } from '#app/components/ui/status-button.tsx'
import { getSessionExpirationDate } from '#app/utils/auth.server.ts'
import { bcrypt, getSessionExpirationDate } from '#app/utils/auth.server.ts'
import { validateCSRF } from '#app/utils/csrf.server.ts'
import { prisma } from '#app/utils/db.server.ts'
import { checkHoneypot } from '#app/utils/honeypot.server.ts'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ import {
type MetaFunction,
} from '@remix-run/node'
import { Form, useActionData } from '@remix-run/react'
import bcrypt from 'bcryptjs'
import { AuthenticityTokenInput } from 'remix-utils/csrf/react'
import { HoneypotInputs } from 'remix-utils/honeypot/react'
import { z } from 'zod'
import { CheckboxField, ErrorList, Field } from '#app/components/forms.tsx'
import { Spacer } from '#app/components/spacer.tsx'
import { StatusButton } from '#app/components/ui/status-button.tsx'
import { getSessionExpirationDate } from '#app/utils/auth.server.ts'
import { bcrypt, getSessionExpirationDate } from '#app/utils/auth.server.ts'
import { validateCSRF } from '#app/utils/csrf.server.ts'
import { prisma } from '#app/utils/db.server.ts'
import { checkHoneypot } from '#app/utils/honeypot.server.ts'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
export const SESSION_EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30
import bcrypt from 'bcryptjs'

export { bcrypt }

const SESSION_EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30
export const getSessionExpirationDate = () =>
new Date(Date.now() + SESSION_EXPIRATION_TIME)
Loading

0 comments on commit 6d158e0

Please sign in to comment.