Go-Swagger : User Authentication & securing API using JWT — Part 1

Shashank Vivek
5 min readAug 9, 2020

--

In my previous article, I have explained on how to register a new user for a website. We saved our password securely using bcrypt into the database which is a sensitive data. Once, we are done with registration, the next step is to provide login for the registered user.

If you are new to go-swagger, I would recommend you to read the introduction and implementation part of this amazing framework.

For user authentication we have few options such as session or JWT (JSON Web Token) based authentication. I will not get into much details of each, but I’ll explain the reason of choosing JWT over session briefly.

JWT Vs Session based Authentication:

Major reason for choosing JWT over session is because the JWT is purely stateless. With stateless, I mean that they can be used by server which has multiple instance of backend services running. With session you will have separate session for each service instance. Hence, if the load balancer redirects call to a service where the session info of the user is not present, then the server won’t be able to authenticate the user.

To overcome the session sharing there are few ways but that would go beyond the scope of this article.

With JWT , the server issues a token to the client(user) after successful login. Once the token is issued by server, it is stored on the client side and is added as Authorization in the headers to get access to protected API calls.

DummyJWT : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

The structure of JWT consists of Header, Payload & Signature separated by dot (“.”) which can be decoded using jwt.io site. Getting into more details of JWT will again be out of scope for this article, so I’ll try to write a small article on JWT and link it here later.

Now, that we have some idea about JWT, we can start working on our small ecommerce website to have user authentication. Lets go step by step:

1. Create “/login” endpoint for authentication

To create the /login endpoint, we’ll follow the same steps which we followed earlier:

You can visualize the API by pasting it online swagger editor . Please note that we’ll be getting token as a response (type LoginSuccess in swagger.yaml) of this endpoint.

2. Generate Boilerplate go-swagger code for the endpoint :

Once we have the /login endpoint created in swagger.yaml, we will generate the respective boilerplate code using:

swagger generate server -f api/swagger.yaml --default-scheme http

This results in creating in below files boilerplate files:

  • /models/login_info.go
  • /models/login_success.go
  • /restapi/operations/user/login.go
  • /restapi/operations/user/login_parameters.go
  • /restapi/operations/user/login_responses.go
  • /restapi/operations/user/login_urlbuilder.go

But we should not be worried about these files as they are generated based on swagger.yaml

3. Code Implementation:

To integrate boilerplate code with our custom code, we need to create a handler file login.go under ./handler folder & a dao package to access user details from MySql .

This project structure which we are discussing, has already been explained previously. Also, To access login details from Database, we’ll be using the same code structure to create mysql client as we have done for user registration in one of my articles.

  • We’ll create a DAO package which will interact with MySQL database. Please note that we’ll be injecting the *sql.DB connection pointer into the FetchUserDetails() to keep the code loosely coupled.
  • Create a utils/authenticator.go file, which we’ll be using to generate JWT token once the password is matched successfully. The below code uses HMAC-SHA as jwt.SigningMethodHS256 . We also added user details under claims such as email , first_name , last_name and an expiration time of 300 minutes for the generated token. The token is signed and returned.
  • Creating login.go to access dao/customer.go & utils/authenticator.gofile. The login.go will perform below operations:
  1. Fetch User details from MySql database.
  2. Since we have encrypted the password using bcrypt , we’ll the same package to the compare the login password with encrypted password.
  3. Once it matches, we create a signed token using utils.GenerateJWT()
  4. return the response LoginSuccess (as defined in swagger.yaml)

4. Wire-up the endpoint with handler

To finally execute login.go when we call /login endpoint, We need to go to configure_e_food.go file and assign NewUserLoginHandler with dbclient:

5. Hit Endpoint to get the token

Once we have the /login endpoint created and /register endpoint for registering a new user, spin up the localhost server with

go run cmd\e-food-server\main.go — scheme http — port=8080

Try the postman to get output as below:

The output token can be decoded to know all the details which we have added on server side using authenticator.go file.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdXRob3JpemVkIjp0cnVlLCJleHAiOjE1OTY5Nzc2MjEsImZuYW1lIjoiU2hhbiIsImxuYW1lIjoiVml2IiwidXNlciI6ImFzZEB0ZXN0LmNvbSJ9.tdhUL-KpDmzSNtV9z6XhUgoTKcVabuOPS3fHAySjSXQ

Make sure to check mark “secret base64 encoded” to view the details on jwt.io

That’s it for this article, in my next article I’ll show how to restrict the API calls so that they are only accessible using the valid JWT token. In case you want a final structured code, you can refer to the demo e-food-server code base .

I hope that this will help someone who is new with go-swagger and wants to implement user authentication. You can use the logic of login.go and authenticator.go in a normal Go app as well, I have just used it as per go-swagger framework.

If you like this article, please 👏 clap 👏 few times to encourage me 🐼 to write more.

--

--