<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Andrii Bui</title>
    <description>The latest articles on DEV Community by Andrii Bui (@andreyka26git).</description>
    <link>https://dev.to/andreyka26git</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F862395%2F22b43a3d-d2ab-431f-9d88-afd8195bb055.jpeg</url>
      <title>DEV Community: Andrii Bui</title>
      <link>https://dev.to/andreyka26git</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/andreyka26git"/>
    <language>en</language>
    <item>
      <title>Authorization &amp; Authentication from backend perspective pt1</title>
      <dc:creator>Andrii Bui</dc:creator>
      <pubDate>Sun, 05 Jun 2022 10:16:51 +0000</pubDate>
      <link>https://dev.to/andreyka26git/authorization-authentication-from-backend-perspective-pt1-2239</link>
      <guid>https://dev.to/andreyka26git/authorization-authentication-from-backend-perspective-pt1-2239</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;I keep doing my tech blog here: &lt;a href="https://andreyka26.com/" rel="noopener noreferrer"&gt;https://andreyka26.com/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To be honest I planned to write this article about a year ago, because for a long time the &lt;strong&gt;authentication &amp;amp; authorization&lt;/strong&gt; process was for me kind of not so clear. I didn’t find any book or article which in simple words can show the whole picture of that process, especially digging into details.&lt;/p&gt;

&lt;p&gt;So in that article we are covering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is auth&lt;/li&gt;
&lt;li&gt;What types of auth could be&lt;/li&gt;
&lt;li&gt;As one of the types we will consider &lt;strong&gt;Basic&lt;/strong&gt; and &lt;strong&gt;Digest&lt;/strong&gt;(with our samples in .NET).&lt;/li&gt;
&lt;li&gt;In the next part of this article we will take a look at &lt;strong&gt;OAuth and OpenId Connect&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article should be useful for people who managed to get the RFC but didn’t get completely &lt;strong&gt;OAuth&lt;/strong&gt; flow. I am here to help you, because I was in the same situation.&lt;br&gt;
Note: I am using official info like RFC or the documentation provided by specific tools, so you can check everything by yourself if you want to. &lt;/p&gt;

&lt;p&gt;Git repository with samples: &lt;a href="https://github.com/andreyka26-git/dot-net-samples/tree/main/AuthorizationSample" rel="noopener noreferrer"&gt;https://github.com/andreyka26-git/dot-net-samples/tree/main/AuthorizationSample&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Definitions
&lt;/h2&gt;

&lt;p&gt;Prior to starting to talk about different approaches to &lt;strong&gt;authentication and authorization&lt;/strong&gt;, we should consider the definitions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Authorization &amp;amp; Authentication&lt;/strong&gt;&lt;br&gt;
From Wikipedia: “&lt;strong&gt;Authorization&lt;/strong&gt; is the function of specifying access rights/privileges to resources, which is related to general information security and computer security, and to access control in particular”.&lt;/p&gt;

&lt;p&gt;From MSDN: “&lt;strong&gt;Authorization&lt;/strong&gt; is the process of determining whether a user has access to a resource. &lt;strong&gt;Authentication&lt;/strong&gt; is the process of determining a user's identity”.&lt;/p&gt;

&lt;p&gt;From Martin Fowler’s blog: “&lt;strong&gt;Authorization&lt;/strong&gt; defines whether a user is allowed to do something.&lt;br&gt;
&lt;strong&gt;Authentication&lt;/strong&gt; confirms that the users are who they claim to be”.&lt;/p&gt;

