Next.js Fetch Data the Right Way (with a Data Access Layer!) (Security, Auth, Cache, DTO)

ByteGrad
2 Sept 202424:18

Summary

TLDRThis video explores the latest Next.js app router and React Server Components, discussing how they blur the line between server and client. It emphasizes the importance of a data access layer for security, especially when dealing with authentication and database interactions. The tutorial demonstrates using a data access layer to ensure that authentication checks are performed before database access, preventing unauthorized data access. It also touches on best practices like using the cache function to avoid duplicate database calls and the server-only package for added security. The video is sponsored by Kind, which provides an easy solution for authentication and authorization in Next.js applications.

Takeaways

  • πŸ˜€ The latest Next.js app router has introduced significant changes, blurring the line between server and client components.
  • πŸ” Security is paramount, especially when dealing with data. It's crucial to implement authentication checks before interacting with the database.
  • πŸ“š An article by Sebastian Markbager recommends using a 'data access layer' for new Next.js projects to enhance security and structure.
  • πŸ—οΈ React server components allow for fetching data directly within the component, necessitating careful handling to ensure security.
  • 🚫 The risk of exposing sensitive data arises when components fetching data are reused in different parts of the application without proper authentication checks.
  • πŸ”‘ Using middleware or page-level checks alone is insufficient to protect data; a more robust solution is needed.
  • πŸ›‘οΈ A data access layer centralizes data interactions and authentication logic, reducing the risk of accidental exposure of sensitive data.
  • πŸ‘₯ The structure supports better teamwork by allowing backend developers to focus on data access and frontend developers to utilize the data.
  • πŸ”„ React's cache function can prevent duplicate database calls when the same data is accessed from different components.
  • πŸ› οΈ Using a data transfer object (DTO) allows for filtering out sensitive fields and transforming data into the desired shape before it's used in the application.

Q & A

  • What is the main focus of the video script?

    -The main focus of the video script is discussing the changes in Next.js app router and how to structure Next.js applications securely, particularly with the introduction of React Server Components.

  • Why is a data access layer recommended in Next.js applications?

    -A data access layer is recommended to ensure that authentication checks are performed before interacting with the database, centralizing data access logic and making the application more secure.

  • What is the problem with accessing data directly in components without a data access layer?

    -Accessing data directly in components without a data access layer can lead to security risks, as there is no guarantee that authentication checks are performed before data is fetched, potentially exposing sensitive data.

  • How does the introduction of React Server Components change the way data is accessed in Next.js applications?

    -React Server Components allow for fetching data directly within the component using async/await, which changes the data access pattern and necessitates a more secure approach like a data access layer.

  • What role does the authentication solution 'Kind' play in the video script?

    -In the video script, 'Kind' is used as an authentication solution to protect pages and ensure that only authenticated users can access certain data or routes in the Next.js application.

  • Why is it important to perform authentication checks before database interactions?

    -Performing authentication checks before database interactions is important to prevent unauthorized access to sensitive data, ensuring that only authenticated users can view or manipulate the data.

  • What is the significance of the data access layer in team-based development?

    -In team-based development, the data access layer helps in dividing responsibilities, allowing backend developers to focus on database interactions while frontend developers use these interactions in the application.

  • How can the data access layer help in maintaining security throughout the application?

    -The data access layer helps maintain security by centralizing authentication and authorization logic, ensuring that all database interactions go through a secure and consistent process.

  • What are some benefits of using a data access layer in Next.js applications?

    -Benefits of using a data access layer include improved security, easier management of authentication and authorization logic, better organization of code, and a clear separation of concerns in team-based development.

  • How can the data access layer help in reducing duplicate database calls in a Next.js application?

    -The data access layer can help in reducing duplicate database calls by centralizing data fetching logic, allowing for caching mechanisms and ensuring that data is fetched only when necessary.

Outlines

00:00

πŸ› οΈ Structuring Next.js Applications for Security

The paragraph discusses the evolution of Next.js app router and the importance of structuring applications securely. It highlights the blurring line between server and client components with React server components and the necessity of a data access layer for security. The speaker introduces the concept of protecting data by ensuring authentication checks before database interactions. An example is given where only authenticated users can view certain content, and the potential risks of reusing components without proper authentication checks are explored. The paragraph concludes by emphasizing the need for a secure architecture that prevents unauthorized data access.

05:00

πŸ” Implementing Authentication with Kind

This section details the process of setting up authentication using Kind, a sponsor of the video. The speaker, who is a brand ambassador for Kind, walks through adding authentication to a Next.js application. The steps include creating an application in Kind, configuring callback URLs, installing the Kind Next.js package, setting environment variables, and adding an API endpoint. The speaker demonstrates how to protect a page by checking the authentication status using Kind's `getServerSession` and redirecting unauthenticated users. The video also shows how to configure Kind for GitHub authentication and ensure that only authenticated users can access protected pages.

