Free YouTube Transcribe

Video transcript

How to Design APIs Like a Senior Engineer (REST, GraphQL, Auth, Security)

Hayk Simonyan · 13,939 words · 64 min read

Want to search this transcript, jump the video from any line, or download it as TXT, SRT, or VTT?

Open in the transcript tool

Full transcript

Introduction

0:00In this course, you'll learn the API

0:01design skills that separate junior

0:03developers from seniors. Most developers

0:06only know how to build basic CRUD APIs,

0:09but they don't really understand how

0:11APIs work behind the scenes, like when

0:13to choose REST over GraphQL, or when to

0:16choose rich protocol like HTTP,

0:18websockets, messaging protocols, or how

0:21to apply security practices. These are

0:23exactly the things that senior engineers

0:26get asked in interviews and the same

0:28principles I've applied myself while

0:30working on real world projects. We'll go

0:32through the API design principles,

0:35protocols, restful and craft API design,

0:38authentication, authorization and

0:40security practices. So everything you

0:43need to know to go beyond the basics and

0:46think like a senior engineer. If you're

0:48stuck in junior to mid-level roles and

0:51want to land senior salaries, then this

0:53is the knowledge that will help you get

0:55there. Welcome to this section where you

API Design Fundamentals

0:58will learn the fundamental principles of

1:00API design which will enable you to

1:03create efficient, scalable and also

1:05maintainable interfaces between software

1:08systems. Here is what we're going to

1:10cover in this lesson. We'll start from

1:12what APIs are and what is their role in

1:15system architecture. Then we'll cover

1:17the three most commonly used API styles

1:20which are REST, GraphQL, and gRPC. We'll

1:24discuss the four essential design

1:26principles that make great APIs and also

1:29how application protocols influence the

1:32API design decisions. We'll also cover

1:34the API design process. So starting from

1:37the design phase to development phase to

1:39deployment. So we'll see how that

1:41process looks like. So let's start by

1:44understanding what is an API. API stands

1:47for application programming interface

1:49which defines how software components

1:51should interact with each other. Let's

1:53say on one side you have the client

1:55which is either the mobile phone or the

1:57browser of this user and on the other

2:00side you have the server which will be

2:01responding to the requests. So API here

2:05is just a contract that defines these

2:07terms which are what requests can be

2:09made. So it provides us with an

2:11interface on how to make these requests

2:14meaning what endpoints do we have what

2:16methods can we use and so on. Also what

2:19responses can we expect from this server

2:22for a specific endpoint. So first of all

2:25it is an abstraction mechanism because

2:27it hides the implementation details

2:30while exposing the functionality. For

2:32example, we can make a request to save a

2:35user data in this server, but we don't

2:37care at all about how the logic applies

2:40behind the scenes inside of this server.

2:42So, we only care about the interface

2:44that is provided through this API and we

2:47only use that endpoint and we store the

2:50user without even knowing about the

2:52implementation details. And it also sets

2:55the service boundaries because it

2:57defines clear interfaces between systems

3:00and components. So this allows us to

3:02have multiple servers. We can have one

3:04server that is responsible for managing

3:06the users. We can have another one that

3:09is responsible for some other records.

3:11Let's say for managing the posts and so

3:13on. So this allows different systems to

3:16communicate regardless of their

3:18underlying implementation like client

3:21browsers with servers or servers with

3:23another servers and so on. Now let's

3:26focus on the most important API styles

3:28you will encounter during the design

3:31phase. These are RESTful, GraphQL, and

3:34gRPC. The most common one out of these

3:36is REST, which stands for

3:38representational state transfer. These

3:41type of APIs use resource-based approach

3:44by using the HTTP methods as a protocol.

3:48One of the advantages of REST APIs is

3:50that they are stateless, meaning that

3:52each request contains all of the

3:54information needed to process it and we

3:56don't need any prior requests to be able

3:58to process the current request. And it

4:01uses the standard methods on HTTP

4:04protocol which are get for fetching

4:06data, post for storing data, put or

4:09patch for updating data and delete for

4:12deleting data. So based on its

4:14characteristics, the rest is most

4:16commonly used in web and mobile

4:18applications. Next, we have GraphQL,

4:21which is the second most common API

4:23style after the REST APIs. GraphQL is a

4:27query language that allows clients to

4:29request exactly what they need. This

4:32means that it comes with a single

4:33endpoint for all of the operations and

4:36we can choose what we are expecting to

4:38receive from this API by providing the

4:41payload in the request. And the

4:43operations here are called query

4:45whenever we are retrieving data or

4:48mutation whenever we are updating data.

4:50So this is the equivalent in put or

4:53patch or post in the restful APIs and

4:56there is also a subscription in

4:58operations which is for realtime

5:00communication. The advantage of GraphQL

5:03APIs is that it allows us to have

5:05minimal round trips. Let's say we need

5:07some data that in restful APIs we will

5:10need to make three requests to get all

5:12of this data. In GraphQL case we can

5:15make a single request and get all of

5:17these data avoiding the unnecessary two

5:20requests that we will otherwise have to

5:22make in RESTful. And because of that

5:24this is the recommended option for

5:26complex UIS. So wherever you have some

5:28complex UIs where on one page you might

5:31need different data on another page you

5:33might need some other complex nested

5:35data. In these cases, GraphQL is the

5:38better choice over restful APIs. And the

5:41last option is gRPC. I would say this is

5:43the least common one out of these three.

5:46GRPC is a high performance RPC framework

5:50which is using protocol buffers for

5:52communication.

5:53The methods in gRPC are defined as RPCs

5:57in the protoiles and it supports

6:00streaming and birectional communication.

6:03This is an excellent approach for

6:05microservices especially and internal

6:07system communication as it is more

6:10efficient when you're working between

6:12servers compared to graphql or compared

6:14to restful APIs. So the difference

6:17between rest graphql and gRPC APIs is

6:20kind of clear but let's also clarify the

6:23real difference between rest and graphql

6:25APIs on examples. So as you saw rest

6:29comes with resource-based endpoints. For

6:31example, here if we take a look at these

6:33requests, you can see that the resource

6:35here is users. So you always expect to

6:38see some users endpoint or some

6:40followers endpoint or let's say posts

6:42endpoint. So it is resource-based and

6:45sometimes we might need to make multiple

6:47requests for getting the related data.

6:50As you can see here, we need let's say

6:52the user details, but we also need the

6:54user posts and followers. So in this

6:57case we need to make three requests to

6:59get all of these data and it uses HTTP

7:02methods to define operations. As you can

7:04see these are HTTP endpoints and we are

7:07using the get method specifically and

7:10the response structures are fixed

7:12meaning if you got one response for this

7:14specific user. Next time you can expect

7:16to have exactly the same response

7:18structure. Maybe some data will be

7:21modified but the structure always

7:23remains the same. And it also provides

7:25explicit versioning. So as you can see

7:27it comes with vub1 for the v1 API then

7:30later if it got a major upgrade then

7:33this will become v2 and so on. And you

7:35can use the headers on the requests to

7:38leverage the http caching on restful

7:40apis. Now if we compare that to graphql

7:44apis it comes with a single endpoint for

7:46all operations. So mostly it is /g

7:49graphql or slash some API endpoint that

7:52is commonly used for all operations and

7:55in this case we will use a single

7:57request to get the precise data that we

8:00need and we will use the query language

8:02of graphql. This is what the query

8:05language looks like. As you can see we

8:07start with a query and then we define

8:09what we need. For example, we need the

8:11user with ID 1 2 3. Then we need the

8:14name of the user, the posts and then we

8:17define whatever we need from the posts.

8:19Maybe we need only title and content and

8:21nothing more. And also the followers and

8:24what we need from followers, maybe only

8:26names. So this allows us to be more

8:29efficient in our requests compared to

8:31restful APIs where we will need to make

8:33free requests for this same data. This

8:37means that client needs to specify the

8:39response structure and in this case the

8:42schema evolution is without versioning.

8:44So here as you saw it is with v_sub_1,

8:46v2 and so on. In this case the schema

8:49usually evolves without versioning. But

8:52there is also a common pattern to start

8:54versioning the fields. For example you

8:57can have followers v2 and that will be

9:00the second type of followers schema. But

9:03you can also go without versioning. So

9:05you can just start modifying the

9:07followers or posts if you are sure that

9:10there are no other clients using your

9:12old API and in this case you can

9:15leverage the application level caching

9:17instead of the HTTP caching. Now let's

9:20discuss the major design principles that

9:23will allow us to create consistent,

9:25simple, secure and also performant APIs.

9:29Ultimately the best API is the one that

9:32we can use without even reading the

9:34documentation. For example, if you saw

9:36the previous endpoints in the users you

9:39see that we have / users/123

9:42and obviously we are expecting to get

9:44the user details of this specific user.

9:47And if you make a request for example to

9:49that endpoint to fetch user details but

9:51then you find out that it also updates

9:54some followers or something while making

9:56this request then obviously that is a

9:58very bad type of API as we didn't expect

10:01it to do such operations. So first of

10:04all the good API should be consistent

10:07meaning it should use the consistent

10:09naming casing and patterns. For example,

10:12if you use camel case in one of the

10:14endpoints, let's say you have user

10:17details and you do this in camel case,

10:19but in another case you do it with a

10:21skinnate case like user/details,

10:25then this is not common and this is not

10:27consistent. The second key principle is

10:30to keep it very simple and focus on core

10:33use cases and intuitive design. So you