&lt;p&gt;You could pick up whatever definition you like, they are basically the same.&lt;br&gt;
I unite &lt;strong&gt;Authorization &amp;amp; Authentication&lt;/strong&gt; to “&lt;strong&gt;auth&lt;/strong&gt;” because most usually (and in examples we’ll see that) - the authorization is impossible without &lt;strong&gt;authentication&lt;/strong&gt;. If you don’t know who the &lt;strong&gt;User&lt;/strong&gt; is - you cannot say what the User is allowed to do via &lt;strong&gt;Client&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. API or Resource Server&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In terms of &lt;strong&gt;OAuth&lt;/strong&gt;it is named “&lt;strong&gt;Resource Server&lt;/strong&gt;”, but for simplicity let me put it in the following way: it is the &lt;strong&gt;Server&lt;/strong&gt; (just a piece of software running on some machine) that handles requests from the &lt;strong&gt;Client&lt;/strong&gt; and sometimes needs the Client to be authorized to get the correct response. &lt;br&gt;
Why sometimes? Because &lt;strong&gt;API&lt;/strong&gt; may contain a public endpoint which doesn’t need auth at all. If all endpoints in the &lt;strong&gt;API&lt;/strong&gt; are public (can be accessed without authorization) - there is no need to use auth. That’s why we will consider all endpoints on the &lt;strong&gt;API&lt;/strong&gt; as protected ones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Client&lt;/strong&gt;&lt;br&gt;
The &lt;strong&gt;Client&lt;/strong&gt; is basically a piece of software which talks to the &lt;strong&gt;API&lt;/strong&gt; and needs to authorize requests (when the endpoints are not public). Most usually this software runs on some device (mobile, desktop, and browser) and &lt;strong&gt;User&lt;/strong&gt; is interacting with the &lt;strong&gt;API&lt;/strong&gt; using &lt;strong&gt;Client&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. User&lt;/strong&gt;&lt;br&gt;
In terms of &lt;strong&gt;OAuth&lt;/strong&gt; the &lt;strong&gt;resource owner&lt;/strong&gt; - is most usually a person who would like to use the &lt;strong&gt;Client&lt;/strong&gt; and the application itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Authorization Server&lt;/strong&gt;&lt;br&gt;
This &lt;strong&gt;Server&lt;/strong&gt; is fully responsible for identity of the user, authentication, and creating tokens. This enables you just to use some verification based on signatures (on &lt;strong&gt;Resource Server&lt;/strong&gt;) and to not worry about implementation details of authentication.&lt;br&gt;
We will use this term in the next part for &lt;strong&gt;OAuth&lt;/strong&gt; and &lt;strong&gt;OpenId Connect&lt;/strong&gt;. For this part it is not possible to decouple &lt;strong&gt;Authorization Server&lt;/strong&gt; from &lt;strong&gt;Resource Server&lt;/strong&gt;. So I will refer to &lt;strong&gt;API&lt;/strong&gt;, &lt;strong&gt;Resource Server&lt;/strong&gt;, &lt;strong&gt;Authorization Server&lt;/strong&gt; or just &lt;strong&gt;Server&lt;/strong&gt; as to the same thing in this part.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flow
&lt;/h2&gt;

&lt;p&gt;The basic flow looks like that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;User&lt;/strong&gt; wants to interact with the application somehow, this makes the &lt;strong&gt;Client&lt;/strong&gt; send and receive data from &lt;strong&gt;API&lt;/strong&gt; back and forth. Since the &lt;strong&gt;API&lt;/strong&gt; has protected endpoints - it requires the &lt;strong&gt;Client&lt;/strong&gt; to authorize its requests, and responds with 401 Not Authorized.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;Client&lt;/strong&gt; then should firstly authenticate the user - make the request to the &lt;strong&gt;Server&lt;/strong&gt; in order it confirms the &lt;strong&gt;User&lt;/strong&gt; is who he claims to be. It may be the same &lt;strong&gt;Server&lt;/strong&gt; where the API is serving or a standalone Server. &lt;br&gt;
Most usually authentication is performed by sending the login and password (some identity) of the &lt;strong&gt;User&lt;/strong&gt; to the &lt;strong&gt;Server&lt;/strong&gt; which responds with a ticket (sequence of characters, typically signed or encrypted so the &lt;strong&gt;API&lt;/strong&gt; can validate). This ticket can be used to access the &lt;strong&gt;API&lt;/strong&gt;. Most usually this ticket is either a token or cookies (see section about &lt;strong&gt;OAuth&lt;/strong&gt; and &lt;strong&gt;OpenId Connect&lt;/strong&gt;). Meanwhile, for sure, the &lt;strong&gt;Server&lt;/strong&gt; should have information about this user (to be able to say this login + password does exist and what he has access to).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;Client&lt;/strong&gt; performs a request to the &lt;strong&gt;API&lt;/strong&gt; including the authorization ticket (either token or cookies) - and then it can get the response from it.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The most common approach for implementing &lt;strong&gt;auth&lt;/strong&gt; is to use &lt;strong&gt;auth&lt;/strong&gt; tokens in headers. For sure there are other ways like sessions. But the main advantage of tokens is that they are stateless: you are not required to make other requests prior to the current one to be authorized. You only need to use the appropriate token.&lt;br&gt;
The token is kept via request headers in the following format: “Authorization:  ”. &lt;br&gt;
Basically scheme means the way you can create or get your token and validate it, so let’s consider most popular auth schemes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Auth schemes
&lt;/h2&gt;

