Auth service without libraries

What this article is about: the article is devoted to the schemes of registration, authentication, authorization of users in web applications, changing passwords, revoking tokens, etc. We will also consider how to organize data storage, discuss what JWT is, and briefly talk about the “service for sending email”

Why did I name the article this way?: in any application there are a number of procedures not directly related to its task. These are methods related to granting access rights and revoking these accesses. At the moment, there is no single term that covers them all. In this article, I tried to list these proceduresand describe them in the form graphic schemes. We'll see how successful I was.

Who is this article for: for those who are starting to master authentication and authorization methods in web applications and want to understand how everything works. I deliberately avoided using complex libraries and frameworks in order to understand on my fingers what methods are needed in the Auth service and how to use them.

The article will consist of 2 parts. In the first part we will discuss the theory needed to understand the methods given, and in the second part the main endpoints of the Auth service will be listed and diagrams with comments will be given. If you are confident in your abilities and do not want to read the boring theory, you can immediately go to the section endpointsif not, let's continue.

Terms

  • Identification — the process of obtaining the user ID: login/e-mail/id

  • Authentication — user identity verification (using a password, fingerprint, etc.)

  • Authorization – granting rights to the user, issuing a token

  • Validation — the process of checking a “piece” of information for compliance with program requirements, or simply for a match with a copy stored in the database.

  • Auth a general term for services/modules/endpoints responsible for identification/authentication/authorization in an application. There is no Russian-language equivalent.

  • JWT (Json Web Token) – user authentication key

  • Code — confirmation code. Sent to the user's email to confirm registration or reset the password.

  • Credentials — user credentials: login, password, google id, etc.

  • Endpoint — url address of a specific API method or Auth service

  • Method — within the framework of this article = endpoint

  • API Methods — methods that implement the application's tasks (what we wrote it for)

  • Auth Service Methods — methods that are not directly related to the application's tasks (in this article, they are contrasted with “API methods”)

  • BD — database

  • Email-client — mail service, for example: gmail, yandex mail, etc.

  • TTL (Time to live) — the lifetime of a record in a database (for example: Redis)

  • Redis — a key-value database server. Very fast, ideal for storing caches and tokens (documentation here)

  • Client — data presentation level (see client-server architecture). Has a graphical interface for interaction with the user. example: a website on the Internet.

  • Server — the level of data acquisition and processing (see client-server architecture). It does not have a graphical interface, it communicates with many clients via API.

Auth service

As mentioned above, the Auth service includes procedures related to granting access rights to users and revoking these accesses. Let's list these procedures:

  1. user registration with login and password

  2. sending a confirmation code to the user's e-mail

  3. Confirmation of user registration using the code received by email.

  4. user registration through an intermediary: Google, Facebook, etc.

  5. authentication and authorization of the user with login and password.

  6. user authentication and authorization through an intermediary.

  7. Logout, revoke tokens.

  8. reset password (user not logged in yet)

  9. update password (user authorized)

  10. issuing tokens after successful authorization.

  11. refresh expired tokens.

  12. maintaining a blacklist of tokens.

  13. Credential version control

Of course, this list can be expanded. We could also add:

  • defining user roles

  • authorization by phone number

  • two-factor authentication

  • account deletion

  • etc.

Unfortunately, the article format does not allow us to describe everything at once, so today we will limit ourselves to the first 13 points.

Data structure

When designing an application, it is important to carefully consider data storage. The user's personal data (nickname, avatar, etc.) and credentials (login and password) should not intersect in one table. Why is this important:

  1. division of responsibility: only the Auth service methods should have access to the user's credentials, other services do not need this data. Fewer access points => higher application security.

  2. extensibility: This allows you to use multiple authorization types in one application and add new authorization methods as needed.

  3. scalability: in large systems there may be several applications with authorization through one common Auth service. In this case, the credentials are generally stored in a separate DB belonging only to this service, other services do not have access there.

Question: What to do with the user's email, which is often used as a login, but we also need it to send registration confirmation emails and password reset codes?

Answer: email is used as a login for only one reason – uniqueness. In my opinion, it would be correct to duplicate it in the “users” and “credentials” tables, since here it performs 2 unrelated functions: login and email.

For example, let's say our application has:

  1. password authorization

  2. authorization via google

  3. authorization via facebook

Auth service data structure

Auth service data structure

JWT

Json Web Token — user authentication key. Used for requests to protected API methods.

I have already described the nuances of working with Jwt in the article “JWT in Detail”, so we will not dwell on this. If the following schemes raise questions for you, check out the sections of the article about JWT:

  • Token validation

  • Blacklist of tokens

  • Version control

Briefly about the postal service

In order to implement registration/authorization procedures using the application, you will need your own mail service. It is necessary to confirm the account registration and to send password reset links to the user's mail.

It is not difficult to implement such a service, most development environments have ready-made libraries for this, but there is a nuance: in the modern world, you can no longer simply send a letter from a random IP from the application code. Such letters will be rejected by the email client (gmail, yandex mail, etc.) as suspicious. They will not just fall into spam, they will return with an access error (!)

