This TypeScript library provides an HMAC authentication interceptor for gRPC, simplifying the process of setting up HMAC authentication for both server and client. It utilizes grpc-js, the official gRPC library for Node.js, employing interceptors to seamlessly integrate HMAC authentication into the gRPC server and client.
npm install --save-dev grpc-hmac-interceptor
Add the HMAC server interceptor to the gRPC server.
// keyId for which secret_key is returned by hmac.GetSecret func type
const getSecret: GetSecret = (keyId: string) => {
// return secret_key for the keyId
return secretKey;
};
// create HMAC server interceptor
const interceptor = NewServerInterceptor(getSecret);
let server: Server = new Server({ interceptors: [interceptor.WithInterceptor()] });
Create the HMAC client interceptor using the provided function NewClientInterceptor
. By default, the interceptor expects the proto to be loaded by @grpc/proto-loader
, and the @grpc/grpc-js
library can be used. If the proto is loaded by protoc, you need to pass true
as the third argument in the interceptor function call.
// keyId and secretKey for HMAC authentication
const target = "localhost:50051";
const interceptor = NewClientInterceptor(keyId, secretKey);
// create gRPC client
const client: ServiceClient = new construct(target, credentials.createInsecure(), {
interceptors: [interceptor.WithInterceptor()]
});
In this case, the proto is loaded by @grpc/proto-loader
, and you can use the @grpc/grpc-js
library for your gRPC client.
// keyId and secretKey for HMAC authentication
const target = "localhost:50051";
const interceptor = NewClientInterceptor(keyId, secretKey, true);
// create gRPC client
const client: ServiceClient = new construct(target, credentials.createInsecure(), {
interceptors: [interceptor.WithInterceptor()]
});
In this case, the proto is loaded by protoc
or grpc-tools
, as the messaged wrapped with jspb.Message
, so interceptor needs to handle the message accordingly.
✏️ Example
# go to example directory
pushd example
# install the dependencies
npm install
# Update the grpc-hmac-interceptor to the latest version
npm install grpc-hmac-interceptor@latest # <latest> is the latest version
# run the example # it will start server with HMAC interceptor and two clients with HMAC interceptor, one with valid HMAC and other with invalid HMAC signature
./run.sh
Steps for generating the HMAC:
- Encode Request Payload: stringify the request payload
- Concatenate with Method Name: build a message by concatenation
request=<stringified request>;method=<method name>
, whererequest
is the stringified request payload andmethod
is the name of the method being called, e.g.request={"name":"John"};method=/example.UserService/GetUser
. If the request payload is empty, the message will be just method name, e.g.method=/example.UserService/GetUser
. - Encrypt with Secret: encrypt the concatenated message using the SHA512_256 algorithm and a secret key. HMAC typically involves using a cryptographic hash function (in this case, SHA512_256) along with a secret key to generate a fixed-size hash value.
- Base64 Encode: encode the encrypted message to base64 to ensure that it is transmitted safely.
Steps for verifying the HMAC:
- Client Interceptor: The client interceptor will add the
x-hmac-key-id
andx-hmac-signature
to the outgoing request metadata. - Server Interceptor: The server interceptor will extract the
x-hmac-key-id
andx-hmac-signature
from the incoming request metadata, and then verify the HMAC signature using thex-hmac-key-id
and the secret key associated with the key id. - if signature is valid, the request will be processed, otherwise
UNAUTHENTICATED
error will be returned.
We welcome contributions to ts-grpc-hmac! Please see the CONTRIBUTING.md file for more information.