&lt;p&gt;There are many schemes that can be used to make the auth. There may be custom ones, but we will consider the most popular ones.&lt;br&gt;
There are resources where you can find all commonly used schemes and RFC documentation for each of them: &lt;a href="https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml" rel="noopener noreferrer"&gt;https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic Scheme
&lt;/h2&gt;

&lt;p&gt;RFC: &lt;a href="https://www.rfc-editor.org/rfc/rfc7617.html" rel="noopener noreferrer"&gt;https://www.rfc-editor.org/rfc/rfc7617.html&lt;/a&gt;&lt;br&gt;
Wikipedia: &lt;a href="https://en.wikipedia.org/wiki/Basic_access_authentication" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Basic_access_authentication&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is the simplest auth scheme:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;get username and password&lt;/li&gt;
&lt;li&gt;concatenate them with “:” &lt;/li&gt;
&lt;li&gt;encode with Base64&lt;/li&gt;
&lt;li&gt;send request with Authorization header&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server&lt;/strong&gt; validates username and password internally&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Using this scheme we cannot decouple &lt;strong&gt;Auth&lt;/strong&gt; from &lt;strong&gt;Resource server&lt;/strong&gt;. So for each request the &lt;strong&gt;Server&lt;/strong&gt; should get all info from the Authorization header, authenticate the &lt;strong&gt;User&lt;/strong&gt; and then authorize him as well. It means that &lt;strong&gt;API&lt;/strong&gt; should know who is the &lt;strong&gt;User&lt;/strong&gt; (store him or know where to get it). To be able to decouple we will consider JWT tokens later on.&lt;/p&gt;

&lt;p&gt;Note: encoding to base64 is needed for encoding special characters, to ensure the string contains only ASCII characters it &lt;strong&gt;will not&lt;/strong&gt; give you any security layer.&lt;br&gt;
Since the user passes his credentials in a raw state - it is required to use one more security layer on top of HTTP application layer - TLS.&lt;/p&gt;

&lt;p&gt;Basic Auth Server: &lt;a href="https://github.com/andreyka26-git/dot-net-samples/tree/main/AuthorizationSample/Basic.Server" rel="noopener noreferrer"&gt;https://github.com/andreyka26-git/dot-net-samples/tree/main/AuthorizationSample/Basic.Server&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Basic Auth Client:&lt;br&gt;
&lt;a href="https://github.com/andreyka26-git/dot-net-samples/tree/main/AuthorizationSample/Basic.WebClient" rel="noopener noreferrer"&gt;https://github.com/andreyka26-git/dot-net-samples/tree/main/AuthorizationSample/Basic.WebClient&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr0zfuvd1m52gg0dqzhzu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr0zfuvd1m52gg0dqzhzu.png" alt=" " width="800" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BasicAuthenticationHandler&lt;/strong&gt; first does the authentication: it extracts username and password from header (decoding base64) and ensures this user does exist (in our case it is a simple if statement, but in real case it should hash the pass and check it along with username). It does it for every request, because we used &lt;strong&gt;&lt;em&gt;.UseAuthorization() .UseAuthentication()&lt;/em&gt;&lt;/strong&gt; middleware registration methods.&lt;/p&gt;

