Episode ini mengamankan gRPC: menyiapkan sertifikat dan TLS di server maupun client, mutual TLS untuk otentikasi dua arah, serta integrasi modern dengan JWT, OAuth2, dan token-based auth yang dikirim lewat metadata.

Sejauh ini semua koneksi gRPC kita plaintext — aman untuk belajar, berbahaya untuk produksi. Siapa pun di jaringan yang sama bisa membaca payload. Episode 11 menutup celah itu dengan TLS dan, untuk kebutuhan yang lebih ketat, mutual TLS (mTLS).
Selain enkripsi, kita membahas autentikasi identitas: memverifikasi siapa pemanggil. Dua pendekatan utama dibahas: kredensial transport (mTLS) dan kredensial per-panggilan (JWT, OAuth2, token). Keduanya sering dipakai bersama — TLS mengenkripsi, token mengotorisasi.
Untuk development, buat CA, sertifikat server, dan sertifikat client dengan openssl:
openssl req -x509 -newkey rsa:2048 -nodes \
-keyout ca.key -out ca.crt -days 365 \
-subj "/CN=belajar-grpc-ca"
openssl req -newkey rsa:2048 -nodes \
-keyout server.key -out server.csr \
-subj "/CN=localhost"
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out server.crt -days 365Tiga perintah ini membuat Certificate Authority (CA), request sertifikat server untuk localhost, dan menandatanganinya dengan CA. openssl x509 -req menandatangani sertifikat — persis proses yang dilakukan CA publik di internet.
Server memuat sertifikat dan kunci pribadi, lalu membuat kredensial:
creds, err := credentials.NewServerTLSFromFile("server.crt", "server.key")
if err != nil {
log.Fatal(err)
}
s := grpc.NewServer(grpc.Creds(creds))
pb.RegisterCatalogServiceServer(s, &catalogServer{})credentials.NewServerTLSFromFile("server.crt", "server.key") membaca pasangan sertifikat-kunci dan menghasilkan kredensial yang dibutuhkan grpc.NewServer.
Client harus memakai TLS dan mempercayai CA kita:
ca := x509.NewCertPool()
pem, _ := os.ReadFile("ca.crt")
ca.AppendCertsFromPEM(pem)
creds := credentials.NewClientTLSFromCert(ca, "localhost")
conn, _ := grpc.NewClient("localhost:50051",
grpc.WithTransportCredentials(creds))credentials.NewClientTLSFromCert(ca, "localhost") membuat kredensial yang memverifikasi sertifikat server terhadap CA kita. Tanpa trust CA ini, handshake gagal — itulah kerja TLS.
Di mTLS, bukan hanya server yang membuktikan diri; client juga harus menunjukkan sertifikat. Server dimodifikasi untuk meminta dan memverifikasi sertifikat client:
cert, _ := tls.LoadX509KeyPair("server.crt", "server.key")
ca := x509.NewCertPool()
pem, _ := os.ReadFile("ca.crt")
ca.AppendCertsFromPEM(pem)
tlsCfg := &tls.Config{
Certificates: []tls.Certificate{cert},
ClientCAs: ca,
ClientAuth: tls.RequireAndVerifyClientCert,
}
creds := credentials.NewTLS(tlsCfg)
s := grpc.NewServer(grpc.Creds(creds))Pengaturan ClientAuth: tls.RequireAndVerifyClientCert memaksa client membuktikan identitasnya dengan sertifikat yang ditandatangani CA yang sama. Hanya client yang punya kunci privat valid yang bisa terhubung.
Client memuat sertifikatnya sendiri selain mempercayai CA:
cert, _ := tls.LoadX509KeyPair("client.crt", "client.key")
creds := credentials.NewTLS(&tls.Config{
Certificates: []tls.Certificate{cert},
RootCAs: ca,
})
conn, _ := grpc.NewClient("localhost:50051",
grpc.WithTransportCredentials(creds))credentials.NewTLS(&tls.Config{...}) memberi client sertifikat untuk dikirim ke server. mTLS ideal untuk komunikasi antar service internal yang terkelola.
Kredensial per-panggilan dikirim lewat metadata sebagai header authorization:
ctx := metadata.AppendToOutgoingContext(
ctx, "authorization", "Bearer " + token,
)
res, err := client.GetProduct(ctx, &pb.ProductId{Id: "p-001"})Server mengekstrak dan memverifikasi token di interceptor (episode 6):
claims := jwt.MapClaims{}
_, err := jwt.ParseWithClaims(bearer, claims, func(t *jwt.Token) (any, error) {
return publicKey, nil
})
if err != nil {
return nil, status.Error(codes.Unauthenticated, "token tidak valid")
}jwt.ParseWithClaims(...) memverifikasi tanda tangan JWT. Klaim di dalam token — seperti sub dan scope — menjadi dasar otorisasi di episode 12.
Untuk skenario di mana client mewakili user, pakai OAuth2: client memperoleh access token dari authorization server, lalu mengirimnya di setiap panggilan. gRPC menyediakan credentials.OAuth untuk membungkus token dan refresh token secara otomatis:
perRPC := oauth.NewOauthAccess(
&oauth2.Token{AccessToken: token, TokenType: "Bearer"},
)
conn, _ := grpc.NewClient("localhost:50051",
grpc.WithTransportCredentials(creds),
grpc.WithPerRPCCredentials(perRPC),
)grpc.WithPerRPCCredentials(perRPC) membuat client menambahkan token ke setiap RPC secara otomatis. Server cukup memvalidasi token terhadap authorization server.
Inti yang harus dibawa pulang:
GRPC_TLS dari episode 7 menjadi pintunya.Di episode 12 selanjutnya kita membahas authorization, auditing, dan best practice keamanan — otorisasi level method, policy enforcement, audit logging dan perlindungan metadata sensitif, serta rate limiting, circuit breaking, dan proteksi terhadap serangan DoS. Koneksi yang terenkripsi sekarang akan dilengkapi kontrol akses yang menyeluruh.