10:36should minimize complexity and aim for

10:39designs that developers can understand

10:41quickly without even maybe reading the

10:43documentation. And simplicity again

10:46comes down to this which is the best API

10:48is one that developers can use without

10:51even reading the documentation.

10:53Next obviously it has to be secure. So

10:55you have to have some sort of

10:57authentication and authorization between

11:00users. Also, if you have inputs, then

11:02you need to make sure that these are

11:03validated and you should also apply rate

11:06limiting. So, these are the most basic

11:08things that you have to do to keep your

11:10APIs secure. And the last pillar is

11:14performance. So, you should design for

11:16efficiency with appropriate caching

11:19strategies with pagination. If you have

11:21a large amount of data, let's say

11:23thousands of posts, you don't want to

11:26retrieve all of these whenever they make

11:28a request to get the post. So you should

11:30always have pagination with some limit

11:32and offset. Also the payloads meaning

11:35the data that you will send back should

11:37be minimized and also whenever possible

11:40you should reduce the round trips. So if

11:43you have the opportunity to send some

11:45small data along with the request of one

11:47of the endpoints then it's better to do

11:50this if you know that you're going to

11:51use it instead of making another

11:53endpoint for making a request to get the

11:56same data. Now each of these APIs use

11:59different protocols and we will learn

12:02more about these in the next lesson. But

12:04basically your protocol choice will

12:06fundamentally shape your API design

12:09options. For example, the features of

12:11HTTP protocol directly enable restful

12:14capabilities. So it makes more sense to

12:17use HTTP along with restful APIs because

12:20it also provides you with status codes

12:23and these are great to be used with

12:25crowd operations that you will have in

12:27restful APIs. On the other hand, web

12:30sockets which is another type of

12:32protocol enable realtime data and also

12:34enable birectional APIs. So this can be

12:38used along with realtime APIs wherever

12:40you need some chat application or some

12:43video streaming. This is a good use case

12:45of websocket APIs. In case of graphql

12:48APIs, you again will use the HTTP

12:51protocol instead of websockets or gRPC.

12:55GRPC on the other hand can be used along

12:57with microservices in your architecture

13:00to make it faster compared to HTTP. So

13:04your protocol choice will affect the API

13:06structure and also the performance and

13:09capabilities.

13:10Therefore, you should choose it based on

13:12its limitations and strengths and the

13:15one that makes more sense in the type of

13:17API that you'll be developing. Now,

13:20let's discuss the API design process. It

13:23all starts with understanding the

13:25requirements, which is identifying core

13:27use cases and user stories that you will

13:30need to develop. also defining the scope

13:33and boundaries because if it's a huge

13:36API then you probably won't develop all

13:38of the features at once. So you should

13:40scope it to some specific features that

13:43you'll be developing and also what are

13:45out of scope for now. Then you should

13:47determine the performance requirements

13:50and specifically in your API case what

13:52will be the bottlenecks and where you

13:54need to make sure that it's performant

13:57and you should also not overlook the

13:59security constraints. So you should

14:01implement all of the basic features like

14:03authentication, authorization, the rate

14:06limiting but maybe some more stuff

14:08depending on the API that you'll

14:10develop. When it comes to design

14:12approaches, there are couple of ways to

14:14go about it. The first one is top-down

14:17approach which is you start with highle

14:19requirements and workflows. This is more

14:22common in interviews where they give you

14:24the requirements on what the API will be

14:27about and then you start defining what

14:30the endpoints will be, what the

14:32operations will be and so on. But there

14:35is also the bottom up approach which is

14:37if you have existing data models and

14:39capabilities then you should design the

14:42API based on this. So this is more

14:44common when you're working in a company

14:46and they already have their data models

14:48and capabilities of their APIs. So you

14:51should take that into account when

14:53designing the API. And we also have

14:56contract first approach which is you

14:58define the API contract before

15:00implementation meaning what the requests

15:03should look like and what the responses

15:05should look like. And this is more

15:07similar to top-down approach and this is

15:09also commonly used in interviews. When

15:12it comes to life cycle management of

15:14APIs, it starts with the design phase

15:17where you design the API, discuss the

15:20requirements and the expected outcomes

15:23of the API and only after that you can

15:26start the development and maybe local

15:28testing of your API. After that you

15:31usually deploy and monitor it. So you do

15:34some more testing but now on staging or

15:36on production. But then it also comes

15:39the maintenance phase. And this is why

15:41it's important to develop it with

15:43keeping the simplicity in place. So it

15:46will be easier for you to maintain or

15:48for other developers to maintain in the

15:50future. And lastly, APIs also go through

15:53deprecation and retirement phase. So

15:56some APIs eventually get deprecated

15:59because there might come up with a new

16:01version of the API that you should use.

16:03Or let's say you are transitioning from

16:05v1 to v2 API. So that's also the

16:08deprecation phase of the v1 API. So

16:12developing APIs is not only in the

16:14development phase as you might assume.

16:16It's not just coding. So the big part of

16:19it is designing it and also keeping it

16:22maintainable and also eventually you

16:24might need to retire it at the end. So

16:27let's recap and see what our next steps

16:30are. We learned what APIs are and about

16:33the most dominant free type of API

16:35styles which are restful, GraphQL, and

16:38gRPC. We've covered the four key

16:41principles that will guide us when

16:43creating API designs effectively. And

16:46you now also understand how the design

16:48choice of your protocol will influence

16:51the design of your API and also the

16:54whole API design process from start to

16:56finish. But we didn't discuss the

16:58limitations and strengths of these API

17:01protocols. So that's why in the next

17:03lesson we will learn all about the API

17:06protocols that we can use with API

17:09design and which one we should choose

17:11based on the requirements of our API.

17:13Before we get into the next lesson, just

17:15knowing the API principles on a high

17:18level won't get you far. In interviews,

17:20you'll usually get code immediately if

17:23you're trying to fake it and if you have

17:25never implemented them in real projects.

17:28If you're a developer with 1 to five

17:30years of commercial experience based in

17:32US, Canada, Europe, Australia, or New

17:35Zealand, and you're stuck in junior to

17:38mid-level roles, but you want to move

17:40into senior positions, master API design

17:42and other concepts and start earning

17:45senior level salaries, then you can

17:47apply to work with me oneonone. This is

17:50exactly what I help developers do inside

17:52of my mentorship program. We take these

17:54concepts and apply them hands-on in real

17:57world projects. The same way senior

17:59engineers will work in top companies. So

18:02the first link in description is where

18:04you can apply. But only apply if you're

18:06serious about advancing to senior roles.

18:09Otherwise, our calendar is fully booked

18:11all the time. And if your application

18:13doesn't seem like a good fit, then

18:15unfortunately we'll have to cancel it.

API Protocols

18:17Choosing the wrong protocol for our API

18:20can lead to performance bottlenecks and

18:22also limitations in functionality.

18:24That's why we need to first understand

18:26these protocols which will allow us to

18:28build APIs that meet our specific user

18:31requirements for latency throughput and

18:34also interaction patterns. That's why in

18:36this lesson we'll cover the role of API

18:39protocols in the network stack. the two

18:42fundamental protocols which are HTTP and

18:45HTTPS and also their relationship to

18:47APIs. Also another common type of

18:50protocol which is websocket for realtime

18:53communication we'll also cover advanced

18:55message queuing protocol which is

18:57commonly used for asynchronous

18:59communication and lastly we'll cover the

19:02gRPC which is Google's remote procedure

19:04call and it is also another common type

19:07of protocol used commonly within

19:09servers. Let's start by understanding

19:11the application protocols in network

19:14stack. Application layer protocols sit

19:17at the top of network stack building on

19:19top of protocols like TCP and UDP which

19:23are at the transport layer. These

19:25protocols at application layer define

19:27the message formats and structures also

19:30the request response patterns and

19:33management of the connections and error

19:35handling. Now below that we have many

19:38other layers like the network layer or

19:41data link layer or even physical layers

19:43but when building APIs we are mostly

19:46concerned with the API layer protocols

19:49which are HTTP, HTTPS, websockets and so

19:52on. The most common type of protocol and

19:55also the foundation of web APIs is HTTP

19:58which stands for hypertext transfer

20:00protocol. This is the typical

20:02interaction between client and server

20:04when they are interacting over HTTP. As

20:07you can see, client always sends an

20:08request and they define the method which

20:11can be get, post or other methods and

20:13they define the resource URL which can

20:16be at / API/ products. Let's say they

20:19are requesting data for this specific ID

20:21of the product and they also define the

20:24version of the HTTP protocol that they

20:26are using. They also define the host

20:29which is the domain of your server where

20:32the information is accessed and usually

20:34they also authenticate before accessing

20:37any resources. So it can be either a

20:39bearer token or a basic authentication

20:42of and so on. So once the request is

20:45authenticated in the server it receives

20:47the response which is in similar format

20:50and it's in HTTP response. So you get

20:52the HTTP version which is again the same

20:55as you requested with and the status

20:57code which can be 200 if it was

20:59successful or it can be 400 if the

21:02client was error or 500 if the error

21:05happened in server and so on. You

21:07receive the content type which can be

21:09usually application JSON but it can also

21:12be a static web page or something else.

21:15And there are many other headers that

21:17you can control like controlling cache.

21:19You can use the cache control header or

21:21some other properties. But these are the

21:24main things that you would notice in

21:25HTTP request response cycles. Now when

21:28it comes to methods, you have get for