In order for letters to reach the recipient, you need to connect a certified intermediary service that verifies the authenticity of the domain and the letter itself, for example: aws.amazon.com. The procedure is not complicated, but it is tedious, and if you are planning a large volume of mailings (>200 letters per day), then it is also paid.

Conclusion: if you want to quickly put your application into production and don’t have time to mess around, I recommend connecting authorization via Google or Facebook, it’s easier at first.

Endpoints

So, to implement the Auth service we will need the following endpoints:

  • POST ~/auth/sign-up — register a user with login and password (scheme)

  • POST ~/auth/send-code — resend email with code (scheme)

  • POST ~/auth/confir-email — user registration confirmation (scheme)

  • POST ~/auth/sign-up — register user with google (scheme)

  • POST ~/auth/sign-in — log in to the system (scheme)

  • POST ~/auth/logout — logout from account (scheme)

  • POST ~/auth/reset-password — reset password (scheme)

  • POST ~/auth/confirm-reset — password reset confirmation (scheme)

  • PATCH ~/auth/update-password — update password (scheme)

  • POST ~/auth/refresh-tokens — get a fresh pair of tokens (scheme)

User registration

user registration scheme

user registration scheme

What's going on here:

  1. user data entry, email uniqueness check

  2. password encryption, saving user data in the database

  3. generating a verification code, saving the code in the Redis DB

  4. receiving a confirmation code to the user's email

  5. request to confirm user registration, save the mark in the database

  6. Generate JWT tokens, transfer to the client

Question: What is the purpose of “user registration confirmation”?

Answer: essentially, this is a check of the validity of the email that will be needed to reset the password.

Resending the verification code

sending verification code scheme

sending verification code scheme

user registration via google What's going on here:

  1. click on the button “send code again”, check email, confirm email

  2. generating a verification code, saving the code in the Redis DB

  3. receiving a confirmation code to the user's email

Question: why do I need to resend the code?

Answer: to prevent codes from accumulating in the cache, any confirmation code should have a short lifetime (on average – 15 minutes). If the user has not managed to complete registration during this time, he will need to request the code again.

User registration via google

user registration via google. scheme

user registration via google. scheme

What's going on here:

  1. authorization request via google, redirect to authorization page, enter credentials

  2. saving user data in the database.

  3. Generate JWT tokens, transfer to the client

Question: how will the server distinguish a request for authorization with a login and password from registration via a Google account if the URL is the same?

Answer: I pass the registration type in the request body. The parameter “providerType” can take values: local, google, facebook, etc.

User authorization

user authorization scheme

user authorization scheme

What's going on here:

  1. user input of login and password, verification of login and password by the server

  2. Generate JWT tokens, transfer to the client

User authorization via google

authorization via google scheme

authorization via google scheme

What's going on here:

  1. authorization request via google, redirect to authorization page, enter credentials

  2. getting user data from the database.

  3. Generate JWT tokens, transfer to the client

Logout from account

Logout scheme

Logout scheme

What's going on here:

  1. The user clicks “Exit”, the application sends tokens to the Auth service

  2. The service adds tokens to the blacklist so that they cannot be used to log into the application

  3. The user is redirected to the authorization page

Reset password

password reset scheme

password reset scheme

What's going on here:

  1. The user clicks “Reset Password” and is redirected to the email entry page

  2. The user enters an email to receive a link, the server checks the validity of the email

  3. Auth server creates a password reset code and sends it to the user's email

  4. The user receives a code

  5. The user enters a new password and confirmation code, the Auth server validates the code, hashes the password, and saves the password hash in the database

  6. The Auth server generates a new pair of tokens and gives them to the client.

Update password

password update scheme

password update scheme

What's going on here:

  1. The user goes to the “User Profile” section in the application, enters the old password, and the new password.

  2. We extract the user's uuid from the token, get the hash of the current password from the DB, validate the password

  3. We encrypt the new password, save the hash of the new password, the hash of the old password in the DB, and increase the version of the credentials by +1 (see the article “More about JWT”)

  4. We add tokens to the blacklist so that they can no longer be used to log into the application

  5. We generate a new pair of tokens and send them to the client

JWT Update

JWT update schema

JWT update schema

What's going on here:

  1. request data with access token

  2. access token validation failed, returning error #401

  3. request to refresh tokens with refresh token,

  4. checking whether the token is included in the black-list

  5. getting version of credentials from DB

  6. token validation, token version check

  7. generating a new pair of tokens, sending to the client

In conclusion

The practices presented are not the ultimate truth. There are a number of approaches to implementing Auth services, and additional tricks to increase the security of the application. I wrote this text to figure out what's what myself. If you find an error in my reasoning, I will be grateful for any comments.

For those who write in TypeScript + Nest.js, I can write an article with an implementation example. If you are interested, write.

More on the topic

  • Role-Based Access Control (RBAC) — user roles

  • OAuth 2.0 is a protocol for organizing an Auth service as a separate server. It takes over the issuance of JWT and simplifies the definition of access rights for users.

  • OpenID is an authentication mechanism for multiple, unrelated resources based on OAuth 2.0

  • PXCE – An additional layer of protection for mobile applications

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *