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