&lt;p&gt;But this is the &lt;strong&gt;Authentication&lt;/strong&gt; part of it, we only checked that the user is who he claims to be. &lt;br&gt;
After &lt;strong&gt;BasicAuthenticationHandler&lt;/strong&gt; did the authentication part we will have &lt;strong&gt;User.Identity&lt;/strong&gt; in each endpoint, and based on this identity we can do &lt;strong&gt;Authorization&lt;/strong&gt; - to verify whether this particular user is allowed to access this endpoint or not.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb66yanxmlw95lnrq3svc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb66yanxmlw95lnrq3svc.png" alt=" " width="604" height="212"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However &lt;strong&gt;Basic Auth&lt;/strong&gt; is so simple it brings a few problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is not secured, you need to send your unencrypted unhashed password through the network&lt;/li&gt;
&lt;li&gt;It doesn’t have any defined way of logging out and logging in the user.&lt;/li&gt;
&lt;li&gt;No built in protocol for giving different permissions for different endpoints, roles, etc. Meaning, that Resource Server will not have claims (role, static, etc) which it can validate in token. This forces each &lt;strong&gt;Resource Server&lt;/strong&gt; to know all user permissions and store it inside.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;API&lt;/strong&gt; should know user (store it)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Digest Scheme
&lt;/h2&gt;

&lt;p&gt;RFC: &lt;a href="https://datatracker.ietf.org/doc/html/rfc7616" rel="noopener noreferrer"&gt;https://datatracker.ietf.org/doc/html/rfc7616&lt;/a&gt;&lt;br&gt;
Wikipedia: &lt;a href="https://en.wikipedia.org/wiki/Digest_access_authentication" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Digest_access_authentication&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First of all I should mention that this sample I rewrite from this repo, so you can see original version: &lt;a href="https://github.com/flakey-bit/DotNetDigestAuth" rel="noopener noreferrer"&gt;https://github.com/flakey-bit/DotNetDigestAuth&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is a little bit complicated &lt;strong&gt;auth&lt;/strong&gt; flow compared to &lt;strong&gt;Basic Auth&lt;/strong&gt;. It doesn’t pass a password through the network, instead of this we are creating and storing some hashes.&lt;/p&gt;

&lt;p&gt;Using this scheme we cannot decouple &lt;strong&gt;Auth&lt;/strong&gt; from &lt;strong&gt;Resource server&lt;/strong&gt;. So for each request the &lt;strong&gt;Server&lt;/strong&gt; should get all info from the Authorization header, authenticate the User and then authorize him as well. It means that &lt;strong&gt;API&lt;/strong&gt; should know who is the &lt;strong&gt;User&lt;/strong&gt; (store him or know where to get it). To be able to decouple we will consider JWT tokens later on.&lt;/p&gt;

&lt;p&gt;This flow requires you to call the endpoint 2 times if you are not authenticated. First you should receive 401 with necessary headers and the next call is done with a generated digest token (on &lt;strong&gt;Client&lt;/strong&gt; side) based on those headers.&lt;/p&gt;

&lt;p&gt;Prior to explaining the flow we should introduce some terminology:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Username&lt;/strong&gt; - just login provided by user&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Password&lt;/strong&gt; - just password provided by user&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Realm&lt;/strong&gt; - area which you can access with a particular digest ticket, something similar to scope in &lt;strong&gt;OAuth&lt;/strong&gt;.  You might return the same &lt;strong&gt;realm&lt;/strong&gt; value for some particular set of endpoints and you will have access to those endpoints with the same &lt;strong&gt;auth&lt;/strong&gt; ticket.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nonce (number once)&lt;/strong&gt; - &lt;strong&gt;Server&lt;/strong&gt; generated string which should be unique for all 401 responses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CNonce&lt;/strong&gt; (client nonce) - &lt;strong&gt;Client&lt;/strong&gt; generated string which should be sent and verified by the &lt;strong&gt;Client&lt;/strong&gt;. &lt;strong&gt;The Server&lt;/strong&gt; doesn’t care about it and includes it as a response so that the &lt;strong&gt;Client&lt;/strong&gt; can confirm that it is the right &lt;strong&gt;Server&lt;/strong&gt;. It is used for plain-text attack mitigation (when an attacker has a plaintext and encrypted version, based on that he could reveal secrets, code blocks, etc).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nc (nonce count)&lt;/strong&gt; - the number of requests (including the current one) that the &lt;strong&gt;Client&lt;/strong&gt; has sent with the nonce value in it. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Opaque&lt;/strong&gt; - Server generated string which should be sent unchanged by the &lt;strong&gt;Client&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Qop (quality of protection)&lt;/strong&gt; - defines whether hash of entity-body is added to hashes or not. It brings additional integrity. It might contain either “&lt;strong&gt;auth&lt;/strong&gt;” or “&lt;strong&gt;auth-int&lt;/strong&gt;” values.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Response&lt;/strong&gt; - in terms of &lt;strong&gt;Digest auth&lt;/strong&gt; it is a kind of signature, just a hash, based on values that will be sent to the &lt;strong&gt;Server&lt;/strong&gt; to be verified.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this auth we may use different hash algorithms, but for simplicity we will use MD5.&lt;/p&gt;