21:31retrieving data, post for creating data

21:33in the server, put or patch for updating

21:36data partially or fully, and delete for

21:40removing data from the server. And when

21:42it comes to status codes which are

21:44received by the server, so you have 200

21:46series which are successful cases. You

21:49have 300 for redirection. 400 means that

21:52client made an error in the request. So

21:54this is an issue from client side or 500

21:57which means that server made an error or

22:00like some error happened in the server.

22:02So which means that this is the issue in

22:04this server. And these are the common

22:06headers like content type which is

22:08defined by the server usually but also

22:10from the client authorization for making

22:13a request and authorizing to the server.

22:16Accept headers cache control user agent

22:18and there are more headers but these are

22:20the common ones. Then we also have HTTPS

22:23which is basically the same HTTP

22:25protocol but with some sort of TLS or

22:28SSL encryption which means that our data

22:31is now protected in transit when we are

22:33making requests. So it adds a security

22:36layer through this TLS or SSL

22:38certificates and encryption and it

22:41protects data in the transit and

22:43benefits of HTTPS is obviously your data

22:46is encrypted in the transit. It comes

22:48with data integrity and you also

22:50authenticate users before providing any

22:52data and it also adds SEO benefits and

22:56you have many risks when you are using

22:57HTTP only without any encryption. So the

23:00golden standard is to always use HTTPS

23:03in servers. The next type of protocols

23:07are web sockets. While we have HTTP

23:09which is very good at request response

23:11patterns, sometimes HTTP has

23:14limitations. For example, let's say

23:16you're pulling some data. Let's say this

23:18is a user chat. So you have the client

23:20and server. On the client side, you have

23:22the user chat and on the server you have

23:24the messages between two users. When one

23:27of the users messages the other, it

23:30sends a request to the server to notify

23:32that a message has been sent. And it

23:34receives a response from the server,

23:36maybe the messages from the other users

23:39if there are any. And then next time if

23:41you need to know if you have new

23:43messages, you need to make again another

23:46request to the server and maybe you

23:48don't have any new messages. So you will

23:50receive an empty response with no new

23:52data. So this was basically an

23:54unnecessary request response cycle and

23:57you might request from some other time

23:59let's say from 1 minute and receive a

24:01response. Now you have some messages but

24:03it can be also empty again. So this way

24:06is not ideal for realtime communication.

24:09As you can see, you get increased

24:11latency. You waste some bandwidth with

24:13making requests that are empty and you

24:16also use the server resources without

24:18the need of making requests to this

24:20server. And for such cases, we have

24:23websockets which solve this issue. So in

24:26websocket you have usually a handshake

24:28that is happening within the first

24:30request and now you have both like

24:32two-side communication between client

24:34and the server which means that once the

24:37handshake is been made the server can

24:39independently decide to push data to the

24:42client. Let's say now you have two new

24:44messages on the server. So server can

24:47decide to send these messages to the

24:49client without even client requesting

24:51for it. But client can still request

24:54data. So if client needs some external

24:56data or more data from the server, it

24:59can still make requests. But server is

25:01now also able to independently push data

25:04to the client. So this is what unlocks

25:06the real-time data with minimal latency.

25:09As soon as you have some new data in the

25:12server, it pushes the new data to the

25:14client and it also reduces the bandwidth

25:17usage by allowing birectional

25:19communication. In client server model

25:21with HTTP you would make let's say new

25:24requests per 5 seconds or 10 seconds to

25:27see if there are any new data in the

25:29server. But in this scenario you don't

25:31make any more requests other than the

25:34first one. And now whenever there are

25:36new data server will push it and

25:38whenever there are no data to be

25:40requested then you don't need to make

25:42unnecessary requests to the server. The

25:45next very common type of protocol is

25:47advanced message queuing protocol which

25:50is an enterprise messaging protocol used

25:52for message queuing and guaranteeing

25:55delivery. In this setup you usually have

25:57the producer which can be either a web

26:00service or payment system or something

26:02like that and on the other side you have

26:05the consumer which can be the processor

26:07of the payments or notification systems

26:10and stuff like that. So producer

26:13publishes messages to the message broker

26:16and here is where you have the advanced

26:18message queuing protocol. You have cues

26:20in the middle. Let's say one of these

26:22cues is for order processing. So

26:24whenever a new order has been placed,

26:26producer publishes a message to this

26:29queue. And then whenever this consumer

26:31is free, it can pull messages from this

26:34queue and start updating the inventory

26:36and data in the database. This allows

26:39the consumer to only pull data from here

26:42whenever it has capacity. And whenever

26:44this consumer is busy with some other

26:47tasks, it leaves the message in the

26:48queue. And then later on, whenever it

26:51has some free capacity, it will pull the

26:53message and start updating the data. And

26:56when it comes to exchange types, you

26:58have direct one-on-one exchange or fan

27:01out or topic based communication. And we

27:04will explore these more when we come to

27:06the message queuing section. The other

27:09common type of protocol is gRPC which

27:12works with protocol buffers. This is a

27:14high performance RPC framework invented

27:17by Google and it uses HTTP2 for

27:20transport meaning the second version of

27:22the HTTP. This means that clients should

27:25support HTTP2 otherwise this can't be

27:28used between client and server but

27:31that's why this is most commonly used

27:33between servers. So usually the client

27:35is another server and we have some other

27:38microservices communicating with each

27:40other with this gRPC framework. It

27:42mainly uses protocol buffers and it also

27:45comes with built-in streaming capacities

27:48because it uses HTTP.2.

27:50So these are the most common types of

27:52API protocols. There are many more but

27:55usually in 90% of cases you would see

27:58only these protocols. And when choosing

28:00the right one, you should mainly

28:02consider the interaction patterns.

28:04Usually, by default, you go with HTTP.

28:06If it's just a request response cycle,

28:08but if you're building something like

28:10real-time chat or some real-time

28:12communication, then you would need to go

28:14with websockets. The choice also depends

28:16from the performance requirements. So if

28:19you have multiple servers, microservices

28:21communicating with each other and there

28:23isn't opportunity to use gRPC for

28:26example then you can go with it to

28:28increase the performance and speed of

28:30the communication but it also comes down

28:33to client compatibility. For example,

28:35most browsers don't support the latest

28:37version of the HTTP. That's why gRPC

28:40isn't that very common for browser

28:42server communication. It also comes down

28:45to the payload size meaning the volume

28:47of the data and encoding security needs

28:50based on the authentication encryption

28:52and so on and also the developer

28:55experience. So the tooling and

28:57documentation and it also comes down to

28:59the developer experience because you're

29:01mostly going to work with this API and

29:04it needs to have good documentation and

29:06tooling for you to fully work with this

29:08type of API protocol. So to recap, we

29:11have explored the role of application

29:13protocols in network stock. The HTTP and

29:17HTTPS which are the most fundamental

29:19types of protocols. Web sockets for

29:22real-time communication. AMQP which

29:25stands for advanced message queuing

29:27protocol which allows us to have

29:29asynchronous communication and adding

29:31message cues between the consumer and

29:33producer and also gRPC which stands for

29:36Google remote procedure call. And the

29:39main advantage of this is that it's high

29:41performance RPC framework which uses

29:43HTTP2 for transport. So we discussed the

29:47application layer which includes these

29:49protocols that we usually use for

29:51building APIs. But we don't know yet

29:54about this transport layer which

29:55includes the TCP and UDP. So in the next

29:59lesson we are going to discuss this

30:01layer and understand which of these

30:03transport layers whether TCP or UDP are

30:06the best choice depending on the API

30:08that we are building. Most developers

Transport Layer: TCP & UDP

30:11work with APIs but never think about

30:13what's actually delivering those

30:15packets. Like how does it happen that

30:17the request is being made from client to

30:20server and how does this request go

30:22through the internet. That's where the

30:24second layer comes in in the OSI model

30:27which is the transport layer that has

30:29the TCP and UDP inside of it. These are

30:33both transport layer protocols, meaning

30:35they handle how data moves from one

30:38machine to another over the network, but

30:41both are doing it very differently. In

30:43this lesson, we'll learn about these

30:45transport layer protocols. We'll start

30:47with TCP, which is the reliable but

30:50slower version. Then we'll learn about

30:52the UDP, which is in short, it's faster

30:55and unreliable version of TCP. and we'll

30:58compare both of them and decide which

31:00one we need to choose based on the API

31:03requirements. Let's start with TCP which

31:06stands for transmission control

31:08protocol. Think of it like sending a

31:10packet with a receipt tracking and also

31:13signature that is required. So when you

31:15send some packets over the internet, you

31:18usually don't send all of it at once.

31:20Sometimes the data is larger. Let's say

31:23it's divided in three chunks. So you

31:25need to send them separately. the first

31:27chunk, the second chunk, and also the

31:29third chunk. So in this case, TCP

31:32guarantees delivery of all of these

31:34three chunks. If one of these packets is

31:37lost or arrives out of order, TCP will

31:40resend or reorder it. It's also

31:43connection based, which means that

31:45before sending any data, it performs a

31:48free-way handshake, which is

31:50establishing the connection between

31:52client and server. It also orders these

31:55packets. Let's say the client receives

31:57the first packet first, then the third

31:59packet, then the second packet. It makes

32:02sure that it's reordered to first,

32:04second, and third. This of course adds

32:07overhead, but it ensures that it's

32:09accurate and reliable. That's why APIs

32:12that involve payments, authentication or