10:00

πŸ“š Introducing the Data Access Layer

The paragraph introduces the concept of a data access layer as a solution to the problem of securing data access in Next.js applications. It explains the risks of having unprotected data access points in components that could be reused in different parts of an application, potentially leading to security vulnerabilities. The speaker advocates for a centralized approach to database interactions, where all data fetching is done through a dedicated layer that ensures authentication checks are performed before any data is accessed. This approach is contrasted with the potential issues of scattered data access points throughout the application code.

15:02

πŸ›‘οΈ Securing Data with a Data Access Layer

This section delves deeper into the practical implementation of a data access layer. The speaker demonstrates how to create a centralized folder for data access, with specific functions for each database interaction, such as fetching or updating articles. The benefits of this approach include ensuring that authentication checks are consistently performed before database access, regardless of where the data is needed in the application. The paragraph also touches on the advantages of this structure for team collaboration, security audits, and the ability to easily update authentication or authorization logic in one place.

20:03

πŸ”— Best Practices for Data Handling in Next.js

The final paragraph discusses best practices for handling data in Next.js applications, building on the data access layer concept. It covers the use of React's `cache` function to prevent duplicate database calls when the same data is accessed from different components. The speaker also mentions the use of the `server-only` package to ensure that data access layer functions are only usable on the server side. Additional security practices are highlighted, such as selecting only necessary fields from the database and creating data transfer objects (DTOs) to filter out sensitive information and transform data into the desired shape for application use. The paragraph concludes by emphasizing the importance of these practices in maintaining a secure and efficient Next.js application.

Mindmap

Keywords

πŸ’‘Next.js

Next.js is a popular React framework that enables functionality such as server-side rendering and generating static websites. In the context of the video, Next.js is used to build a web application with a focus on the latest features of its app router, which blurs the line between server and client-side rendering.

πŸ’‘React Server Components

React Server Components are a feature that allows components to be rendered on the server, which can improve performance and security. The video discusses how these components change the way developers structure their Next.js applications, allowing for direct data fetching within the component itself.

πŸ’‘Data Access Layer

A data access layer is a concept in software design where a centralized component handles all interactions with the database. The video emphasizes the importance of using a data access layer for security reasons, ensuring that authentication checks are performed before any data is accessed, which is recommended for new Next.js projects.

πŸ’‘Authentication

Authentication is the process of verifying the identity of a user. The video discusses implementing authentication with Next.js using a service called 'Kind', which is used to check if a user is logged in before allowing access to certain pages or data, ensuring that only authorized users can view or manipulate protected content.

πŸ’‘Middleware

Middleware in Next.js refers to functions that have access to the request and response objects and can either end the request-response cycle or call the next middleware function. The video mentions using middleware for route protection, but cautions that it's not enough on its own to secure data access.

πŸ’‘Prisma

Prisma is an ORM (Object-Relational Mapping) tool that simplifies database interactions in web applications. The script uses Prisma to illustrate how data is fetched from a database within Next.js server components, and how it should be done within a data access layer for security purposes.

πŸ’‘Server Actions

Server Actions in Next.js are a way to perform actions on the server in response to client-side events. The video points out that while server actions are tied to a specific page route, they can be misused if not properly protected, leading to potential security gaps.

πŸ’‘Reusability

Reusability in software development refers to the ability to use a component or piece of code in different parts of an application or in different projects. The video discusses the risk of reusing data-fetching components without proper authentication checks, which can lead to security vulnerabilities.

πŸ’‘Security Best Practices

Security best practices are guidelines and procedures aimed at preventing security breaches. The video highlights several security best practices, such as using a data access layer, ensuring authentication before data access, and using tools like 'Kind' for managing authentication and authorization.

πŸ’‘Data Transfer Object (DTO)

A Data Transfer Object is a design pattern used to transfer data between processes. In the video, the concept is used to shape and filter data from the database before it's used in the application, ensuring that only necessary and non-sensitive data is exposed to the rest of the application.

πŸ’‘Cache Function

The cache function in React is used to prevent unnecessary re-renders of components. The video suggests using React's cache function to optimize data fetching, ensuring that database calls are not duplicated when data is accessed from multiple components.

Highlights

Next.js app router has undergone significant changes, blurring the line between server and client with React Server Components.

Security in Next.js is emphasized, with a recommendation to use a data access layer for new projects.

Authentication checks should precede database interactions to ensure data security.

React Server Components allow for fetching data directly within the component, changing the traditional approach.

The potential risk of reusing components that fetch data without authentication checks can lead to security vulnerabilities.

Middleware can be used in Next.js for route protection, but it doesn't secure data access within components.

Introducing a data access layer centralizes data interactions and ensures authentication checks are performed.