&lt;p&gt;The flow is the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;Client&lt;/strong&gt; performs a request to &lt;strong&gt;Resource Server&lt;/strong&gt; without any Auth.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;Client&lt;/strong&gt; collects &lt;strong&gt;realm&lt;/strong&gt;, &lt;strong&gt;qop&lt;/strong&gt;, &lt;strong&gt;nonce&lt;/strong&gt; and &lt;strong&gt;opaque&lt;/strong&gt; from response header.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjbnnrpjqxngvl1mktyen.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjbnnrpjqxngvl1mktyen.png" alt=" " width="628" height="580"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Client&lt;/strong&gt; generates request auth token:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First Hash (A1) = MD5 (&lt;strong&gt;username:realm:password&lt;/strong&gt;)&lt;/p&gt;

&lt;p&gt;Note: we can use MD5-sess algorithm, which essentially means to use the same algorithm, but in this format:&lt;/p&gt;

&lt;p&gt;First Hash (A1) = MD5 (MD5 (&lt;strong&gt;username:realm:password&lt;/strong&gt;):&lt;strong&gt;nonce:cnonce&lt;/strong&gt;)&lt;/p&gt;

&lt;p&gt;Why would we like to do it? It allows you to not care about user password. On top of that, I think, it allows you to use a different algorithm for hashing user credentials (username:realm:password) for security purposes. And for &lt;strong&gt;auth&lt;/strong&gt; we can use another algorithm with &lt;strong&gt;nonce&lt;/strong&gt; and &lt;strong&gt;cnonce&lt;/strong&gt; value.&lt;/p&gt;

&lt;p&gt;Second Hash (A2) = MD5 (httpMethod:requestUrl)&lt;/p&gt;

&lt;p&gt;Response = MD5 ({First Hash}:&lt;strong&gt;nonce:nonceCount:cnonce:qop&lt;/strong&gt;:{Second Hash})&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6oy2nlr26cja99srxoc2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6oy2nlr26cja99srxoc2.png" alt=" " width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Client&lt;/strong&gt; sends the same request including Authorization header in following format:
Digest &lt;strong&gt;username&lt;/strong&gt;=”{username}”,
&lt;strong&gt;realm&lt;/strong&gt; =”{realm }”,
&lt;strong&gt;nonce&lt;/strong&gt;=”{nonce}”,
&lt;strong&gt;uri&lt;/strong&gt;=”{uri}”,
&lt;strong&gt;qop&lt;/strong&gt;={qop},
&lt;strong&gt;nc&lt;/strong&gt;={nc},
&lt;strong&gt;cnonce&lt;/strong&gt;=”{cnonce}”,
&lt;strong&gt;response&lt;/strong&gt;=”{response}”,
&lt;strong&gt;opaque&lt;/strong&gt;=”{opaque}”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frfpnbjs0ptjcej8hgfon.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frfpnbjs0ptjcej8hgfon.png" alt=" " width="561" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Server&lt;/strong&gt; verifies the hash by using values provided by the &lt;strong&gt;Client&lt;/strong&gt; (authenticate and authorize). Then it either rejects with a 4XX error, or serves the response.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnm2z0hn4bffg30djp1uh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnm2z0hn4bffg30djp1uh.png" alt=" " width="800" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is one interesting question: How is the &lt;strong&gt;Server&lt;/strong&gt; supposed to generate the first hash without knowing the password, since the &lt;strong&gt;Client&lt;/strong&gt; doesn’t pass it on request?&lt;/p&gt;