32:14user data always use TCP. On the other

32:17hand, we have UDP, which stands for user

32:20datagram protocol. It's fast and

32:23efficient, but the downside of this is

32:25that it doesn't guarantee that all of

32:27the packets will arrive. For example, if

32:30you're sending four packets from the

32:32server to the client, one of these

32:34packets might be lost and it won't be

32:36pushed to the client and UDP won't make

32:39sure that this eventually gets

32:40delivered. So, there is no delivery

32:43guarantee. There is also no handshake or

32:46connection or any sort of tracking. But

32:49because of these trade-offs, it is

32:51faster transmission and it comes with

32:53less overhead as it doesn't need to make

32:56sure that all of the packets are

32:58delivered or in the correct order. For

33:00example, in video calls, UDP can be the

33:03best protocol because if some

33:05information was cut in the middle or

33:08let's say you're in a call with someone

33:10and their internet connection lacks, you

33:12don't need to receive that old

33:14connection or the old data on what they

33:16said because you are in the call right

33:18now. So UDP is the go-to for video

33:21calls, online games, or live streams

33:24because if one of these packets drops,

33:26it's still fine and you don't need to go

33:28back and resend this packet. You can

33:30just move on and send the next packets.

33:34This is what the three-step handshake

33:36looks like in TCP. As you can see, the

33:38first step is that client sends a

33:40request to the server. In the second

33:42step, server syncs and acknowledges the

33:45request. And in the first step, the

33:47client acknowledges the server and this

33:50is where the connection is established

33:51between the client and server. And now

33:54they can start sending data back and

33:56forth on top of this TCP protocol. So in

34:00short, TCP is the safer and reliable

34:03version of UDP, but it is slower. And on

34:06the other hand, UDP is faster and

34:08lightweight, but it is risky. For

34:10example, if one of the packets in

34:12between the source and destination is

34:14lost, it doesn't resend it. So there is

34:17no guaranteed delivery. But on the other

34:20hand, if in TCP one of the packets is

34:22lost after some time out, it still

34:24resends the first packets. And this way

34:27it guarantees that all data will be

34:29delivered compared to UDP where some

34:31data might be lost, but it will still

34:33keep going. And when choosing between

34:36those two, these are the main things

34:38that you need to look for. If you need

34:40the connection to be safe and reliable,

34:42then you need to go with TCP. Or if you

34:44need it to be fast, lightweight, but

34:47some data loss might be acceptable, then

34:49you will need to go with UDP. For

34:51example, it is best for using TCP in

34:54bankings, emails, payments, and so on.

34:57And on the other hand, UDP is mostly

34:59used in video streaming, streaming,

35:02gaming, and so on. These are the main

35:04things that you need to know about the

35:06application and transport layers. And

35:09these are the only layers that will need

35:11to be used to building APIs. And in the

35:14next lesson, we will learn about restful

35:16APIs and how we usually design APIs in

35:19restful format. Restful APIs let

RESTful API Design

35:22different parts of a system talk to each

35:24other using the standard HTTP methods.

35:28They are the most common way developers

35:30build and consume APIs today. And in

35:32this video, you'll learn how to design

35:34clean REST APIs by following the proven

35:37best practices so that you avoid

35:39creating messy and inconsistent patterns

35:42that make the APIs hard to use and

35:45maintain. We'll start by learning about

35:47the architectural principles and

35:50constraints of restful APIs, about the

35:53resource modeling and URL design, also

35:56the status codes and the error handling

35:59as well as filtering, sorting, and so

36:01on. and we'll learn the best practices

36:04when using and developing restful APIs.

36:07Let's start from the resource modeling.

36:09Resources are the core concepts in REST.

36:12Let's say you have the business domain

36:14which consists of the products, orders

36:17and reviews. When modeling this to a

36:20restful API, you usually convert this

36:22into nouns and not verbs. Meaning that

36:25the product becomes products, order

36:27becomes orders, and same for the

36:30reviews. These can be collections or

36:32individual items. For example, this

36:35first request which is to / API/

36:38products will return you the collection

36:40of products, not a single product. But

36:43on the other hand, you could have slash

36:44products and slashsp specific ID of a

36:47product which will return you the

36:49individual item. And notice that we are

36:52using / products when retrieving the

36:54collection of products. And we are not

36:57using something like get products which

37:00will be not a best practice in restful

37:02APIs. As I mentioned we are using nouns

37:05here and not verbs. So to fetch orders

37:08for example you don't define the URL as

37:11get orders. You just define it as slash

37:14orders and depending on the method that

37:16we'll use let's say it's a get method

37:18then you will retrieve the orders. If

37:20it's a post method then you will create

37:21an order and so on. So all the resources

37:25should be clearly identifiable through

37:27the URLs. For instance, this is an

37:30example of getting a collection. This is

37:33an example of getting a specific item.

37:36And also nested resources should be

37:38clear defined. For example, if you want

37:40to retrieve reviews for some specific

37:43product, then we would assume that if

37:45you make a request to SL products/ ID of

37:48that product and then / reviews, you

37:51would get the reviews for that specific

37:53product. But in real world APIs, you

37:56rarely want to return all the results at

37:58once. That's why we usually incorporate

38:01filtering, sorting, and pagionation in

38:03APIs. So, let's start from the

38:05filtering. For example, if you make a

38:07request to get all the products, you

38:10usually add some query parameter, which

38:12in this case, you can see it's category.

38:14So, you're first of all filtering them

38:16by category. And then also with the end

38:19sign, you add that they should be in

38:22stock. So, the in stock should be true.

38:25And this way, you are only returning the

38:27items that you're going to display on

38:29the UI. And you're not making some

38:31requests that will waste the bandwidth

38:33of this API. and also it will be a huge

38:36response for you in the front end side.

38:39Next we also have sorting. In this case

38:41again it's controlled through the query

38:43parameters and query parameters are

38:45anything that start after the question

38:48mark in the URL. So in this case you

38:50usually pass the sort attribute and this

38:53can be for example ascending by price or

38:56ascending by reviews or it can be also

38:59the descending order. So based on this

39:02you will get the response from the API

39:04in a sorted order because if you for

39:07example have thousand items in the back

39:09end in the database you don't want to

39:12retrieve all of these in unsorted order

39:15to the front end because let's say the

39:17front end now needs to sort them by the

39:20price ascending. This means that it

39:22needs to make request to get all of the

39:24products which are these thousand items

39:26that you have in the database. So that

39:29will be very inefficient. That's why we

39:31do the sorting in the back end instead.

39:33So your back end should support sorting

39:36functionality. This way the front end

39:38can just make a request to your back end

39:41and pass this sort query parameter and

39:44then that way it will get the sorted

39:46products to be displayed on the screen.

39:49And next we also have pagination. Again

39:51with the query parameter you usually

39:53pass the page which you want to retrieve

39:55and also the limit because if you don't

39:58pass the limit then again it will give

40:00you all of the products starting from

40:02the page two till the end which can be a

40:05lot of items. So you also pass some sort

40:07of limit and that limit is whatever

40:10you're going to display on the front end

40:12and then based on that you will get the

40:14response and here let's say you fetched

40:1610 items so you're going to display

40:18those 10 on the UI and then once they

40:21click on the next page you will make

40:23another request to the page three this

40:25time and you will get the next items

40:28from the server. Now usually we use page

40:30for pagination but there is another

40:33common attribute that is offset. So some

40:35APIs use offset instead of the page and

40:39they use this in combination with limit

40:41which basically means if you have

40:43thousand items. So offset will tell the

40:46API from where to start counting this

40:48thousand items and then limit is the

40:51same as you have it here. So it's

40:53basically limiting the number of items

40:55that you are getting from this offset to

40:58retrieve to the front end. And the last

41:00option you can also have this cursor

41:02based. So instead of page and limit you

41:05would pass a cursor which will be the

41:07hash of the page you want to retrieve.

41:10So this approach of adding filtering

41:12sorting and pagination comes with

41:14benefits. So first of all it saves the

41:16bandwidth of your server. It also

41:18improves the performance both in the

41:20server side and on the front end side.

41:23And it also gives the front end more

41:25flexibility because now you can fetch

41:27only the things that you need and not

41:29some unnecessary data from the database.

41:32Now let's come to the HTTP methods that

41:34REST APIs use because they rely on HTTP

41:38protocols and hence they are using the

41:40HTTP methods especially for crowd

41:43operations. So these are the most common

41:46types of crowd operations you would see

41:49in REST APIs. First of all we have the

41:51get method which is used for reading

41:54data from the API. So this is for

41:56retrieving resources as you saw like

41:58retrieving the products, retrieving the

42:01reviews and so on. And the URL usually

42:04looks like this. You you make a get

42:06request to the / API/ version of the

42:09API/ the resource name. And these type

42:12of requests are both safe and item

42:15ponent. Which basically means if you

42:17make a request to slash products two or

42:20three times, you expect to receive the

42:22exact same output every time unless some

42:25new products obviously have been added

42:27to the database. Next, we have the post

42:30method. This is usually when you're

42:32creating a resource in your server. The

42:34common example is again you will make

42:37the request to exact same endpoint as

42:39you have it for the get to create a

42:41collection but in this case instead of

42:44get you are using post method and this

42:46tells the API that you need to create a

42:49resource in the products and not

42:51retrieve them. These type of requests

42:54change the state of the server. They are

42:56adding a new item and also they are not

42:59item ponent which means that they are

43:01creating a resource. So the first time