The data access layer concept is beneficial for security, reusability, and team collaboration.

Using a data access layer helps prevent unauthorized data access, even when components are reused in different parts of the application.

Authentication and authorization logic can be consolidated in the data access layer for easier maintenance.

The data access layer is not an external API but an internal application structure for safe data handling.

Prisma is used as an example of an ORM for database interactions within the data access layer.

The data access layer can help in logging database access and conducting security audits.

React's cache function can prevent duplicate database calls when the same data is accessed from different components.

The server-only package can be used to ensure that data access layer functions are not accidentally used on the client side.

Selecting specific fields from the database can minimize the exposure of sensitive data.

Data Transformation and creation of Data Transfer Objects (DTOs) can shape data for specific application needs.

Centralizing data access logic makes it easier to update the application in response to changes in database schema.

Kind is recommended for handling authentication and authorization, simplifying what was once a complex problem.

The video concludes with a call to action for viewers to consider implementing a data access layer in their Next.js projects.

Transcripts

play00:00

a lot of things have changed in the

play00:01

latest nextjs app router so with react

play00:04

server components the line between

play00:06

server and client have blurred and many

play00:08

other things have changed so in this

play00:10

video I want to talk about how to

play00:12

structure or how to architect your

play00:14

nextjs applications so this is actually

play00:16

a wonderful article about Security in

play00:18

nextjs by Sebastian markager and this is

play00:22

an article about Security in nextjs and

play00:24

here you can see they actually recommend

play00:27

using a so-called data access layer for

play00:30

your new project in this video I'll show

play00:31

you what that means but for example we

play00:33

want to make sure that we do an

play00:35

authentication check before we actually

play00:37

interact with our database and there's a

play00:39

certain way that we can structure our

play00:41

application make sure we do that so

play00:42

what's the problem why do we need

play00:44

something fancy like a data access layer

play00:46

what even is that well let's say we have

play00:48

a very simple project I just have a

play00:50

homepage here and that's what we have

play00:53

here H1 and read an article right so

play00:55

this whole project just has one article

play00:58

I can go to the article page and here I

play01:00

have some text this is actually data

play01:03

right when it comes to security what do

play01:05

we want to protect what do we want to

play01:06

secure it's our data right our data is

play01:08

the most important part if we render the

play01:11

wrong button or the markup isn't right

play01:13

that's not the end of the world

play01:14

typically but if this article text

play01:17

specifically if this should only be

play01:18

viewable for logged in users maybe even

play01:21

paid users then we want to make sure

play01:23

that this text here cannot be read by

play01:25

guest users or free users um so what I'm

play01:27

doing here is I'm using a react server

play01:29

comp components right this is a page

play01:31

component and by default everything in

play01:33

the nexts rter is essentially a server

play01:36

component I can do async await and this

play01:38

is how you get data in the idiomatic way

play01:40

in the latest next chance app router

play01:42

right you can do it directly here in the

play01:43

server component you don't need use

play01:45

effect you don't need an API route or

play01:47

route Handler either you also don't need

play01:49

a server action you can do it directly

play01:51

like this okay so in my database I just

play01:53

have one article I'm using Prisma here

play01:55

and you can see here in my database I

play01:57

just have this one simple article here

play01:59

that is what I'm getting and that is the

play02:00

text that I'm showing here so that's

play02:02

what we have so far now what's the

play02:03

problem with this so we want to make

play02:05

sure that only logged in users let's say

play02:06

can actually read this text so what you

play02:09

could do is simply add some protection

play02:11

to this whole page right so you could

play02:13

use an authentication solution so we're

play02:15

going to use kind in this video they are

play02:16

today sponsor and they have in my view a

play02:19

great solution for authentication the

play02:21

way it works with kind is you can do

play02:22

something like this and now when this

play02:24

page loads we're first going to do an

play02:26

authentication check right so then

play02:27

before you even get anything from the

play02:29

database you first have the O check in

play02:31

this case this would work but with react

play02:33

server components we can also fetch data

play02:36

in another component right so here we

play02:38

were fetching the data uh right here in

play02:40

the article page but maybe we are

play02:42

fetching that in some component maybe we

play02:45

have a dedicated component for the text

play02:47

right which actually kind of makes sense

play02:49

and in there we do the data fetching and

play02:51

we then return the actual text right so

play02:53

then we would use that component right

play02:55

every react developer has components on

play02:57

their mind so maybe you or somebody else

play03:00

on your team structures it like this

play03:02

where you actually access the data in a

play03:04

separate component now this is risky

play03:06

with server components because now it's

play03:09

still protected right we're still first

play03:11

doing the authentication check before we

play03:13

render this component and before we

play03:15

actually get the data from the database

play03:17

but what react developers also have

play03:20

front of mind is reusability so what if

play03:23

somebody on your team reuses this

play03:25

component on the homepage let's say

play03:27

right so maybe somebody's going to use

play03:29

it on the homepage

play03:30

here we do not have an authentication

play03:31

check so now if I go to the homepage I

play03:34

can view this data or whatever which is

play03:38

not what we

play03:44

want and by the way it doesn't matter

play03:47

how you protect your pages whether it's

play03:49

actually like this in a page component

play03:51

or instead maybe you're using middleware

play03:53

we can also use middleware with kind

play03:54

right it would look something like this

play03:56

they have the width off and we want to

play03:58

run this on the/ article route but this

play04:00

only protects the SL article route but I

play04:03

just added this component on a on the

play04:05

homepage which is a public route right

play04:07

so here we are still accessing that well

play04:09

what should be private data right so it

play04:12

doesn't matter what way of protecting

play04:14

you use as long as there is a gap

play04:16

between where you do the authentication

play04:18

and where you actually access data from

play04:20

your database there is a gap and that

play04:22

Gap allows for well potentially

play04:25

dangerous and here I showed you an

play04:27

example of getting data but this problem

play04:29

also also is with updating data with

play04:31

server actions right so server actions

play04:33

are the idiomatic way of updating data

play04:35

now server actions they live on the page

play04:38

the route on which you're using them so

play04:40

if you're using a server action on the/

play04:42

article route you may think oh

play04:44

middleware I'm going to protect the SL

play04:45

article route so the the server action

play04:47

I'm using there is going to be protected

play04:49

well what if somebody's using that

play04:50

server action on a public route on the

play04:52

homepage let's say right so this way of

play04:55

protecting your app at the middleware

play04:57

level or at the page level like that is

play05:00

this is not enough and so instead you

play05:01

may want to use a data access layer now

play05:04

before I show you the solution I quickly

play05:06

removed what we just did and I quickly

play05:08

will show you how to setup kind and then

play05:10

we'll take a look at the data access

play05:12

layer we don't even have any kind of

play05:14

authentication right so everybody can

play05:15

just go here it's a public page right

play05:17

now so we need to add some

play05:18

authentication so let's start there and

play05:20

then I'll show you how to structure it

play05:22

so I'm going to use kind for the

play05:23

authentication they are today sponsor

play05:25

and I'm actually a brand ambassador for

play05:27

them it's a paid sponsorship but I had a

play05:28

great time working with them so far and

play05:30

they have a very generous free tier as

play05:32

well you can find a link in the

play05:33

description if you want to sign up right

play05:35

now if you sign up you can easily add an

play05:37

application I will quickly add

play05:38

authentication with them so you can see

play05:40

how that works but everything that we're

play05:41

going to talk about here also works with

play05:43

any other authentication solution you

play05:45

may be using so here I just need to

play05:47

quickly add uh some name I'll call it

play05:48

nextjs app a backend web here nextjs is

play05:52

very backend heavy so it's actually more

play05:54

of a backend framework so here they have

play05:56

a template here for nextjs okay easy all

play05:59

right so so then here they show you

play06:00

exactly existing codebase how to

play06:03

implement this so yes it's running on

play06:05

Local Host 3000 I just have to set these

play06:07

to call back URLs here in kind boom boom

play06:11

all right then I can install their next

play06:12

JS package can just copy and paste that

play06:15

right here all right and then let's see

play06:17

we need to add some environment

play06:19

variables I'm going to quickly create.

play06:22

logo and just paste that right here and

play06:24

actually here after logging in where do

play06:27

we want to redirect the user well in

play06:28

this case let's actually redirect them

play06:30

to that article page so that's the only

play06:32

thing I will change here all right so

play06:33

then last step here we need to add the

play06:35

API endpoint so that kind can internally

play06:38

wire everything up and actually I should

play06:40

be able to just copy the path and then

play06:42

here I should be able to create a new

play06:45

file by just pasting everything like

play06:47

this yeah and here we need to just copy

play06:50

and paste that right here all right so

play06:52

that's all we need to do to add

play06:53

authentication to our nextjs app with

play06:56

kind and then here they show you log in

play06:58

and log out buttons we're not going to

play07:00

use that here but we do want to protect

play07:01

this article page now so what we can do

play07:04

with kind we can go to that page so what

play07:06

we can do is if we want to protect this

play07:08

article page well when it renders we can

play07:10

simply check the authentication status

play07:12

of the user so kind gives us this get

play07:15

kind server session that we can use

play07:17

everywhere on the server side this is a

play07:18

server component so we can use it it

play07:20

will give us an is authenticated

play07:22

function actually so I do need to call

play07:24

it here so if the user is not

play07:25

authenticated we are going to redirect

play07:27

them to that API route so kind can take

play07:30

care of logging the user in and if the

play07:32

user is authenticated we continue here