&lt;p&gt;And there are 2 main solutions: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;we either store plain passwords (VERY VERY BAD APPROACH), &lt;/li&gt;
&lt;li&gt;or we store hashed value of (&lt;strong&gt;username:realm:password&lt;/strong&gt;) to be able to get the hash by &lt;strong&gt;username&lt;/strong&gt; and &lt;strong&gt;realm&lt;/strong&gt;. And this brings another problem. Once you want to change a hash (for example you used firstly MD5 and then some security weaknesses were detected and you want to change to SHA-256) you cannot do much.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Comparing to &lt;strong&gt;Basic Auth&lt;/strong&gt; this flow fixed a lot of problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There is no plain password passed through the network&lt;/li&gt;
&lt;li&gt;You can configure nonce lifetime to allow access only for some certain period of time. It is possible to log out all users by changing &lt;strong&gt;opaque&lt;/strong&gt; value, this will force everybody to reauthenticate.&lt;/li&gt;
&lt;li&gt;You can specify different access areas (different controllers, endpoints, etc) via &lt;strong&gt;realm&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However it still has some problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No built in protocol for giving different permissions for different endpoints, roles, etc. Meaning, that &lt;strong&gt;Resource Server&lt;/strong&gt; will not have claims (role, static, etc) which it can validate in token. This forces each &lt;strong&gt;Resource Server&lt;/strong&gt; to know all user permissions and store it inside.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;API&lt;/strong&gt; should know the user (store it). You can fix it by storing a hash for a particular username and realm, but still it is some kind of knowledge of the user compared to JWT for example.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Basic Auth&lt;/strong&gt; is pretty simple to implement but it has a lot of functionality and security lacks. &lt;strong&gt;Digest Auth&lt;/strong&gt; is much more complicated, but solves some of the problems that &lt;strong&gt;Basic Auth&lt;/strong&gt; has, but still it has some lack of functionality that regular applications would need for the Auth process. &lt;/p&gt;

&lt;p&gt;So in the next part we will consider &lt;strong&gt;OAuth&lt;/strong&gt; and &lt;strong&gt;OpenId Connect&lt;/strong&gt; protocols which solved those problems.&lt;/p&gt;

&lt;p&gt;To reach me out or to follow me:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Instagram&lt;/strong&gt;: &lt;a href="https://www.instagram.com/andreyka26_programmer/" rel="noopener noreferrer"&gt;https://www.instagram.com/andreyka26_programmer/&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Telegram&lt;/strong&gt;: &lt;a href="https://t.me/programming_space" rel="noopener noreferrer"&gt;https://t.me/programming_space&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Facebook&lt;/strong&gt;: &lt;a href="https://www.facebook.com/groups/719475658991936" rel="noopener noreferrer"&gt;https://www.facebook.com/groups/719475658991936&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;LinkedIn&lt;/strong&gt;: &lt;a href="https://www.linkedin.com/in/andrii-bui-a55b39166/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/andrii-bui-a55b39166/&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/andreyka26-git" rel="noopener noreferrer"&gt;https://github.com/andreyka26-git&lt;/a&gt;&lt;/p&gt;

</description>
      <category>auth</category>
      <category>programming</category>
      <category>csharp</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How I make myself productive with Google</title>
      <dc:creator>Andrii Bui</dc:creator>
      <pubDate>Sat, 14 May 2022 14:15:04 +0000</pubDate>
      <link>https://dev.to/andreyka26git/how-i-make-myself-productive-with-google-3ff1</link>
      <guid>https://dev.to/andreyka26git/how-i-make-myself-productive-with-google-3ff1</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;I keep doing my tech blog here: &lt;a href="https://andreyka26.com/" rel="noopener noreferrer"&gt;https://andreyka26.com/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hello guys, in this article I'll explain to you why I've started using Google productive tools like Google Calendar, Google Keep, Google Tasks, and Google Docs. So basically everyone uses it in different ways - but I will show you my use cases and how they can be solved with mentioned tools and applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Google Tasks: use cases
&lt;/h2&gt;

&lt;p&gt;For Google tasks I have three main use cases:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Instant task to not forget&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sometimes I find myself recalling something to buy or something to not forget to do, etc. This is the time when you can open Google Tasks. Since Google Tasks has a client application that can run offline, you can just get your phone and add your task. Whenever you will set an internet connection it will synchronize your task and you will be able to access it from other devices and the web.&lt;/p&gt;

