gRPCでユーザ/パスワード認証をする


環境

Client Server
言語 Ruby Go

参考にしたコード

https://github.com/grpc/grpc-go/issues/106#issuecomment-246978683
(clientとserverを両方goで実装した例)

ソースコード

gRPCリクエストのメタデータでusernamepasswordを渡し、認証をします。

Client

client.rb
stub = HogeServer::Stub.new("localhost:99999", :this_channel_is_insecure)
request = HogeRequest.new(hoge: 'fuga')
metadata = { username: 'admin', password: 'admin123' }
stub.hoge(request, metadata: metadata)

Server

server.go
import (
    grpc "google.golang.org/grpc"
    metadata "google.golang.org/grpc/metadata"
)

grpcServer := grpc.NewServer(
    grpc.StreamInterceptor(streamInterceptor),
    grpc.UnaryInterceptor(unaryInterceptor),
)

func streamInterceptor(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
    if err := authorize(stream.Context()); err != nil {
        return err
    }
    return handler(srv, stream)
}

func unaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
    if err := authorize(ctx); err != nil {
        return nil, err
    }
    return handler(ctx, req)
}

func authorize(ctx context.Context) error {
    if md, ok := metadata.FromIncomingContext(ctx); ok {
        if len(md["username"]) > 0 && md["username"][0] == "admin" &&
            len(md["password"]) > 0 && md["password"][0] == "admin123" {
            return nil
        }
        return errors.New("AccessDeniedError")
    }
    return errors.New("EmptyMetadataError")
}