tutorial

  1. Integrasi gRPC dengan OAuth2


title: “59. Integrasi gRPC dengan OAuth2: Panduan Lengkap dan Praktis” date: 2024-07-08 author: Senior Software Engineer tags: [gRPC, OAuth2, Security, Golang, Microservices, Authentication]

Pendahuluan

Pada era di mana microservices menjadi arsitektur primadona, keamanan komunikasi antar layanan menjadi prioritas utama. Salah satu protokol RPC modern, yaitu gRPC, semakin populer karena efisiensi dan fleksibilitasnya. Namun, bagaimana Anda memastikan komunikasi di antara layanan gRPC tetap aman? Di sinilah OAuth2 berperan sebagai mekanisme otentikasi yang kokoh dan teruji.

Artikel ini membahas end-to-end integrasi gRPC dengan OAuth2 — mulai dari konsep dasar, arsitektur, hingga implementasi lengkap beserta simulasi dan contoh kode menggunakan Golang. Cocok bagi Anda yang ingin membangun microservices yang secure by design.


Konsep Dasar gRPC dan OAuth2

gRPC adalah framework RPC (Remote Procedure Call) open-source dari Google, berbasis protokol HTTP/2 dan Protobuf. Keunggulannya ada pada efisiensi, language-agnostic, serta streaming data.

OAuth2 adalah standar otorisasi modern yang banyak dipakai untuk mengelola akses terhadap REST API, serta kini juga diadopsi pada komunikasi API modern seperti gRPC.

Mengapa OAuth2 untuk gRPC?

  • Single Sign-On (SSO) untuk service-to-service.
  • Mendukung scopes dan roles based access.
  • Skala distribusi, audit, dan pengelolaan token sentral.

Arsitektur Integrasi gRPC + OAuth2

Secara umum, flow integrasi OAuth2 pada skenario gRPC service-to-service adalah sebagai berikut:

sequenceDiagram
    participant Client as gRPC Client
    participant AuthServer as OAuth2 Server
    participant Service as gRPC Server

    Client->>AuthServer: Request Access Token (client_credentials)
    AuthServer-->>Client: Access Token
    Client->>Service: gRPC Request with Bearer Token (metadata)
    Service-->>Client: Response / Error (Unauthorized if expired/invalid)

Penjelasan Alur

  1. Client melakukan request token ke OAuth2 server menggunakan grant type client_credentials.
  2. Mendapatkan access token (JWT) dari OAuth2 server.
  3. Setiap request gRPC menyisipkan token pada metadata (mirip header HTTP).
  4. gRPC Server melakukan verifikasi token setiap request dan memutuskan apakah request boleh dilayani.

Implementasi Integrasi: Studi Kasus di Golang

Kita akan membangun simulasi minimum viable:

  • gRPC Client (berperan sebagai microservice client)
  • OAuth2 Server (dummy)
  • gRPC Server (API provider, validasi token)

Catatan: Untuk lingkungan real-world, Anda dapat menggunakan OIDC Provider seperti Keycloak, Auth0, dsb. Namun di sini kita gunakan pendekatan dummy agar mudah dipahami.

1. Mendefinisikan Protobuf

Buat file greet.proto:

syntax = "proto3";

package greet;

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

2. Implementasi Dummy OAuth2 Server

// oauth2_server.go
package main

import (
    "net/http"
    "encoding/json"
    "time"
)

func main() {
    http.HandleFunc("/token", func(w http.ResponseWriter, r *http.Request) {
        // Validasi client_id dan secret, grant_type, dsb
        // Di dunia nyata, jangan seperti ini!
        token := map[string]interface{}{
            "access_token": "dummy-access-token",
            "token_type": "bearer",
            "expires_in": 3600,
        }
        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(token)
    })

    http.ListenAndServe(":8081", nil)
}

3. Server gRPC dengan Interceptor OAuth2

Interceptor untuk Validasi Bearer Token

import (
    "context"
    "google.golang.org/grpc"
    "google.golang.org/grpc/metadata"
    "google.golang.org/grpc/codes"
    "google.golang.org/grpc/status"
)

func authUnaryInterceptor(
    ctx context.Context,
    req interface{},
    info *grpc.UnaryServerInfo,
    handler grpc.UnaryHandler,
) (interface{}, error) {
    md, ok := metadata.FromIncomingContext(ctx)
    if !ok {
        return nil, status.Errorf(codes.Unauthenticated, "metadata tidak ditemukan")
    }

    tokens := md["authorization"]
    if len(tokens) < 1 || tokens[0] != "Bearer dummy-access-token" {
        return nil, status.Errorf(codes.Unauthenticated, "akses ditolak, token tidak valid")
    }

    return handler(ctx, req)
}

Setup Server

s := grpc.NewServer(grpc.UnaryInterceptor(authUnaryInterceptor))
// Daftarkan service Greeter
pb.RegisterGreeterServer(s, &GreeterServer{})

4. Client: Ambil Token & Lakukan Panggilan RPC

func getAccessToken() (string, error) {
    resp, err := http.PostForm("http://localhost:8081/token", url.Values{
        "grant_type":    {"client_credentials"},
        "client_id":     {"test"},
        "client_secret": {"test123"},
    })
    // parsing response JSON, return access_token
}

func main() {
    conn, _ := grpc.Dial("localhost:50051", grpc.WithInsecure())
    client := pb.NewGreeterClient(conn)

    // Dapatkan access token
    token, _ := getAccessToken()

    // Kirim metadata dengan token
    md := metadata.Pairs("authorization", fmt.Sprintf("Bearer %s", token))
    ctx := metadata.NewOutgoingContext(context.Background(), md)

    resp, err := client.SayHello(ctx, &pb.HelloRequest{Name: "OAuth2"})
}

Tabel Komparasi: Integrasi gRPC tanpa dan dengan OAuth2

FiturTanpa OAuth2Dengan OAuth2
OtentikasiTidak adaAccess Token JWT
OtorisasiTidak adaScope/role-based
Audit LogTidak tersediaTersedia (token claim)
Single Sign-OnTidak bisaBisa
Manajemen Token ExpiryManual / Tidak adaOtomatis (expires_in)

Best Practice & Simulasi Attack

Simulasi: Client mencoba request ke gRPC server TANPA menyematkan token.

Hasil:
Server menolak dengan status Unauthenticated.

Ini memastikan bahwa hanya client yang memiliki access-token valid dari OAuth2 server yang dapat mengakses resource di RPC server.

Tips Production:

  • Gunakan token proper (misal JWT) dan library jwt-go untuk parsing dan validasi.
  • Gunakan TLS (gRPC mendukung TLS secara natif).
  • Pastikan token tidak hardcoded!

Kesimpulan

Integrasi gRPC dengan OAuth2 sangat penting untuk menjaga keamanan arsitektur microservices Anda. Dengan menerapkan interceptor pada gRPC server, kita bisa memastikan semua permintaan terverifikasi — sekaligus menyiapkan jalur untuk future enhancement seperti role-based access control.

Ingat: Untuk lingkungan production gunakan OAuth2 provider populer (Keycloak, Auth0) serta JWT verification yang komprehensif. Integrasi ini scalable baik untuk B2B, SaaS, maupun internal systems.


Masih banyak pengembangan lanjutan (scope, policy, dynamic permission) yang bisa diintegrasikan. Namun semoga artikel ini memberi pondasi kuat dan praktikal untuk perjalanan adopsi OAuth2 dengan gRPC di sistem Anda.

Selamat mencoba, dan tetap utamakan keamanan! 🚀

comments powered by Disqus