&lt;p&gt;For example, noting to buy something.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyu8xmh06f1dq7ufr492j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyu8xmh06f1dq7ufr492j.png" alt=" " width="453" height="529"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Planned task (possibly with email integrated into it)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Recently I've got a lot of such use cases because I had plenty amount of emails regarding relocation and start working for Microsoft. So I was getting different emails with action items to do (visa, health insurance,  hardware pickup, etc.) You can integrate email, which possibly contains the date and place of an event with names and sender email, into the task with configuring reminder. And when the time comes you can instantly find your email and get all the necessary details. On top of that any other tasks without emails like haircuts, or other appointments with persons.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Just planned task&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhyjwcnc2aiaihuq8n2h4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhyjwcnc2aiaihuq8n2h4.png" alt=" " width="448" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Planned task with integrated email&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Create email clicking on this button&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhl6e1c3r2ex1oh05fb81.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhl6e1c3r2ex1oh05fb81.png" alt=" " width="512" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By default it creates task with the email subject&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw0b40f5qstm9fu1wq6uc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw0b40f5qstm9fu1wq6uc.png" alt=" " width="448" height="255"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you click on the "Test email button" you'll be redirected straight into the email.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funlvxo13wwl6m77i06eh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funlvxo13wwl6m77i06eh.png" alt=" " width="445" height="289"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Besides this, for email integrated tasks you can set reminders as well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Regular/repeating tasks&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This use case I mostly use  when I have repeating tasks for some period of time: taking pills, body exercises, reminders for reading, etc.&lt;br&gt;
For any repeating task - you could click on the "Date Time" button&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fde6yov0gnig5xrms4q61.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fde6yov0gnig5xrms4q61.png" alt=" " width="293" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And then go to the "Repeat" option.&lt;br&gt;
Here just set repeating options.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F297cyuka5mbukqfl4ss8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F297cyuka5mbukqfl4ss8.png" alt=" " width="450" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then you will get this task on your list repeatedly once a day along with reminders.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4mk2v4km1altvx1tqcxz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4mk2v4km1altvx1tqcxz.png" alt=" " width="452" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Google Tasks: Features I like
&lt;/h2&gt;

