Wtf is Grpc? Part 1: Authentication and Authorization in Flutter and Golang.
Tags: flutter, go, grpc, mongodb
Published: 2023-09-04 13:53:10

Greetings, fellow tech enthusiasts, and welcome to a tech journey like no other! 🚀 Today, we're embarking on a roller-coaster ride through the fascinating world of gRPC, Flutter, and Golang, but with a twist – we've spiced it up with a generous serving of humor. Buckle up; it's going to be a wild ride!

In our three-part series, we'll explore the ins and outs of gRPC, the delightful dance between Flutter and Golang, and discover how these technologies can come together to create harmonious applications that can bring a smile to even the most stoic developer's face.
## Table of Contents

1. [Introduction](#a-quick-peek)
   - [gRPC: A Not-So-Boring Bookish and Slightly Amusing Definition](#gRPC:a-not-so-boring-bookish-and-slightly-amusing-definition)
   - [gRPC vs REST: The Iron Throne of APIs](#grpc-vs-rest-the-iron-throne-of-apis)
   - [Types of gRPC](#types-of-grpc)

5. [Prerequisites](#prerequisites)
   - Create project
   - Setup  Database model
   - Password Hashing
   - Environment
   - JWT
6. [Basic of Protocol Buffer](#basic-of-protocol-buffer-(.proto).)
   - Service
   - Message


7. [Setup Basic Project in Golang](#setup-basic-project-in-golang)

8. [Create Protocol Buffers](#create-protocol-buffers-for-our-project)

9.  [Generate Golang code](#generate-code-for-golang)
10. [Authentication in Go](#create-basic-auth-function)
11. [Setup Server and Middleware](#setup-server-and-middlware)
12. [Start Server](#connect-whole-and-start-server)
13. [Flutter Project](#flutter-project)
   - [Setup Project](#setup-project)
   - [Output](#output)

14. [Conclusion](#conclusion)
   - [Source Code](#source-code)
   - [Follow Me](#follow-me-on)


## A Quick Peek
- **Part 1: Authentication & Authorization**
- **Part 2: Custom Flutter Notifications**
- **Part 3: Chat Applications with gRPC**

## gRPC: A Not-So-Boring Bookish and Slightly Amusing Definition

Alright, time to don our academic spectacles and approach this with a hint of whimsy. Imagine you're at a fancy library soirée, and someone asks, "What, pray tell, is gRPC?" You respond with a grin:

"Gentlefolk, gRPC, which stands for 'Google Remote Procedure Call,' is like the telegraph system of the digital realm. It's a meticulously structured, high-tech method for different programs to chit-chat with each other, just like sending telegrams back in the day, but without the Morse code."

"But wait, there's more! Instead of tapping out dots and dashes, gRPC uses Protocol Buffers, which is like encoding your messages in secret spy code, only it's not so secret. This makes your data compact and zippy, perfect for today's speedy world."

"Picture it as a virtual switchboard operator connecting your apps with finesse. Plus, it plays nice with HTTP/2, which is like giving your data a sleek, sports car to zoom around in, making it super fast."

"So, in essence, gRPC is the gentleman's agreement between software, ensuring they can communicate efficiently and reliably, like two well-mannered tea-drinking robots having a chat. It's the technological equivalent of a courteous bow, allowing different systems to exchange information harmoniously."

## gRPC vs REST: The Iron Throne of APIs

| Aspect                 | gRPC                             | REST                                       |
|------------------------|----------------------------------|--------------------------------------------|
| Protocol               | Uses HTTP/2 for communication.   | Typically uses HTTP/1.1, but can use HTTP/2.|
| Data Serialization     | Uses Protocol Buffers (ProtoBuf) for efficient binary serialization. | Uses human-readable formats like JSON or XML. |
| Communication Patterns | Supports unary, server streaming, client streaming, and bidirectional streaming. | Primarily supports request-response (HTTP GET, POST, etc.). |
| Payload Size           | Smaller payload due to binary serialization, making it more efficient. | Larger payload due to text-based serialization. |
| Performance            | High performance and low latency, suitable for microservices. | Slightly slower due to text-based serialization. |
| Language Agnostic      | Supports multiple programming languages, making it polyglot. | Can be used with any language, but not as standardized. |
| Code Generation        | Generates client and server code automatically from Protobuf definitions. | No automatic code generation for client or server. |
| Error Handling         | Uses status codes and detailed error messages for robust error handling. | Typically relies on HTTP status codes and custom error messages. |
| Tooling                | Well-documented and supported by various libraries and tools. | Widely supported with many tools and libraries available. |


![meme1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/blgjv1kcl69fkmu9frls.jpeg)


## Types of gRPC

Here are the primary types of gRPC communication:

- **Unary RPC (Request-Response)**: This is the simplest form of gRPC communication. The client sends a single request to the server and waits for a single response. It's similar to traditional request-response interactions.

- **Server Streaming RPC**: In this pattern, the client sends a single request, but the server responds with a stream of messages. It's useful when the server needs to push multiple pieces of data to the client, such as real-time updates.

- **Client Streaming RPC**: Here, the client sends a stream of messages to the server, and the server responds with a single message. This can be beneficial for scenarios like uploading large files.

- **Bidirectional Streaming RPC**: In this type, both the client and server can send a stream of messages to each other concurrently. It's ideal for interactive and real-time applications like chat or gaming.


![meme2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0hjqn5xhwe05d5yuo9nl.jpeg)

In this we are going to explore **unary gRPC** using **login**,**signup** and **get-user** request.

## Prerequisites

- Basic understanding of Golang,Flutter and [MongoDb](https://www.mongodb.com/).
- Excitement to learn something new.

## Setup Basic Project in Golang

- Create new project 
```
go mod init <project-name>
```
- Install Mongo package for go

 ```
  go get go.mongodb.org/mongo-driver
```
- Setup Database Model
    - Create package `db` 
      - Create Struct to access database
        {% gist https://gist.github.com/Djsmk123/1403119e28114262c26122bd902dd9f4 %}
       
      - Create new model `user.go`
{% gist https://gist.github.com/Djsmk123/1704a8ef3dc83fa412fe239aefcbe107 %}


- Password hashing : we are going to create function for hashing password and check password, **Never store password in simple text**.
    - Create package `utils` in root.
    - Install required package `go get golang.org/x/crypto/bcrypt`.

    - Create `HashPasword` and `CheckPassword` function in `password.go`

{% gist https://gist.github.com/Djsmk123/7c4e2173113a63f9da95072b1d53d032 %}

- Setup Environment: We required few environment variable like `server_address`,`mongodburl` and `jwt_key` etc.
    - Install Viper package for loading `app.env`.
      ```
        go get github.com/spf13/viper
      ``` 
for more information read about [viper](github.com/spf13/viper)
   - Create function in `utils` to load `app.env` file.
    
{% gist https://gist.github.com/Djsmk123/8a08873035b40020285accf87a232fe4 %}

- Create `app.env` in root folder.

```
DB_NAME=grpc 
DB_SOURCE=mongodb://localhost:27017
RPC_SERVER_ADDRESS=0.0.0.0:9090
GIN_MODE=debug
TOKEN_SYMMETRIC_KEY=12345678123456781234567812345678
ACCESS_TOKEN_DURATION=600m

```

- Setup Jwt: We need authorization in few requests so its going to `bearer` token based authentication. 
    - Install required Jwt package

```
     go get github.com/dgrijalva/jwt-go
```

---

> Note: Not Going to cover Jwt Basics.

- Create new package token and create interface to create token and verify token.
{% gist https://gist.github.com/Djsmk123/a53b8f913e89e4782bb5a33a85a49c3e %}

{% gist https://gist.github.com/Djsmk123/75c6379f8b80b1df5e0eb5a30324d308 %}

{% gist https://gist.github.com/Djsmk123/9a538a676b247517fe82bea83403de82 %}


---

## Basic of Protocol Buffer (`.proto`).

- **Service**: A unary service in gRPC involves a single request from the client to the server, which then sends a single response back to the client. To define a unary service, you need to create a .proto file that describes the service and the message types it uses.

- **Message**: A message is a data structure that represents the information being sent between the client and server. It's defined in your .proto file using the message keyword. Here's a simple example:
```
syntax = "proto3";

message MyRequest {
  string name = 1;
  int32 age = 2;
}

message MyResponse {
  string greeting = 1;
}

```
In this example, we have two messages, `MyRequest`and `MyResponse`. `MyRequest` has two fields, name and age, while `MyResponse` has a single field, greeting.

- Importing Data Structures from Another Package:

``` 
import "other_package.proto";

message MyRequest {
  other_package.SomeMessage some_data = 1;
}
```

## Create Protocol buffers for our project:

- Services: We will have following services called `login`, `signup` and `get-user`. 

- Create `user.proto`, User object to return to the client.
```
syntax = "proto3";

package pb;
option go_package="github.com/djsmk123/server/pb";

message User{
    int32 id=1;
    string username=2;
    string name=3;
}
```

- Create `rpc_login.proto`, it will have LoginRequestMessage and LoginReponseMessage

```
syntax="proto3";
package pb;
import "user.proto";
option go_package="github.com/djsmk123/server/pb";


message LoginRequestMessage{
    string username=1;
    string password=2;
}

message LoginResponseMessage{
    User user=1;
    string access_token=2;
}

```

- Same for `rpc_signup.proto`:

```
syntax="proto3";
package pb;
import "user.proto";
option go_package="github.com/djsmk123/server/pb";


message SignupRequestMessage{
    string username=1;
    string password=2;
    string name=3;
}

message SignupResponseMessage{
    User user=1;
    
}

```
- To create message `rpc_get_user.proto`: 
```
syntax="proto3";
package pb;
import "user.proto";
option go_package="github.com/djsmk123/server/pb";

message GetUserResponse{
    User user=1;
}
```

- Create service `rpc_services.proto`
```
syntax="proto3";
package pb;
option go_package="github.com/djsmk123/server/pb";
import "empty_request.proto";
import "rpc_get_user.proto";
import "rpc_login.proto";
import "rpc_signup.proto";

service GrpcServerService {
    rpc SignUp(SignupRequestMessage) returns (SignupResponseMessage){};

    rpc login(LoginRequestMessage) returns (LoginResponseMessage){};
    rpc GetUser(EmptyRequest) returns (GetUserResponse) {};
}
message EmptyRequest{
    
}
```

## Generate code for Golang

- Create `pb` package in root folder.
- Run command to generate equivalent code for golang 
```
protoc --proto_path=proto --go_out=pb --go_opt=paths=source_relative \
    --go-grpc_out=pb --go-grpc_opt=paths=source_relative \
    proto/*.proto
```

![image 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xrjl4bhl3vh8woq1pzsv.png)

## Create Basic Auth function
- Create `Auth` Package: This package has basic function like `get-user`,`login`, `signup`,`tokenCreation` and function to convert MongoDB userModel to gRPC `user` Messsage.

- Create `converter.go` in `auth` package.
{% gist https://gist.github.com/Djsmk123/42b6349b62cbb7bb8ecefd062b70a618 %}

- Create `token_generate.go` to generate token.
{% gist https://gist.github.com/Djsmk123/ff4f4ed8f48e236eaef62025416524a0 %}

- Create `login.go`
{% gist https://gist.github.com/Djsmk123/e5ef70ede9286e2817f164498f47d6bf %}

- Create `signup.go`

{% gist https://gist.github.com/Djsmk123/753d829b5bb5c0701bb4df49321944b5 %}

- Create `get-user.go`
{% gist https://gist.github.com/Djsmk123/8d19daf99f4ea75e78561d1310873676 %}


## Setup Server and Middlware 

- Create `server.go` in `gapi` package struct to register `GrpcServiceServer`.

{% gist https://gist.github.com/Djsmk123/71a867e4cd9ce66c400b11b7cbc2b1f1 %}

- For creating middlware for Authentication, we will need [`Unary Interceptors`](https://shijuvar.medium.com/writing-grpc-interceptors-in-go-bf3e7671fe48) but before that we will check,if request service required authentication or not, we will list all method that are not required token.
> Note by default all the method have restriction for auth token.

Create `services.go`

{% gist https://gist.github.com/Djsmk123/2847da6609c108e9a6a334ab36bc9f5d  %}

- Create `middlware.go`

{% gist https://gist.github.com/Djsmk123/9fcf99688783532e3bf2b2c8b5456a2d %}


## Connect whole and start server

finally we are going to main function in `main.go`,lets load environment, connect database(MongoDb) and RunServer.
{% gist https://gist.github.com/Djsmk123/ea29704877afcb2b6af355783575ad5d %}

## Run Server

```
go run .
```

## Test server

You can test gRPC services using [`evans-cli`](https://github.com/ktr0731/evans).
- Start CLI Tool

```
evans --host localhost --port 9090 -r repl
```

- Call `login` service

```
call login
```



![output1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vkdhip9jx584ne8z3h8p.png)

!!!Oops,we forgot to define `login`,`get-user` and `signup` from `pb` interface.


- Create `auth.go` in `gapi` package.

{% gist https://gist.github.com/Djsmk123/4875bd7b05238d36585f26e3bee3ad5c %}

## Try again 



![output2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dzvde8h2crt9xx3vzkcr.png)

---

## Flutter Project

- This Flutter application features four key pages: `SplashScreen`, `LoginScreen`, `SignUpScreen`, and `HomeScreen`.

- **SplashScreen**: This initial page verifies the user's authentication status. If authenticated, it communicates with the `gRPC` server using the `get-user` service and redirects the user to the `HomeScreen`. Otherwise, it navigates to the `LoginScreen`.

- **LoginScreen**: The LoginScreen presents fields for entering a `username` and `password`. Upon pressing the submit button, the application invokes the `login` service to authenticate the user. The `access_token` is saved to local storage, and the user is redirected to the `HomeScreen`.

- **SignUpScreen**: The SignUpScreen offers fields for `name`, `username`, `password`, and `confirmpassword`. When the user submits the form, the application calls the `signup` service on the `gRPC` server.


> Note: Not going to create whole UI and remaining Login,but only will cover required parts. You are free to create your own ui or can refer from whole in github repo.

## Setup Project

- Add following dependencies into `pubspec.yaml`
```
  shared_preferences: ^2.2.1
  protobuf: ^3.1.0
  grpc: ^3.2.3
```
- Install `protoc_plugin` for dart.
```
dart pub global activate protoc_plugin
```

- Copy `.proto` files from server to root folder of the flutter project.

- Created equivalent code in dart

```
protoc --proto_path=proto --dart_out=grpc:lib/pb proto/*.proto
```
- Create channel for gRPC services `services/grpc_services.dart`
{% gist https://gist.github.com/Djsmk123/44dd0d488bfc9278c9edc1783275aa57 %}


- Create AuthServices for different method like `login`,`signup` and `get-user`

{% gist https://gist.github.com/Djsmk123/afb881c80deb731a48a28a775258a5d6 %}


- We are done just call function in presentation layer and add your own logic.

## OUTPUT

![1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x8lraakwu7oy3z9pfoq8.jpg)

![2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v9zksi2iehzljb91msch.jpg)

![3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/15izyvs45n9w8k3zgxfa.jpg)


![4](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gxqbb99vsb5k0b7y1233.jpg)


![5](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o5sdxjguxdrtxchxavat.jpg)


![6](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jjrmaipxazub5s0l0e50.jpg)

Thanks for joining me on this tech adventure! We hope you've enjoyed the journey through gRPC, Flutter, and Golang as much as I have. But wait, the fun doesn't stop here!

Stay tuned for my upcoming blogs, where I'll sprinkle more humor, insights, and tech wizardry into your day. Who knows, in my next episode, we might just unveil the secret to debugging code with a magic wand (disclaimer: we can't actually do that, but a coder can dream, right?).

Until then, keep coding, keep laughing, and keep those fingers ready on the refresh button because the next tech tale is just around the corner! 🚀✨"





## Source code 
[Github Repo](https://github.com/Djsmk123/wtf-is-grpc)

## Follow me on 

- [Twitter](https://twitter.com/smk_winner)

- [Instagram](https://www.instagram.com/smkwinner/)

- [Github](https://www.github.com/djsmk123)

- [linkedin](https://www.linkedin.com/in/md-mobin-bb928820b/)

- [dev.to](https://dev.to/djsmk123)

- [Medium](https://medium.com/@djsmk123)