play07:34

and we actually are going to make that

play07:36

fetch call to our database through our

play07:39

omm us using Prisma here but works

play07:41

similarly for other OMS and that will

play07:43

give us some data here and so we can

play07:46

just take it text and that's what we

play07:48

would see then now here I'm actually

play07:49

already being redirected here so if I

play07:51

click on read article I'm not logged in

play07:53

so indeed I should be redirected right

play07:55

and indeed kind is redirecting me to a

play07:57

login page now here we do need to

play07:59

specify how we want the user to log in

play08:02

so we can go to authentication here and

play08:04

kind gives us these options now what we

play08:06

want to use is just GitHub here I'm

play08:08

going to save that now if I try going to

play08:10

that article page again all right so

play08:11

here we have continue with GitHub I'll

play08:13

quickly log in and now here I'm

play08:15

redirected now if I go to inspect here

play08:17

under cookies and if I go here yeah so

play08:19

here under access token I can see my so

play08:22

I'm logged in and therefore I can see

play08:23

the article page with that well

play08:25

protected data right that's why I can

play08:27

now see this right so this is a very

play08:29

quick way of securing our page for only

play08:31

logged in users you don't want to do it

play08:33

in layout right so if you watch my other

play08:36

videos on authentication in nextjs you

play08:38

know that you typically don't want to

play08:40

add it to the layout here um it's very

play08:42

tempting to do this if you want to

play08:43

protect your whole app right because you

play08:45

think uh instead of doing it in every

play08:46

page we're just going to do it once in

play08:48

the layout but that will not work as

play08:50

expected because the layout here will

play08:51

not do it's not going to run this if you

play08:54

for example uh click on this link like

play08:56

here when we navigate here it's not

play08:58

going to read do the check for the

play09:00

article page so you don't want to do it

play09:02

in layout you want to do it either in

play09:04

the page component or you can also

play09:06

create a middleware they both have

play09:08

certain advantages let's say we do it

play09:10

like this now what's the problem with

play09:11

this I have now properly protected them

play09:13

so what's the issue with

play09:16

this you can see we get the same result

play09:19

but we have just refactored this a

play09:21

little bit so we have a dedicated

play09:23

component for the text and in a real

play09:25

next CH app you could very well have a

play09:27

separate component where you actually

play09:28

get the data and this is the important

play09:31

part because now there is more of a gap

play09:34

right so here now we are doing the

play09:36

authentication check but where we

play09:38

actually access the database is now in a

play09:40

separate place and it's in a separate

play09:42

component here and so so far so good but

play09:45

react developers also have reusability

play09:48

at the top of their mind right so there

play09:50

could be you or some other developer on

play09:52

your team could accidentally perhaps use

play09:55

this component on the homepage right so

play09:58

I could also use text here on the

play10:00

homepage uh if I do it here on the

play10:02

homepage we now have this text here on

play10:04

the homepage so even if I log myself out

play10:07

by clearing all of my cookies here so I

play10:10

don't have the token anymore since the

play10:12

homepage is not protected right we don't

play10:15

have any authentication check here and

play10:17

I'm not logged in I can still read this

play10:19

right so this text here this piece of

play10:21

data that we have that should be

play10:23

protected is not protected right now

play10:25

right now the article page is still

play10:27

properly protected but the homepage is

play10:29

is public so if you use that component

play10:31

on the homepage right so it doesn't

play10:33

matter if you use middleware or you do

play10:34

the authentication check directly in the

play10:37

page right let's stick to the page for

play10:39

this tutorial this problem exists with

play10:41

both approaches I have other videos also

play10:43

with kind when to do the authentication

play10:44

check in the page or when in middleware

play10:47

it depends a little bit on your setup

play10:49

but uh let's continue with doing it in

play10:50

the page for this video so how do we fix

play10:53

this how can we prevent this so this is

play10:55

where the concept of a data access layer

play10:58

comes into play so what we want to do is

play11:00

we want to have one centralized place or

play11:03

layer in our application where we

play11:06

interact with our database right so our

play11:08

data so what you could do is you could

play11:10

create a folder here for all your data

play11:13

access right we can actually just call

play11:15

it data access and in here we can create

play11:18

a file uh here is this is going to be

play11:20

for the Articles right so for the

play11:22

article table in our database let's say

play11:25

and here I will have all of the ways

play11:27

that I'm going to interact with my

play11:30

article data so here I could export a

play11:32

function that I can just call get

play11:34

article right I could accept some ID or

play11:36

something like that but let's keep it

play11:38

simple and here is where I'm going to

play11:40

get the data right so what we were doing

play11:42

previously somewhere in you know

play11:44

somewhere in our application somewhere

play11:46

in our component tree we now know for

play11:49

sure that all of the data is going to

play11:51

come from here I will just return that

play11:54

from here this one function is going to

play11:57

be responsible for getting the article

play11:59

all of the data access is going to be in

play12:01

here so this is for getting an article

play12:03

maybe we we are going to have one for

play12:06

update article right all of your CR

play12:08

delete article we can right these are

play12:11

not empty but you get the point all of

play12:13

the interactions with your database

play12:15

you're going to create functions in here

play12:18

you can also do it with a class if

play12:19

you're a backend developer you may

play12:21

already be familiar with the concept of

play12:22

a data access layer but a lot of you are

play12:24

actually coming from the front end world

play12:26

so basically what we're doing here is

play12:27

we're creating a centralized place where

play12:29

we do all the data access basically all

play12:31

our interactions with our database so

play12:34

now whenever you need data in your

play12:35

application somewhere you're not going

play12:37

to randomly do that in some component

play12:40

right so here we're not going to get the

play12:41

article data from here now because we

play12:43

have one function now for getting the

play12:45

article and so whenever we need to get

play12:47

an article we're going to use that

play12:48

function right so now if I want to get

play12:50

article data I can say article data and

play12:53

now I need to use that function right

play12:55

get article I should import that and I

play12:57

get a rest quickly line here by the way

play12:58

because Prisma tells me it could also be

play13:00

null right I may have deleted it in the

play13:02

database I'm ignoring that here but I

play13:05

can remove Prisma now from here right so

play13:07

now I can access this data in the text

play13:09

component now since we're always going

play13:11

to use this function now when we need to

play13:13

get an article we can do the

play13:15

authentication check in here so we can

play13:17

just do all of this with kind right here

play13:20

right so you first do the off check and

play13:22

then you interact with the database and

play13:25

the benefit is now I can safely use this

play13:28

get article function function wherever I

play13:29

want whether it's in this component or

play13:32

in some other component and I can be

play13:34

rest assured that the authentication

play13:36

check is always being done because

play13:38

there's no Gap now between the

play13:39

authentication check and the place where

play13:41

I'm accessing my database right there's

play13:43

no Gap in here they right after each

play13:45

other they're right in the same function

play13:47

so that is in essence the benefit of

play13:49

using a data access layer it's safer in

play13:52

my view because now whenever I need to

play13:54

get a article I just use that one

play13:55

function which takes care of all the

play13:57

authentication and potentially

play13:59

authorization logic so I can now more

play14:01

comfortably uh work here in my

play14:03

application now I may still want to have

play14:06

a page level check as well maybe more of

play14:08

a as a convenience perhaps as a way to

play14:11

quickly do some redirections at a page

play14:13

level let's say um or just to see what

play14:16

what pages should be uh public or

play14:18

private and so that would be like your

play14:19

first line of defense whether you're

play14:21

doing some kind of page level check or

play14:23

middleware check that would be like your

play14:25

first line of defense and then in

play14:27

addition to that whenever you need to

play14:29

get access to a piece of data in this

play14:31

case you know a particular article it

play14:33

could be other data that you have you're

play14:34

going to create a separate function for

play14:36

that in your data access layer right

play14:38

basically just one file right now in

play14:41

which you also do the authentication

play14:42

check so that you're always certain that

play14:45

the act the interaction with database is

play14:47

safe and data access layer is not an API

play14:50

or or an external API or something like

play14:52

that right so you may be inclined to use

play14:54

like a DAT an API layer to fix that

play14:56

issue but that's not necessary when

play14:58

you're using an API you're actually

play14:59

going over the network there are other

play15:01

complications that come from that

play15:03

instead we can just structure our

play15:05

application code slightly differently so

play15:07

that every interaction with your

play15:08

database is now going to be in this one

play15:10

folder let's say this is just we can

play15:12

call it a layer you can call it however

play15:14

you want and we could have one file per

play15:16

uh table or schema in our database right

play15:19

so here I'm using Prisma and here I just

play15:21

have this one model for article this

play15:23

will create one table in my database and

play15:25

so you may want to have one file for

play15:28

each one you have and in this case I

play15:29

only have article and so here you would

play15:31

do your authentication check right

play15:33

before the actual database call and we

play15:35

would do the same for the other

play15:37

potential functions here right so if you

play15:38

want to update the article maybe you

play15:40

would have some kind of database call

play15:41

like this maybe you pass in an ID or

play15:43

something like that but here again you

play15:45

would first do your authentication check

play15:47

before you interact with the database

play15:48

and now wherever in your app where you

play15:50

need to update the article you need to

play15:52

make sure that you only use this

play15:54

function and then you can be rest

play15:55

assured that there's always the

play15:57

authentication check first right so now

play15:59

only logged in users can update an

play16:01

article you know realistically you're

play16:02

going to have other authentication

play16:04

authorization rules right so maybe every

play16:06

logged in user can actually uh get an

play16:08

article but to update an article you

play16:10

need to be an admin or something like

play16:12

that and so here you can have additional

play16:14

rules if the user is not an admin kind

play16:16

has a great solution for roles and

play16:18

permissions as well we can check if the

play16:20

user has the proper role or permission

play16:22

so that's another benefit of using this

play16:24

structure is now whenever you need to

play16:26

change your authentication or

play16:27

authorization logic you know where to

play16:29

look because previously if you were

play16:31

doing the authentication check in some

play16:33

you know random components throughout

play16:35

your codebase you don't know exactly

play16:38

where you left that check right so now

play16:40

you want to update the authorization

play16:42

logic so that only admins can update

play16:44

articles so now you have to think oh

play16:46

where did I leave that where did I leave

play16:48

that uh logic was it in a text component

play16:50

or some other component right so it's

play16:52

scattered throughout your codebase but

play16:53

this way you know where to look it's all

play16:55

in your data access folder you have

play16:57

embedded that Within these function all

play16:59

of the updates happen in one place also

play17:01

if you work in a team you may have one

play17:03

person who takes care of the data access

play17:05

layer and another person and that

play17:07

actually uses that in the rest of the

play17:09

app right so I think it also helps split

play17:11

up the work I think somebody who is a

play17:13

traditional backend developer would feel

play17:15

more at home interacting with the

play17:16

database than a traditional front end

play17:19

developer right so a front end developer

play17:20

would probably feel more comfortable

play17:22

actually using these functions so I

play17:24

think this is a more natural way of

play17:26

splitting up the work in a team that's

play17:28

working on xsf it also helps in other

play17:31

related ways for example if you want to

play17:32

log who's accessing the database the

play17:35

access or you doing some kind of

play17:36

security audit you can just do it

play17:38

directly in here you know where to do it

play17:40

it's all in one centralized place right

play17:41

so there are many benefits that come

play17:43

with this structure the fancy word for

play17:45

this is a data access layer and you can

play17:47

implement it in different ways you can

play17:48

use classes but this is now the

play17:50

recommended structure for accessing your

play17:53

data in new nextjs projects right and by

play17:56

the way if you ever need this data in

play17:58

some other component maybe not in text

play18:00

maybe we also need article data in some

play18:02

statistics component maybe and writer

play18:05

can log in and can view their most

play18:07

popular posts right and we want to show

play18:09

the we want to show the title of the

play18:11

most popular post right just an example

play18:13

but we could want to access this data

play18:15

and other components as well right so

play18:17

now I'm accessing the article data in

play18:19

stats as well as in text and maybe I

play18:21

have stats here on the page as well so

play18:24

now maybe you are getting worried

play18:25

because now we're going to duplicate

play18:27

those calls right so now you could say

play18:29

oh I'm accessing the data the database

play18:31

from this component but now also from

play18:33

this component so that would be a bit

play18:35

much because now we're going to invoke

play18:37

this multiple times so we're going to

play18:38

make that datab base call multiple times

play18:40

Well react has a solution for that

play18:43

actually they have a cache function so

play18:45

you can wrap that entire function in a

play18:47

in the cache function from react if you

play18:50

invoke that multiple times during what

play18:53

react calls a render pass so if this

play18:55

page gets rendered they both get called

play18:58

but it would only run once right so it

play19:00

would not make duplicate calls to the

play19:02

database so that's something that you

play19:04

may want to use here as well in addition

play19:06

to that you may also want to use the

play19:09

server only package it will make sure

play19:11

that if you try accessing anything here

play19:13

on the client side that you will get an

play19:15

error so it's it's slightly safer so

play19:17

that you're not accidentally trying to

play19:19

use these functions on the client side

play19:21

and what you may also want to do is if

play19:23

you're using an omm like Prisma here

play19:25

there are some other security best

play19:27

practices I would say um because very

play19:29

often you don't need all of the article

play19:31

data right so with Prisma here I can

play19:33

select what I want so here I want the

play19:35

text for example but maybe this article

play19:38

in the database also has the author

play19:40

email right and that is more sensitive

play19:42

data right so somebody's email is not

play19:44

something that we Loosely want to pass

play19:46

around now by default if you leave the

play19:48

select off if you just do it like this

play19:50

it will give you all the fields of that

play19:52

article but by using select here we can

play19:54

make sure that we only get the text

play19:56

field back and not the email that's so

play19:58

we can be more specific and get back

play20:01

just the fields that we need and not the

play20:03

more more sensitive perhaps Fields right

play20:05

so that's another I would say security

play20:07

best practice right also if you're if

play20:09

you're actually managing users in your

play20:11

own database you don't want to get their

play20:12

hashed passwords right so you don't want

play20:14

to select the password in that case now

play20:16

let's say we we are getting the data

play20:18

like this so we are getting the article

play20:20

data from the database and we are

play20:22

returning it plainly like that now

play20:24

before we actually return that and sort

play20:26

of make it available to the rest of our

play20:28

app where wherever we may be accessing

play20:30

wherever we may be trying to use that

play20:32

maybe we sort of want to do one last

play20:34

filter step or now you may want to be a

play20:36

little bit more specific so instead of

play20:38

just returning the whole article data

play20:40

like that maybe we actually do want to

play20:42

pass and make available a specific

play20:44

object right so we know that article

play20:46

data has an ID so maybe we do indeed

play20:49

want to return that ID okay and also the

play20:53

text right so article data. text okay so

play20:56

we are now returning essentially the

play20:57

same now if article data also had that

play20:59

author email right you could decide to

play21:02

not include it here right so here in

play21:04

this case you can also say well we're

play21:06

simply not going to return that from

play21:07

here that's another way of sort of

play21:09

filtering out sensitive Fields also

play21:11

maybe you can already do some data

play21:13

Transformations here or some or do some

play21:15

computation here for example the slug

play21:17

for if it for whatever reason is not

play21:19

part of the article data from the

play21:21

database maybe the slug right so that's

play21:23

typically the title of the article in

play21:25

the URL maybe we can just take uh the

play21:27

article dat

play21:29

the text and then just maybe take the

play21:31

first uh the first 10 characters or

play21:33

something like that so that it's easier

play21:35

to use it in the rest of the app

play21:37

basically the fancy word for this is a

play21:39

data transfer object dto and so instead

play21:42

of doing it like this we may actually

play21:44

create a function that actually does

play21:46

that for us right so here we can say

play21:47

create article dto and you pass in the

play21:51

article data and that's what we're going

play21:52

to return here let me actually just

play21:54

create that function here create article

play21:56

dto which takes in that article data and

play21:59

it returns an object with that ID detect

play22:02

we came up with some slug example as

play22:05

well right so here it's basically a way

play22:07

of filtering out sensitive field and

play22:10

maybe do some Transformations on some

play22:11

data basically making sure that it's the

play22:14

exact shape that we want because what

play22:16

you get back from the database may may

play22:18

not be the exact shape in which you want

play22:20

to use it in the rest of your

play22:21

application that's what we would return

play22:23

now basically we get the data the raw

play22:25

data from the database and we just shape

play22:26

it a little bit before we return it from

play22:28

from that function before we're actually

play22:30

going to use it in the rest of the

play22:31

application we may want to create a

play22:33

separate file where you have these uh

play22:35

dto another benefit of this is for

play22:37

example if you if you change the model

play22:39

in your database right maybe here I'm

play22:42

going to change the schema actually here

play22:44

for Prisma instead of text maybe we

play22:46

actually rename this to content let's

play22:48

say the benefit is now that we don't

play22:50

have to update that everywhere in our

play22:52

app and so previously if you were just

play22:54

using the raw for the raw object from

play22:57

the database you would have to update an

play22:58

every plan but now we are also

play23:00

centralizing that here in one place so

play23:03

we can keep using text as long as we of

play23:06

course change this into content right so

play23:08

then in the rest of the app we can still

play23:10

use article data. text right so we would

play23:12

still use article data. text here but

play23:14

now it is do content from the database

play23:16

right so now I would say this is

play23:18

becoming pretty uh sophisticated setup

play23:20

in the latest next s app router next

play23:22

chance is a full stack framework so we

play23:24

are sort of rediscovering a lot of

play23:26

traditional software engineering concept

play23:29

but I would say this is a better

play23:30

structure than randomly accessing your

play23:33

data throughout your component this is

play23:35

something that you may want to use or at

play23:37

least to think about right so here we

play23:39

were talking about getting data fetching

play23:42

data from your database but the same

play23:44

problem will exist update data in a

play23:46

database in a server action and actually

play23:48

for very similar reasons you may be

play23:50

confused a little bit because this is

play23:51

all pretty Cutting Edge but the good

play23:53

news is for authentication and

play23:56

authorization which used to be a huge

play23:58

problem

play23:59

at least that part of the stack has been

play24:01

solved thanks to kind kind makes it

play24:03

really easy to manage all of the

play24:04

authentication authorization stuff so I

play24:07

would say check out kind I want to thank

play24:08

them for sponsoring this video very easy

play24:10

to set up very professional looking you

play24:12

can find a link for them in the

play24:14

description and I want to thank you for

play24:15

watching as well hope to see you the

play24:17

next one bye

Rate This
β˜…
β˜…
β˜…
β˜…
β˜…

5.0 / 5 (0 votes)

Related Tags
Next.jsSecurityData Access LayerAuthenticationReact Server ComponentsDatabase InteractionWeb DevelopmentPrisma ORMKind AuthCode Structure