43:03you create a resource, you will get the

43:05ID of the first item that you created.

43:08The second time you create it, you will

43:10get the ID of the second one and so on.

43:13Next, we have the put and patch methods

43:15which are very similar, but they are

43:18updating resources in your API, but they

43:21do it a bit differently. The put method

43:23replaces the whole resource, whereas the

43:26patch method partially updates the

43:28resource in your API. Now you can see

43:30that the request URL is exactly the same

43:33in both of their cases. So it's to slash

43:36products slash id of a product you want

43:38to modify just in case of the put

43:41request it will take this whole product

43:43with the ID of 1 2 3 and it will

43:46basically replace it with the new one

43:48that is coming from the front end.

43:50Whereas in case of the patch it will

43:52again take this item from the database

43:54with ID 1 2 3 but it will update it

43:57partially. Let's say you just updated

44:00the title from the front end and you

44:02made the request it patch method. So

44:05this will only update the title of this

44:07product and it will leave the other

44:09parts other properties unchanged. And

44:12the last crowd operation is delete and

44:15we use delete method in this case and

44:17obviously as the name tells it deletes

44:20the resource from the database. So again

44:22the URL is exactly the same as you have

44:25for modifying items. it's to /roucts/

44:29id of the resource and in this case you

44:31are not passing anything in the request

44:33body. So you are just making a delete

44:35request to this item and you are

44:38removing this from the database and each

44:40of these operations return you different

44:42status codes depending on how the

44:45request went whether it was successful

44:47or not. For that we have status codes

44:50and error handling in restful APIs. So

44:53you should use the appropriate status

44:55codes when working with REST APIs. For

44:58example, the 200 series are for

45:00successful requests. For example, 200 is

45:03okay. 200 is resource has been created.

45:06204 is there is no content here. Let's

45:09say you made a request the previous

45:12request we were talking about to

45:14/roucts/ some ID of a product and you

45:17successfully retrieved this item. This

45:20means that you also need to set the

45:21status code to 200 because the request

45:24has been successful. In the other case

45:27where you're creating a product and

45:28you're making a post request to /

45:30products, this time you shouldn't

45:32response with the same 200 code because

45:35200 generally means that the status was

45:38okay. But in 2011 case, it means that

45:41the resource has been created. And in

45:43this case, since you're creating a new

45:44product, you should obviously response

45:46with the 2011 status code, meaning

45:49resource has been created. We also have

45:51300 series which are for redirection.

45:54Let's say you make a request to a URL

45:56and now this URL has been moved to

45:58somewhere else. So it will respond with

46:01a 300 series and it will redirect you to

46:04the new URL. In 400 series, we have the

46:07client errors. So this is whenever your

46:09front end made a bad request or the user

46:12made a bad request. For example, 400 is

46:15a generic bad request. In 401 we have

46:18unauthorized requests, meaning the user

46:21is not authenticated to make this

46:23request. For 404 we have not found. So

46:26generally when you visit some URL or you

46:29make a request for some specific

46:30resource that doesn't exist, you would

46:32get this 404 status code. So for 400

46:36case, let's say you made a request with

46:38invalid parameters or some wrong JSON

46:41format. In this case, you would get a

46:43generic 400 repair request. But if a

46:46user makes a request to to get some

46:49product which is let's say the product

46:51with this ID and it doesn't exist in the

46:54database after querying it, then you

46:56should respond with the 404 status code,

46:59meaning that the resource has not been

47:01found. And lastly, we have 500 series.

47:04These are things when error happens in

47:06your server. So you don't know the exact

47:09reason and it's also not a client error

47:12meaning client requested everything

47:14properly. And in this case we throw

47:16unexpected server side errors. You

47:18generally respond with a server error

47:21message and you return the 500 status

47:24code along with it. When it comes to

47:26best practices of restful APIs, first of

47:29all notice that we are using plural

47:31nouns for all of the resources. So

47:34instead of slashroduct we are using

47:36/roducts for retrieving the products

47:39collection. So you should always use the

47:41plural in this case. Also in the crowd

47:45operations we use the proper HTTP

47:47methods. For example when making a

47:49request to delete users we expect to

47:52make a request to users/ ID of a user

47:55and not some post request to/ users/ ID.

47:59So first of all the HTTP methods needs

48:01to be properly set up and also the URL.

48:05We don't expect some random things like

48:07/dee to delete a resource from the

48:10database. As you saw we also support

48:12filtering sorting and pagination in good

48:15rest APIs. Not only pagination for

48:18example in this case we only have the

48:20page free but we cannot limit the amount

48:23of products that we want to retrieve.

48:25Whereas in this case we can fully

48:27control what we want to get from the

48:29API. We want to get the items from page

48:31three. We want this number of limit to

48:34be applied on the products. And we also

48:36want to apply some sort like sorting to

48:39sort the price or sort by ratings and so

48:42on. And also versionings in the restful

48:45APIs. As you noticed in all of these

48:48requests, they all come with a prefix

48:50which is / API and then slash the ID of

48:54the API which is either v_sub_1, v2, v3

48:57and so on. Let's say in the future you

49:00migrate your API and you start using

49:03bunch of new features but you also break

49:05something in the previous version one

49:07then if you use the versioning you won't

49:09break it on the front end because they

49:11can use the old version of your API and

49:14still use the old features and

49:16functionalities while you continue to

49:18develop the new version let's say

49:20version three and you support new

49:21features here and you might have broken

49:24something here but they are still using

49:26the old API so this doesn't impact the

49:29end users. So to recap, we learned about

49:32the rest architectural principles and

49:34constraints. Also about the resource

49:37modeling and URL design and how we model

49:40the business domain into the rest to

49:42full API domain. Also the status codes,

49:46error handling and the proper methods to

49:48be used with the basic crowd operations.

49:52And lastly, we covered the best

49:53practices for restful APIs that you

49:56should use to keep your APIs consistent

49:59and also predictable for other

50:01developers who are using it. Before we

50:03move on to the next section, just

50:05knowing these crowd operations and

50:07routes, it's good as a starting point.

50:10But if you've never built a restful API

50:13or graphqle API at the lower level and

50:16implemented these concepts, then this is

50:18not going to take you far. You need to

50:20also do the practice other than the

50:23theory. If you're a developer with 1 to

50:25five years of commercial experience

50:27based in US, Canada, Europe, Australia

50:30or New Zealand and you're stuck in

50:33junior to mid-level roles, but you want

50:35to move into senior positions, master

50:37API design and other concepts and start

50:40earning senior level salaries, then you

50:43can apply to work with me oneonone. This

50:45is exactly what I help developers do

50:47inside of my mentorship program. We take

50:50these concepts and apply them hands-on

50:52in real world projects. The same way

50:54senior engineers will work in top

50:56companies. So the first link in

50:58description is where you can apply. But

51:01only apply if you're serious about

51:02advancing to senior roles. Otherwise,

51:05our calendar is fully booked all the

51:07time. And if your application doesn't

51:09seem like a good fit, then unfortunately

51:12we'll have to cancel it. Traditional

GraphQL API Design

51:14restful APIs often return too much or

51:16too little data which requires us to do

51:19multiple requests for a single view to

51:21get all the data that we need. GraphQL

51:24solves this issue by giving clients

51:26exactly what they requested for. But

51:28designing GraphQL APIs is different from

51:30designing restful APIs. That's why in

51:33this video we'll cover the core concepts

51:35of GraphQL and why it exists. the schema

51:38design and type system of GraphQL,

51:41queries and mutations, error handling,

51:43and also best practices for designing

51:46GraphQL APIs. Let's start by

51:48understanding why GraphQL exists in the

51:50first place. It was created by Facebook

51:52to solve a very specific pain, which is

51:55clients needing to make multiple API

51:57calls and still not getting the exact

51:59data that they needed. For example, if

52:02you imagine we have the Facebook APIs

52:04like user API, posts API, comments and

52:07likes for the Facebook page. Most of the

52:10times client can make requests to all of

52:12these APIs separately and still not get

52:15all the data that it needs which will

52:17require it to do multiple requests to

52:19the same API. This of course adds up to

52:22the overall latency of the page because

52:25the page is still not loaded until all

52:27of these requests are made and the data

52:30is fetched. But in case of GraphQL APIs,

52:33you have a single GraphQL endpoint. So

52:35the client specifies the shape of the

52:37response and this one endpoint handles

52:40all of the data interactions. It is

52:42still an HTTP request, but as you can

52:44see, we can specify the exact data that

52:47we need. For example, we need the user

52:48with ID 1 2 3 and we need only the name

52:51of the user also posts and from the

52:54posts we can specify only title. So we

52:56don't need the images for this view. And

52:58again with the comments you can specify

53:00the exact data that you need within the

53:02object so that you are not doing

53:04overfetching of the data. Now let's see

53:07the schema design and type system of

53:09GraphQL and how it's different from

53:11restful APIs. The schema in this case is

53:14a contract between the client and

53:16server. In schema, first of all, you

53:18have types which can be for example user

53:20type that you specify and you specify

53:23all the fields that exist on this user

53:25type which are ID, name, posts and so

53:28on. And as you can see if the type is

53:30not a primitive type like posts then you

53:32can specify another type of post array

53:35and then this post type can be defined

53:37separately. Next we have queries to read

53:40data. So this is the equivalent of doing

53:43get requests in restful API. You specify

53:46the query and the function of this

53:48query. This can be the user query which

53:51fetches the user with specific ID and