&lt;p&gt;Back in the day, I used some kind of documents inside the phone or computer. I even used a regular notebook with a pen for tasks. And they all had some drawbacks which were used by what I am using right now.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integration with Google environment&lt;/strong&gt;. Most likely a huge amount of you (viewers) have your personal accounts in Gmail. So the first advantage of Google tasks is that it is integrated into the Google environment, so you can leverage other Google tools (Gmail, Calendar, Keep, etc).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It is free&lt;/strong&gt;. You don't need to pay any money for a subscription for usage. You will need to pay only if you run out of overall Google Drive space (currently 15Gb), then you can extend to more space and you are okay.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It is cloud-based&lt;/strong&gt;. It brings 2 advantages:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;em&gt;The data could unlikely be lost (replication, high availability, etc), and Google itself is responsible for that.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;You can access your data from any device or from anything that has a browser and internet connection. Currently, I have 2 phones, my personal laptop, a laptop from previous work, current laptop from Microsoft. And all those devices are synchronized with Google Environment. If I add any task to one of those devices - this task will appear on all devices&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simple and user-friendly interface&lt;/strong&gt;. There aren't many functionalities, you can create different lists, only 1 level of hierarchy (task -&amp;gt; subtask), you can integrate with Gmail, you can set reminders, and add the "Details" section, but I don't think it is useful. And basically, this is pretty much enough for basic use cases&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reminders&lt;/strong&gt;. On my phone, I can configure specific sounds for specific reminders (daily tasks, previous day's tasks, timed tasks). By doing that you can differentiate different tasks from notifications. And those notifications are working without an internet connection (the only one case is when you've added from another device and it wasn't synchronized with your current device, because you've not turned on the internet yet)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl1hc5pgsudlc23qmve30.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl1hc5pgsudlc23qmve30.png" alt=" " width="231" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At some point when you have a lot of tasks and all of them has some dedicated time - it is important to not get lost in the list. For that purpose we can use Google Calendar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Google Keep: use cases
&lt;/h2&gt;

&lt;p&gt;Google keep is a tool for taking notes. Basically, I'm not that happy with it because I miss some functionality. Currently, I'm migrating to Microsoft OneNote for that reason.&lt;/p&gt;

&lt;p&gt;I'm noting there everything relevant and important like addresses, phones, things to remember, maybe someone's words to not forget.&lt;/p&gt;

&lt;p&gt;I'll note the advantages and disadvantages of it because for me it is not that good tool for notes.&lt;/p&gt;

&lt;p&gt;Pros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Google keep has decent performance on the phone, it is pretty quick&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It can work without an internet connection, you need to turn on the internet connection only to make it sync with the server (and consequently with other devices).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integration with Gmail. You can just open some emails, go to the tab with Google Keep, and start making notes. The email will be automatically attached to your note.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffvy8gqf35liujd9fy1fd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffvy8gqf35liujd9fy1fd.png" alt=" " width="512" height="126"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you can navigate to this email when viewing this note:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F82pf97pge1wnjgqii1xs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F82pf97pge1wnjgqii1xs.png" alt=" " width="512" height="164"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Pretty good system of labeling and colors (I actually don't use them, because I don't make many notes in Keep, mostly everything is in Google Docs now).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integration with Google Docs: you can easily move your note to document in Google Docs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can attach a reminder to your note:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpf3j857w4d1ma1avcw8r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpf3j857w4d1ma1avcw8r.png" alt=" " width="512" height="169"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And will appear in Google Calendar:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fktijx570bmfhrhd5d1uk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fktijx570bmfhrhd5d1uk.png" alt=" " width="512" height="231"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It doesn't contain any text editing tools like Google Docs contains. You can write plain text without any configuration of font size, font color, bold, italic other styles, font style, making lists with checkboxes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Each note has 2 styles: "regular" and "checkboxes".&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;"Regular":&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5nikncfqtboynscifiia.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5nikncfqtboynscifiia.png" alt=" " width="512" height="255"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;"Checkboxes":&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz3yqufzo9oipf309q5oj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz3yqufzo9oipf309q5oj.png" alt=" " width="512" height="317"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I really don't understand the purpose of this, because you can do this checkbox behavior in Google Tasks. On top of that, I hate that it is applied to the whole note. So basically you cannot create one such "checkbox" list and then append regular text, and then do another "checkbox" list.&lt;/p&gt;

&lt;p&gt;On top of that if you change your style back to the "regular" one it will clear all blank lines and another styling:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwhla9kudqtqd5um1ave1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwhla9kudqtqd5um1ave1.png" alt=" " width="512" height="208"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can paste the photo, but it will be pasted on the top of your note, not in the place where you wanted it to be.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftxies02kmt14q0flxutf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftxies02kmt14q0flxutf.png" alt=" " width="381" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It doesn't contain integration with Google Tasks. For example, I faced situations when I need to attach Google Keep notes to Google Tasks but there is no such option.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For categorizing and structuring your notes between the categories you have only a labeling mechanism.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So personally for me - it is better to use Google Docs and Google Drive for noting everything.&lt;/p&gt;

&lt;p&gt;But it is slower than Google Keep, and as I know you cannot edit it on the phone without an internet connection. On top of that, you need to swap Google Docs and Google Drive applications each time you need to get to another document which is not that great from a performance standpoint as well.&lt;/p&gt;

&lt;p&gt;That's why I'm considering moving my notes to Microsoft OneNote.&lt;/p&gt;

&lt;h2&gt;
  
  
  Google Calendar: use cases
&lt;/h2&gt;

&lt;p&gt;Basically, I'm using Google Calendar prior to the next day. Because Google Calendar includes all events, tasks, and reminders. Because sometimes you have a really huge amount of tasks for different days and you need to know what you are going to do only for tomorrow.&lt;br&gt;
On top of that, it serves me as the connector of my notes and tasks together with my events and reminders in one place. I can see everything for a particular date in one place, and create everything as well from this place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I find Google Environment so convenient for managing my life and tasks, it really simplifies and speeds up productivity. But from the taking notes standpoint, it is not that great. So I will appreciate your comments and ideas about how YOU use Google Environment or anything else for your productivity.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>tasks</category>
      <category>management</category>
      <category>notes</category>
    </item>
  </channel>
</rss>
