Becoming a software developer – episode XV

Becoming a software developer – episode XV

Welcome to the fifteenth episode of my course “Becoming a software developer” in which we will implement password encryption, authorization and authentication using JWT.

All of the materials including videos and sample projects can be downloaded from here.
The source code repository is being hosted on GitHub.


 

Scope

  • Encryption
  • Authentication
  • Authorization

Abstract

Encryption

Whenever we want to store user accounts along with their passwords in our database, the best option is to apply a hashing function. It means that given e.g. “secret” password such function will create a so-called hash which can not be reversed (or decrypted) based on some random and secure sequence of characters named salt. Basically, whenever we want to ensure that the password is valid, we need to create its hash based on the salt generated for the first time when hashing the password e.g. during account registration and then compare the hashes, simple as that. This way, even if the data storage would be compromised the password can not be decrypted easily, as the hash is not a reversible function (at least theoretically).

Authentication

In order to find out the identity of the user in our system, he needs to be able to authenticate in some way. For the typical web application which is stateless, we can choose between different methods of authentication and pass along this information either with cookies, headers or within the URL itself. In our case, we want to use JWT (JSON Web Tokens) which is one of the most popular industry standards and basically boils down to generating a secure token that can be passed within the HTTP Header “Authorizaion: Bearer {token}”. Once the token is validated by the server, we can assign an identity to the user and allow him to perform operations that he wouldn’t be able to do otherwise.

Authorization

Once the user was authenticated we can grant him access to the different operations or resources for example based on his role (user, moderator, admin etc.) or claims (list of permissions). While authentication is all about finding out if the user is who he claims to be, the authorization’s task is to validate whether the user has the required permissions to successfully perform a request.

Next

In the next expisode we will talk a little bit more about caching, implement the “login” endpoint in our API, move further with business logic and also resolve the user identity based on JWT claims and map it automatically to the commands that require user id.

9 Comments Becoming a software developer – episode XV

  1. Bartosz

    Z tego co rozumiem salt to jest klucz który służy do zaszyfrowania hasła? Jeśli tak to nie rozumiem tego co zrobiłeś w klasach UserService oraz Encrypter. W UserService przy rejestracji użytkownika zapisujesz do bazy danych zaszyfrowane hasło + salt, gdzie salt, patrząc na wywołanie metody GetSalt sugerowałoby, że jest generowane na podstawie hasła, lecz patrząc w ciało tej metody widzę, że parametr value jest użyty jedynie do komunikatu, gdy jest on pusty, a salt jest jednak generowane losowo.
    Tutaj pojawia się nieścisłość której nie mogę zrozumieć, z ciała metody GetSalt wynika, że salt jest generowane losowo, a nie na podstawie hasła jak wynika z wywołania tej metody (chyba, że coś przeoczyłem/czegoś nie rozumiem), a więc żeby przy logowaniu sprawdzić, czy hasło jest poprawne należało by odczytać salt z bazy i wygenerować na jego podstawie hash wpisanego hasła i go porównać z tym zapisanym w bazie. W klasie UserService jednak wygląda to inaczej, generujesz nowy salt, i na jego podstawie generujesz hash do porównania z hashem z bazy, czy to nie spowoduje sytuacji, że dwa takie same hasła będą miały inny hash?

    Tak w skrócie:
    Czy metoda GetSalt generuje salt losowo czy na podstawie hasła?
    Dlaczego przy logowaniu generujesz nowy salt, zamiast pobrać go z bazy?

    Reply
  2. Pior

    Witam
    Ma pytanie. Po aktualizacji nie ma już dostępu do UseJwtBearerAuthentication(IApplicationBuilder, JwtBearerOptions) jakaś rada jak teraz wszystko połączyć?

    dzieki
    pozdrawiam

    Reply
  3. Bartosz

    Mam takie pytanie, bo w .Net Core 2.0 app.UseJwtBearerAuthentication() w Configure() został zamieniony na services.AddAuthentication().AddJwtBearer() i przeniesiony do ConfigureServices() z której nie ma dostępu do pliku z ustawieniami w poniższy sposób app.ApplicationServices.GetService();
    i dostęp do pliku rozwiązałem za pomocą:
    Configuration.GetSection(“jwt:issuer”).Value
    ale czy jest inna możliwość dostania się do tych ustawień? (dodanie IApplicationBuilder app do parametrów ConfigureServices() oczywiście wyrzuca błąd)

    W komentarzach czasami usuwa się kod więc podrzucam link do kodu:
    https://pastebin.com/F3UJc4pU
    I jeszcze pytanie do powyższego kodu, jest jakaś różnica między liniami 46,47, a 53,54?

    Reply
    1. Bartosz

      Jeszcze jedna rzecz wyszła w testach w .Net Core 2.0 nie czyta pliku appsettings.json, przez co nie może wczytać konfiguracji i się wysypuje przy services.AddAuthentication(), znalazłem taki wątek ale zbytnio mi nie pomógł:
      https://github.com/aspnet/Hosting/issues/1191
      Może miałeś podobny problem i masz na to jakieś rozwiązanie?

      Reply
    2. Trep

      Nie wiem czy to dobre rozwiązanie ale jest napisana przez Piotra extension method do IConfiguration i można ja uzyć w ConfigureServices
      var jwtSettings = Configuration.GetSettings();

      Reply
  4. Geoffrey Barnes

    Hey

    Thanks for putting together this post on becoming a software developer – episode XV.It is a great read. I particularly find your thoughts about encryption interesting.
    Keep up these insightful posts.

    Cheers!

    Reply

Leave a Reply to Bartosz Cancel reply

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