53:54also the return type of this query which

53:56in this case is the user type that we

53:59defined above. And GraphQL also come

54:01with mutations. You can think of this as

54:04the equivalent to post, put, patch and

54:06delete methods in restful APIs. So

54:09anytime you are mutating a data in the

54:12database, you are making a mutation

54:14query. Here as you can see we have an

54:16example of create user method which

54:18accepts name and of course many things

54:20in real world and then it returns the

54:22user type that we have defined above. So

54:25if you have good schema design in

54:27GraphQL, it should mirror your domain

54:29model and it should be intuitive and

54:32flexible. Next, once you defined the

54:34schema design and type system, you can

54:36start querying and mutating data with

54:39this GraphQL API. For that, we have

54:41queries for fetching data. Again, this

54:43is like the get requests in restful

54:46APIs. And here you can specify exactly

54:48what you need from the user. This is the

54:50same user method that we defined there

54:52in the schema. So here you can also

54:55specify the exact attributes like the

54:57name posts and from posts you need the

55:00title only and this will make a request

55:02to your graphql API and return the exact

55:04data that you requested. Similarly you

55:07can also use the mutations that you

55:09defined. For example, if you have a

55:11create post method defined as a

55:13mutation, you can use this to mutate the

55:16post. for example, setting the title and

55:18body of the post and then you also

55:20specify what data you need to retrieve

55:22after this post is created which is ID

55:25and title. When it comes to error

55:27handling in GraphQL APIs, this is a bit

55:30different than in restful APIs since

55:32GraphQL always returns 200 okay status

55:35for all responses even if there was an

55:38error. In this case, we have to return

55:40errors field in the response which will

55:42indicate that there was an error. So

55:44partial data can still be returned with

55:47errors like in this case we have the

55:49user which is null and then we have the

55:51errors field which indicates that you

55:53have the status code 404 message not

55:55found and path which is the user in your

55:58schema. As you can see in this case you

56:00can specify the status code in the

56:02errors array. Since we are returning 200

56:05status codes for all GraphQL requests,

56:07that's why we have the status code

56:09specifically mentioned in the errors so

56:11that we know what kind of error this is,

56:13which is user not found. There are also

56:16best practices that we normally follow

56:18when designing GraphQL APIs. First of

56:21all, the schemas that we saw, it's a

56:22good practice to keep them small and

56:24modular. Also, we should avoid deeply

56:27nested queries. For example, you can

56:29have a user and then nested post and

56:31then within the post you can have a

56:33comment. So this can be infinitely

56:35nested and to avoid that we usually

56:37implement query limit depths which is

56:40how deep you can go like how many layers

56:43nested you can have in your data. So you

56:45specify something like six or seven

56:48layers deep. We also use meaningful

56:50naming for types and fields so that it

56:53also makes from the client side because

56:55they both are going to use the same

56:56schema. And when mutating data, we

56:59always use the input types for

57:01mutations. Before a system can authorize

Authentication

57:04or restrict anything, it first needs to

57:06know the identity of the requesttor.

57:09That's what authentication does. It

57:11verifies that the person or system

57:13trying to access your app is legit. And

57:15in this video, you'll learn how modern

57:17applications handle authentication from

57:19basic to bear tokens to OF2

57:22authentication and GVT tokens as well as

57:25access and refresh tokens and also

57:28single sign on and identity protocols.

57:31Before learning the different types,

57:33let's first understand what is

57:34authentication. Authentication basically

57:37answers who the user is and if they are

57:40allowed to access your system. So

57:42whenever a login request is sent either

57:44by the user or another service this is

57:47where we confirm the identity of the

57:49user and either provide them access so

57:52approve their request or reject it with

57:55unauthorized request. This is basically

57:58the first step before authorization

58:00begins which is the topic of the next

58:02lesson. So before you access any data or

58:05perform any actions on this service, the

58:08system needs to know who you are and

58:10this is where the authentication is

58:12used. The first and simplest type of

58:14authentication is basic authentication.

58:17This is where you use username and

58:19password in combination and you send a

58:22login request which contains the base 64

58:25encoded version of username and

58:27password. This is a very simple way of

58:30encoding data and it's easily

58:32reversible. And because it's easily

58:34reversible, it's now considered insecure

58:37unless it's wrapped within HTTPS. But

58:40even with that, it is now very rarely

58:42used outside of the internal tools in

58:45the company. Next, we have bearer tokens

58:48which are more secure compared to basic

58:50authentication. Here you send the access

58:53token with each request instead of the

58:55username and password encoding. So

58:57whenever the client needs to access

58:59resources, they send this token within

59:01the request and then your API verifies

59:04or rejects the token and if it verifies

59:07then you send the successful response

59:09with the data that they requested. Bear

59:12tokens are the standard approach

59:13nowadays especially in API design

59:16because it is fast and stateless which

59:19makes it easy to scale those APIs. The

59:22next type is O of2 authentication in

59:24combination with GVT tokens. So O of 2

59:28is a protocol which is the second

59:30version of OAF. It lets users login

59:34through a trusted provider like Google

59:36or GitHub. So user sends a request to

59:39access your resources and if you allow

59:42them to authenticate with Google,

59:44basically Google sends your app a GVT

59:46token which contains the information of

59:48this user. This is how that payload will

59:51look like. Usually they send you the

59:53user ID or the email, the username and

59:56more stuff and also the expiration date

59:58for this GVT tokens. This is a signed

1:00:02object which then you pass from your app

1:00:04to the API and then your API will

1:00:07authenticate based on this information.

1:00:10Give are also stateless similar to

1:00:12bearer tokens which means that you don't

1:00:14need to store sessions between their

1:00:16requests and each request can be

1:00:18executed separately. Next we also have

1:00:21access and refresh types of tokens. So

1:00:24modern systems use shortlived access

1:00:26tokens which expire faster and also long

1:00:29lift refresh tokens which usually expire

1:00:32later than the access tokens. Access

1:00:35tokens are used for API calls. So

1:00:37whenever you want to get some data from

1:00:39the API, you send this access token to

1:00:42access the data and refresh tokens on

1:00:45the other hand are used to renew the

1:00:48access tokens. So whenever the access

1:00:50token expires, this is where you will

1:00:52use the refresh token to get a new one,

1:00:55a new access token behind the scenes. So

1:00:58this way users won't be logged out. They

1:01:00will stay logged in and also your system

1:01:03will stay secure because you are

1:01:04frequently renewing this access token.

1:01:07And one note here is that you should

1:01:09typically keep the refresh tokens in the

1:01:11server side for security reasons. And

1:01:14lastly we have SSO which stands for

1:01:16single sign on and identity protocols

1:01:19that are used with it. Single sign on

1:01:21lets users to have one login. So login

1:01:24once and access multiple services. For

1:01:27example, when you log into Google, you

1:01:29can access both Gmail, Drive, and also

1:01:32Calendar and all of their other

1:01:34services. And behind the scenes, this

1:01:36SSO uses either SL protocol or O of 2

1:01:40protocol. Oaf2 is used more often

1:01:43nowadays for the modern applications to

1:01:46login with Google or with GitHub or any

1:01:49other service provider. It is a modern

1:01:51and JSON based. And on the other hand,

1:01:54SL protocol uses XML based approach. But

1:01:57still, SL is very popular in the legacy

1:02:00systems and in companies that use things

1:02:03like Salesforce or internal dashboards.

1:02:06So these are identity protocols which

1:02:08means that they will define how apps

1:02:10securely exchange the user login

1:02:12information between each other. But

1:02:14authentication is just the first step

1:02:16before users can access your service. So

1:02:19this tells you who the user is and if

1:02:22they are allowed to access your service.

1:02:24That is when they send a login request

1:02:26and you confirm or deny their identity.

1:02:29But after that you also have the

1:02:31authorization step which tells you what

1:02:33resources exactly this user can access

1:02:36to. Basically it tells you what they can

1:02:38do what the user can do in your system

1:02:41and that is what we will cover next in

1:02:43the next video. Before getting into

1:02:46authorization, there is a difference

1:02:48between how juniors would implement such

1:02:50authentication models and how seniors

1:02:52would implement it. Senior developers

1:02:55know that authentication is about

1:02:57securing tokens, refresh flows, and

1:02:59preventing attacks. And they also build

1:03:01it in a secure way while considering the

1:03:04tradeoffs. If you only know the theory,

1:03:07then companies will see it right through

1:03:09you. And if you want to implement those

1:03:11at a lower level with my guidance and

1:03:13one-on-one support, then that's why we

1:03:15have the mentorship program. If you're a

1:03:18developer with 1 to 5 years of

1:03:20commercial experience based in US,

1:03:22Canada, Europe, Australia, or New

1:03:25Zealand, and you're stuck in junior to

1:03:27mid-level roles, but you want to move

1:03:29into senior positions, master API design

1:03:32and other concepts and start earning

1:03:34senior level salaries, then you can

1:03:36apply to work with me oneonone. This is

1:03:39exactly what I help developers do inside

1:03:41of my mentorship program. We take these

1:03:44concepts and apply them hands-on in real

1:03:46world projects. The same way senior

1:03:48engineers will work in top companies. So

1:03:51the first link in description is where

1:03:53you can apply. But only apply if you're

1:03:55serious about advancing to senior roles.

1:03:58Otherwise, our calendar is fully booked

1:04:00all the time. And if your application

1:04:03doesn't seem like a good fit, then

1:04:04unfortunately we'll have to cancel it.

Authorization

1:04:07Authorization is the step that happens

1:04:09after authentication. Once someone is

1:04:11logging in into our system. So once the

1:04:14login request is approved which means

1:04:16that the system now knows who the user

1:04:18is. The next step is deciding what they

1:04:20can do which is the step of

1:04:22authorization. It needs to check what

1:04:24resources or actions that user has

1:04:26permissions to access and also what are

1:04:29the denied actions for this user. This

1:04:31is how we control security and privacy

1:04:34in the systems. And in this video you'll

1:04:36learn how applications and systems

1:04:38manage permissions using the three main

1:04:40authorization models. The first one is

1:04:43role based access control. Next we have

1:04:45attribute based access control. Also

1:04:48access control list which is another way

1:04:50of managing authorization. Plus you'll

1:04:53learn how technologies like of2 and gvts

1:04:56help us to enforce those rules in

1:04:58practice. So authentication happens

1:05:00first which tells us who the user is and

1:05:03if they are allowed to access our

1:05:04system. But on the next step we have

1:05:06authorization which determines what you

1:05:09can actually do as a user in this

1:05:11system. If we take a look at GitHub as

1:05:14an example and accessing repositories on

1:05:16GitHub there you have different

1:05:18permissions for different users. For

1:05:20example, user A can have write access

1:05:22only which means they can only push code

1:05:24to this repo. But on the other hand, we

1:05:27can have user B and here you can grant

1:05:29only read access which means they can

1:05:31only read this repository but they

1:05:33cannot push code to it or they cannot

1:05:36create pull requests and so on. And on

1:05:38the other side we can have also admin

1:05:40users which have full control. So they

1:05:43can manage all the settings for the

1:05:44repository. They can even decide to

1:05:46delete this repository and so on. So you

1:05:49can see that different users can have

1:05:51different access controls on systems. To

1:05:54manage these access controls, we have

1:05:56common authorization models. So the one

1:05:59that we just looked at is the role based

1:06:01authentication model which assigns roles

1:06:04to users something like admin, editor or

1:06:06readonly access, write access. And this

1:06:09is the most common approach among these

1:06:12authorization models. But we also have

1:06:14attribute-based access control which is

1:06:17based on the user or resource

1:06:19attributes. So this is more flexible and

1:06:22more complex compared to the role-based

1:06:24authentication. And the other common

1:06:27approach is to have access control lists

1:06:29ACL and each resource here has its own

1:06:32permissions list. So you can assign

1:06:34permission lists to a resource and this

1:06:37is what will determine what resources

1:06:39you can access. For example, this is a

1:06:41common way of managing Google Docs and

1:06:43we will look at this in more detail now.

1:06:46And each of these models has its

1:06:48tradeoffs, pros and cons. So this

1:06:50depends on the specific system

1:06:52requirements. But real systems often

1:06:55combine also multiple models together to

1:06:57have more complex and more secure setup.

1:07:01So first up we have role- based access

1:07:03control or RBAC as an an acronym. Here

1:07:06users are assigned to roles and each

1:07:09role has a defined set of permissions.

1:07:11For example, as you saw with the GitHub,

1:07:13you can have admins and admins usually

1:07:15have full access to all resources. So

1:07:18they can create, they can read or update

1:07:21resources. They can even delete

1:07:22resources and also manage other users in

1:07:25the roles. And next you have editor

1:07:28which is usually a bit less than admin.

1:07:31So they can edit content like creating

1:07:33or reading content or updating resources

1:07:36but they cannot delete resources and

1:07:38they cannot also manage other users. And

1:07:41next you can have viewer users which can

1:07:44only read data. So they can read the

1:07:46resources and content but they cannot

1:07:49update anything or they cannot create

1:07:51anything in your system. This is the

1:07:53most common way in authorization models

1:07:56and this is used in apps that you use

1:07:58daily like you saw with GitHub or stride

1:08:01dashboards or CMS tools, team management

1:08:04tools and so on. The next model is

1:08:07attribute-based access control or ABAC

1:08:10in short. This access control goes

1:08:12beyond the roles. So it uses the user

1:08:15attributes or resource attributes and

1:08:18environment conditions to define the

1:08:20access. Some example policy you can see

1:08:23here. Let's say you want to only allow

1:08:25access if some conditions are met. In

1:08:28this case, whenever the user department

1:08:30is set to HR and you can combine this

1:08:32with multiple conditions like whenever

1:08:34the resource attribute equals to

1:08:37internal and so on and only in this case

1:08:40you allow them access and you either

1:08:42allow them read access or write access.

1:08:44So this can also be combined with the

1:08:46role based authorization but in this

1:08:49case you are checking the user model or

1:08:52resource model in your database and

1:08:54based on the attributes you either allow

1:08:57or deny the access. So here as you can

1:08:59see we are checking user attributes like

1:09:02the department the age or whatever you

1:09:04want to check here. Next, you can also

1:09:07combine it with resource attributes like

1:09:09confidentiality or the owner of the

1:09:12resource or classification. And this can

1:09:15also be combined with environment like

1:09:17time of the day, location, device type,

1:09:20and so on. Since you're combining these

1:09:22attributes to either grant or restrict

1:09:25access, this is more flexible than the

1:09:27role-based authorization, but it

1:09:29requires good policy management and

1:09:31generally it's more complex and you can

1:09:34encounter conflicts here with the

1:09:36attribute-based access control. The

1:09:38third common type is the access control

1:09:41lists. Instead of providing role based

1:09:43access or attribute-based access, you

1:09:45can have access control list for the

1:09:47specific resource. Let's say you have a

1:09:50resource like a document or a JSON file

1:09:53and here you can have a permission list

1:09:55on which users can access this document

1:09:58like user Alice has only read access or

1:10:01user Bob has both read and write access

1:10:04and another user has no access to this

1:10:07document. So as you can see we're

1:10:09managing two things here. First of all

1:10:11which users are allowed to access this

1:10:13document and second what are their

1:10:16permissions. So each of the users has

1:10:18different permissions on this document.

1:10:21ACL's are highly specific and also user

1:10:24centric which means it's hard to scale

1:10:26them well in systems with millions of

1:10:29users or objects unless you manage them

1:10:32carefully. But for example, Google Drive

1:10:35is one example of this where you have

1:10:37documents like a Google doc and then you

1:10:40share this Google doc with your

1:10:42colleagues, right? So you share someone

1:10:44with read access only and then you share

1:10:46this doc with someone else but now they

1:10:48can also edit and add comments to this

1:10:51document. So this is a example of ACL

1:10:55access control list which is used in

1:10:57Google drive and Google documents. This

1:11:00gives you more control over resources

1:11:02and documents, but it's also harder to

1:11:05scale with millions of users. But it's

1:11:07possible as you can see because Google

1:11:09Drive is using this for their documents,

1:11:11Excel sheets and so on. So these were

1:11:14the access control models. But how do

1:11:17systems enforce those authorizations?

1:11:19These are where O of 2 and GVt or access

1:11:23tokens come into play. So first we have

1:11:25OF2 which is delegated authorization

1:11:28which is a protocol used when service

1:11:31wants to access another services

1:11:33resources on a behalf of a user. For

1:11:36example, if you want to let a third

1:11:38party app read your GitHub repositories.

1:11:41Let's say you're deploying your app to

1:11:43Versel. So you need to give Versel

1:11:45control over your repository on GitHub.

1:11:49Instead of giving your username and

1:11:51password to the third party application

1:11:53which won't be secure at all because you

1:11:56don't know what they can do with your

1:11:57username and password. This way you are

1:11:59giving them full control. Instead,

1:12:01GitHub gives them the token that

1:12:04represents the permissions which you

1:12:06approved to use. So you as a user send a

1:12:09request with the third party app to

1:12:12request access to your repositories and

1:12:15then GitHub gives you the access token

1:12:17which you should create. So you should

1:12:19also provide what resources, what

1:12:21repositories this third party app can

1:12:24access and also what they can do. Can

1:12:26they create, read, update or can they

1:12:28delete or whatever the permissions you

1:12:30set and then GitHub sends them the token

1:12:33which contains the permissions which

1:12:35this third party app is allowed to use

1:12:38and OF2 defines the flow for securely

1:12:40issuing and validating those tokens. So

1:12:43you give them the access token and not

1:12:46your password which represents the

1:12:48permissions that you approve personally.

1:12:50So it can be reading specific repos or

1:12:53also creating pushing to those

1:12:55repositories but not deleting those

1:12:57repositories. And next we have also

1:13:00token based authorization using GVt or

1:13:03bearer tokens and permission logic. Once

1:13:05a user is authenticated, most systems

1:13:08use a token typically a GV token or this

1:13:11can be also bear token that carries this

1:13:14information like user ID, the roles like

1:13:17admin or editor and also scopes which is

1:13:20what scopes they are allowed to access

1:13:23and whenever this token is expiring and

1:13:26who is the issuer of this token. So

1:13:29whenever a user makes a request, it

1:13:31always carries this token information

1:13:33and reaches to the backend server. This

1:13:35is where the server will check your

1:13:37token and validity and it will apply the

1:13:40appropriate permission logic. So to not

1:13:43confuse this with authorization models,

1:13:45there is a key distinction. The token

1:13:47usually carries the identity and claims

1:13:50of your user as you see it here. But

1:13:52authorization models like role based or

1:13:55attribute-based this is what defines

1:13:57what is allowed to access as a user. So

1:14:00tokens are just mechanisms while these

1:14:03are authorization models. So in summary

1:14:06authorization isn't just letting users

1:14:08in like authentication but it also

1:14:10controls what they can access once they

1:14:12are in. We learned what authorization

1:14:15is, what are the three most common

1:14:17authorization models which are role

1:14:19based, attribute-based and access

1:14:21control lists. And also you saw a couple

1:14:23of real world examples like how GitHub

1:14:26manages your authorization tokens. And

1:14:28this should give you an idea on when to

1:14:30use each model based on the system that

1:14:32you're building. And you also saw some

1:14:35implementation patterns with O of 2 or

1:14:37GVT tokens. Each of these models has

1:14:40their own trade-offs, their own pros and

1:14:43cons, and real systems often combine

1:14:45multiple models to stay flexible and

1:14:47secure. APIs are like doors into your

Security

1:14:50system. If you leave them unprotected,

1:14:52then attackers and anyone can walk right

1:14:55in and do whatever they want with your

1:14:57user data and overall the system. That's

1:15:00why in today's video, we'll look at

1:15:02seven proven techniques which will help

1:15:04you to protect your APIs from unwanted

1:15:06attacks. The first one we have in the

1:15:08list is rate limiting which controls how

1:15:11many requests a client can make in a

1:15:14given time. For example, you can set a

1:15:16limit for user A to make let's say 100

1:15:19requests per some period of time to your

1:15:22API. And if they cross that limit and

1:15:24let's say make 101 requests, then you

1:15:27block the next request and allow some

1:15:30time to pass before they can send their

1:15:32next request. If you don't set this to

1:15:35your API, then attackers can overwhelm

1:15:37your system. They can send like

1:15:39thousands of requests per minute and

1:15:41then overwhelm your API which will take

1:15:44your system down or it can also brute

1:15:46force your data. And these rate limits

1:15:48can be set per endpoint. For instance,

1:15:51let's say you have some /comments

1:15:53endpoint and here they can send a

1:15:55request to either create a comment or

1:15:57fetch comments. You can set that limit

1:15:59for endpoint level. So these comments

1:16:02endpoint will be set to some strict

1:16:05number of requests per minute. You can

1:16:07also set it per user or IP address.

1:16:10Let's say in a we have the IP address of

1:16:13first user and then B for the second, C

1:16:15for this one and your attacker has some

1:16:18IP address which corresponds to D. If

1:16:20you get the 101 request from the D IP

1:16:25address, then you will know that this

1:16:27user overused the API. So you will block

1:16:30it at the user IP level. And there is

1:16:33also overall rate limiting to protect

1:16:35from DDOS attacks. Since you can set the

1:16:38rate limit to work per user or per IP

1:16:41address, that means that this attacker

1:16:43alone cannot send that many requests.

1:16:46You will block it with your rate

1:16:47limiting in the API. But what they can

1:16:50do is they can spin up some bots and

1:16:52each bot will have their own limit,

1:16:54right? Let's say you've set it to 100

1:16:57per IP address. So each of these boats

1:16:59has 100 and overall they have more than

1:17:02you would allow or your system could

1:17:05handle. That's why you have also overall

1:17:07rate limitings which can be some bigger

1:17:10number. So whenever all the traffic

1:17:12coming into your server reaches or

1:17:15passes this number then you will

1:17:17temporarily block all requests until you

1:17:19find out the root cause. And of course

1:17:22these numbers are just examples. So in

1:17:24reality it's much more than thousand but

1:17:26that's just an example. The second one

1:17:29on the list is course which stands for

1:17:31cross origin resource sharing. This

1:17:34controls which domain can call your API

1:17:36from a browser and without proper course

1:17:39malicious websites could trick users

1:17:41browsers into making requests on their

1:17:44behalf. For instance, if your API is

1:17:47only meant to serve your front-end app

1:17:49which is at app.youdomain.com

1:17:50yourdommain.com

1:17:52then only requests from this source

1:17:55should be allowed. If anyone else sends

1:17:57you a request like up another domain.com

1:18:00then you should block this request and

1:18:02not allow them to use your API for

1:18:05authenticating or using any of its data.

1:18:08The third one is also a common one which

1:18:10is SQL and NoSQL injections. Injection

1:18:14attacks can happen when the user input

1:18:16is directly included in the database

1:18:18query. For instance, attacker can modify

1:18:21it and send some queries to read or

1:18:24delete your data. Here, for example,

1:18:26this part bypasses the checks entirely

1:18:29and then attacker can use this query to

1:18:32start reading data from your database or

1:18:34modify anything or they can also delete

1:18:37all the data, all the user data and any

1:18:40other tables that you have in this

1:18:41database. So to fix this, we always use

1:18:45parameterized queries or OM safeguards.

1:18:48The next technique to use is firewalls.

1:18:51Uh firewall acts as a gatekeeper

1:18:54filtering the malicious traffic from the

1:18:56other normal traffic. So typically you

1:18:59have it between your API and the

1:19:01incoming traffic. For example, if you

1:19:04use the AWS's web application firewall,

1:19:07these can block requests with unknown

1:19:09attack patterns such as suspicious SQL

1:19:12keywords or strange HTTP methods, which

1:19:15means it will block any suspicious

1:19:16requests from attackers, but it will

1:19:19allow others to bypass the request and

1:19:22reach to your API. Some APIs are also

1:19:25private and should only be accessed from

1:19:27specific networks. That's why we have

1:19:29also VPNs which stand for virtual

1:19:32private networks. The APIs that are

1:19:34within the VPN network can only be

1:19:37accessed by someone who is also within

1:19:40that same network. Which means that some

1:19:42APIs are public facing meaning these

1:19:44APIs will allow any requests from the

1:19:47internet from your users. But this for

1:19:50example can be within the VPN network.

1:19:52Which means if a user from web tries to

1:19:55reach your API then this request will be

1:19:58blocked because the user is not within

1:20:00the same network. But on the other hand

1:20:03if you have another user here which is

1:20:05within the VPN network they can make a

1:20:07request to these APIs and in this case

1:20:10they will bypass the checks and their

1:20:12request will reach to your APIs. This is

1:20:15useful where you have internal tools.

1:20:17Let's say you have internal admin

1:20:19dashboard and the API for this admin

1:20:21panel will only be reachable by

1:20:24employees connected to the company VPN.

1:20:27Next, we have CSRF, which stands for

1:20:29cross-sight request forgery. This tricks

1:20:32a logged in user's browser into making

1:20:34unwanted requests to the API. Let's say

1:20:37you as a user are logged in into your

1:20:40bank system and your bank system uses

1:20:42cookies for authentication. If the bank

1:20:45system is not secure and they only use

1:20:48session cookies, another malicious site

1:20:50might use your cookie and submit a

1:20:52hidden transferring money request

1:20:54through your cookie. So to prevent such

1:20:57attacks, companies also use CSRF tokens

1:21:00in combination with session cookie. So

1:21:02the banking system will check if the

1:21:04session cookie is present but it will

1:21:07also check if the CSRF token matches

1:21:09with the one that they have and if it

1:21:12doesn't then it will block this request

1:21:14from the other unknown source while it

1:21:16will allow request from your behalf. And

1:21:19the last one we have is XSS or it's also

1:21:22called cross-sight scripting. This lets

1:21:24attackers to inject scripts into web

1:21:27pages served to other users. For

1:21:30example, if you have a comment section

1:21:32and this comment gets submitted to your

1:21:35API. Next, your API will also store it

1:21:37in a database. You can get normal

1:21:40requests like nice picture or something

1:21:42like that and this will get to your API.

1:21:44Your API will store it in the database.

1:21:47So everything is fine there. But what if

1:21:49an attacker places a script in this

1:21:52comment section and within this script

1:21:55they can try to do many different

1:21:57things. For example, they can try to

1:21:59fetch the cookie for another user or

1:22:01they can try to inject something into

1:22:04your database. And if you allow this,

1:22:06then it will reach to your server and

1:22:08the information will be written into the

1:22:11database. Later when the other users

1:22:14load these comments section on their

1:22:16screen, they will get also the injected

1:22:19comment directly into their web page and

1:22:21the browser will execute this malicious

1:22:24JavaScript code into the other users

1:22:26browser. Before ending the video, again

1:22:29reminding you about the mentorship

1:22:31program. If you're a developer with one

1:22:33to five years of commercial experience

1:22:35based in US, Canada, Europe, Australia,

1:22:38or New Zealand, and you're stuck in

1:22:40junior to mid-level roles, but you want

1:22:43to move into senior positions, master

1:22:45API design and other concepts and start

1:22:48earning senior level salaries, then you

1:22:50can apply to work with me oneon-one.

1:22:53This is exactly what I help developers

1:22:55do inside of my mentorship program. We

1:22:57take these concepts and apply them

1:22:59hands-on in real world projects. The

1:23:02same way senior engineers will work in

1:23:04top companies. So the first link in

1:23:06description is where you can apply. But

1:23:08only apply if you're serious about

1:23:10advancing to senior roles. Otherwise,

1:23:13our calendar is fully booked all the

1:23:15time. And if your application doesn't

1:23:17seem like a good fit, then unfortunately

1:23:19we'll have to cancel

Recently added transcripts

Browse the whole transcript library

This transcript was generated from the captions YouTube publishes for this video. Get the transcript of any YouTube video atfreeyoutubetranscribe.com, free, unlimited, no sign-up.