Authentication

This document provides an overview of gRPC authentication, including our built-in supported auth mechanisms, how to plug in your own authentication systems, and examples of how to use gRPC auth in our supported languages.

Overview

gRPC is designed to work with a variety of authentication mechanisms, making iteasy to safely use gRPC to talk to other systems. You can use our supportedmechanisms - SSL/TLS with or without Google token-based authentication - or youcan plug in your own authentication system by extending our provided code.

gRPC also provides a simple authentication API that lets you provide all thenecessary authentication information as Credentials when creating a channel ormaking a call.

Supported auth mechanisms

The following authentication mechanisms are built-in to gRPC:

  • SSL/TLS: gRPC has SSL/TLS integration and promotes the use of SSL/TLSto authenticate the server, and to encrypt all the data exchanged betweenthe client and the server. Optional mechanisms are available for clients toprovide certificates for mutual authentication.
  • Token-based authentication with Google: gRPC provides a genericmechanism (described below) to attach metadata based credentials to requestsand responses. Additional support for acquiring access tokens(typically OAuth2 tokens) while accessing Google APIs through gRPC isprovided for certain auth flows: you can see how this works in our codeexamples below. In general this mechanism must be used as well as SSL/TLSon the channel - Google will not allow connections without SSL/TLS, andmost gRPC language implementations will not let you send credentials on anunencrypted channel.

Warning

Google credentials should only be used to connect to Google services. Sending a Google issued OAuth2 token to a non-Google service could result in this token being stolen and used to impersonate the client to Google services.

Authentication API

gRPC provides a simple authentication API based around the unified concept ofCredentials objects, which can be used when creating an entire gRPC channel oran individual call.

Credential types

Credentials can be of two types:

  • Channel credentials, which are attached to a Channel, such as SSLcredentials.
  • Call credentials, which are attached to a call (or ClientContext inC++).

You can also combine these in a CompositeChannelCredentials, allowing you tospecify, for example, SSL details for the channel along with call credentialsfor each call made on the channel. A CompositeChannelCredentials associates aChannelCredentials and a CallCredentials to create a newChannelCredentials. The result will send the authentication data associatedwith the composed CallCredentials with every call made on the channel.

For example, you could create a ChannelCredentials from an SslCredentialsand an AccessTokenCredentials. The result when applied to a Channel wouldsend the appropriate access token for each call on this channel.

Individual CallCredentials can also be composed usingCompositeCallCredentials. The resulting CallCredentials when used in a callwill trigger the sending of the authentication data associated with the twoCallCredentials.

Using client-side SSL/TLS

Now let’s look at how Credentials work with one of our supported authmechanisms. This is the simplest authentication scenario, where a client justwants to authenticate the server and encrypt all data. The example is in C++,but the API is similar for all languages: you can see how to enable SSL/TLS inmore languages in our Examples section below.

  1. // Create a default SSL ChannelCredentials object.
  2. auto channel_creds = grpc::SslCredentials(grpc::SslCredentialsOptions());
  3. // Create a channel using the credentials created in the previous step.
  4. auto channel = grpc::CreateChannel(server_name, channel_creds);
  5. // Create a stub on the channel.
  6. std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
  7. // Make actual RPC calls on the stub.
  8. grpc::Status s = stub->sayHello(&context, *request, response);

For advanced use cases such as modifying the root CA or using client certs,the corresponding options can be set in the SslCredentialsOptions parameterpassed to the factory method.

Using Google token-based authentication

gRPC applications can use a simple API to create a credential that works forauthentication with Google in various deployment scenarios. Again, our exampleis in C++ but you can find examples in other languages in our Examples section.

  1. auto creds = grpc::GoogleDefaultCredentials();
  2. // Create a channel, stub and make RPC calls (same as in the previous example)
  3. auto channel = grpc::CreateChannel(server_name, creds);
  4. std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
  5. grpc::Status s = stub->sayHello(&context, *request, response);

This channel credentials object works for applications using Service Accounts aswell as for applications running inGoogle Compute Engine(GCE). In the former case, the serviceaccount’s private keys are loaded from the file named in the environmentvariable GOOGLE_APPLICATION_CREDENTIALS. The keys are used to generate bearertokens that are attached to each outgoing RPC on the corresponding channel.

For applications running in GCE, a default service account and correspondingOAuth2 scopes can be configured during VM setup. At run-time, this credentialhandles communication with the authentication systems to obtain OAuth2 accesstokens and attaches them to each outgoing RPC on the corresponding channel.

Extending gRPC to support other authentication mechanisms

The Credentials plugin API allows developers to plug in their own type ofcredentials. This consists of:

  • The MetadataCredentialsPlugin abstract class, which contains the pure virtualGetMetadata method that needs to be implemented by a sub-class created bythe developer.
  • The MetadataCredentialsFromPlugin function, which creates a CallCredentialsfrom the MetadataCredentialsPlugin.

Here is example of a simple credentials plugin which sets an authenticationticket in a custom header.

  1. class MyCustomAuthenticator : public grpc::MetadataCredentialsPlugin {
  2. public:
  3. MyCustomAuthenticator(const grpc::string& ticket) : ticket_(ticket) {}
  4. grpc::Status GetMetadata(
  5. grpc::string_ref service_url, grpc::string_ref method_name,
  6. const grpc::AuthContext& channel_auth_context,
  7. std::multimap<grpc::string, grpc::string>* metadata) override {
  8. metadata->insert(std::make_pair("x-custom-auth-ticket", ticket_));
  9. return grpc::Status::OK;
  10. }
  11. private:
  12. grpc::string ticket_;
  13. };
  14. auto call_creds = grpc::MetadataCredentialsFromPlugin(
  15. std::unique_ptr<grpc::MetadataCredentialsPlugin>(
  16. new MyCustomAuthenticator("super-secret-ticket")));

A deeper integration can be achieved by plugging in a gRPC credentialsimplementation at the core level. gRPC internals also allow switching outSSL/TLS with other encryption mechanisms.

Examples

These authentication mechanisms will be available in all gRPC’s supportedlanguages. The following sections demonstrate how authentication andauthorization features described above appear in each language: more languagesare coming soon.

Go

Base case - no encryption or authentication

Client:

  1. conn, _ := grpc.Dial("localhost:50051", grpc.WithInsecure())
  2. // error handling omitted
  3. client := pb.NewGreeterClient(conn)
  4. // ...

Server:

  1. s := grpc.NewServer()
  2. lis, _ := net.Listen("tcp", "localhost:50051")
  3. // error handling omitted
  4. s.Serve(lis)

With server authentication SSL/TLS

Client:

  1. creds, _ := credentials.NewClientTLSFromFile(certFile, "")
  2. conn, _ := grpc.Dial("localhost:50051", grpc.WithTransportCredentials(creds))
  3. // error handling omitted
  4. client := pb.NewGreeterClient(conn)
  5. // ...

Server:

  1. creds, _ := credentials.NewServerTLSFromFile(certFile, keyFile)
  2. s := grpc.NewServer(grpc.Creds(creds))
  3. lis, _ := net.Listen("tcp", "localhost:50051")
  4. // error handling omitted
  5. s.Serve(lis)

Authenticate with Google

  1. pool, _ := x509.SystemCertPool()
  2. // error handling omitted
  3. creds := credentials.NewClientTLSFromCert(pool, "")
  4. perRPC, _ := oauth.NewServiceAccountFromFile("service-account.json", scope)
  5. conn, _ := grpc.Dial(
  6. "greeter.googleapis.com",
  7. grpc.WithTransportCredentials(creds),
  8. grpc.WithPerRPCCredentials(perRPC),
  9. )
  10. // error handling omitted
  11. client := pb.NewGreeterClient(conn)
  12. // ...

Ruby

Base case - no encryption or authentication

  1. stub = Helloworld::Greeter::Stub.new('localhost:50051', :this_channel_is_insecure)
  2. ...

With server authentication SSL/TLS

  1. creds = GRPC::Core::ChannelCredentials.new(load_certs) # load_certs typically loads a CA roots file
  2. stub = Helloworld::Greeter::Stub.new('myservice.example.com', creds)

Authenticate with Google

  1. require 'googleauth' # from http://www.rubydoc.info/gems/googleauth/0.1.0
  2. ...
  3. ssl_creds = GRPC::Core::ChannelCredentials.new(load_certs) # load_certs typically loads a CA roots file
  4. authentication = Google::Auth.get_application_default()
  5. call_creds = GRPC::Core::CallCredentials.new(authentication.updater_proc)
  6. combined_creds = ssl_creds.compose(call_creds)
  7. stub = Helloworld::Greeter::Stub.new('greeter.googleapis.com', combined_creds)

C++

Base case - no encryption or authentication

  1. auto channel = grpc::CreateChannel("localhost:50051", InsecureChannelCredentials());
  2. std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
  3. ...

With server authentication SSL/TLS

  1. auto channel_creds = grpc::SslCredentials(grpc::SslCredentialsOptions());
  2. auto channel = grpc::CreateChannel("myservice.example.com", channel_creds);
  3. std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
  4. ...

Authenticate with Google

  1. auto creds = grpc::GoogleDefaultCredentials();
  2. auto channel = grpc::CreateChannel("greeter.googleapis.com", creds);
  3. std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
  4. ...

C

Base case - no encryption or authentication

  1. var channel = new Channel("localhost:50051", ChannelCredentials.Insecure);
  2. var client = new Greeter.GreeterClient(channel);
  3. ...

With server authentication SSL/TLS

  1. var channelCredentials = new SslCredentials(File.ReadAllText("roots.pem")); // Load a custom roots file.
  2. var channel = new Channel("myservice.example.com", channelCredentials);
  3. var client = new Greeter.GreeterClient(channel);

Authenticate with Google

  1. using Grpc.Auth; // from Grpc.Auth NuGet package
  2. ...
  3. // Loads Google Application Default Credentials with publicly trusted roots.
  4. var channelCredentials = await GoogleGrpcCredentials.GetApplicationDefaultAsync();
  5. var channel = new Channel("greeter.googleapis.com", channelCredentials);
  6. var client = new Greeter.GreeterClient(channel);
  7. ...

Authenticate a single RPC call

  1. var channel = new Channel("greeter.googleapis.com", new SslCredentials()); // Use publicly trusted roots.
  2. var client = new Greeter.GreeterClient(channel);
  3. ...
  4. var googleCredential = await GoogleCredential.GetApplicationDefaultAsync();
  5. var result = client.SayHello(request, new CallOptions(credentials: googleCredential.ToCallCredentials()));
  6. ...

Python

Base case - No encryption or authentication

  1. import grpc
  2. import helloworld_pb2
  3. channel = grpc.insecure_channel('localhost:50051')
  4. stub = helloworld_pb2.GreeterStub(channel)

With server authentication SSL/TLS

Client:

  1. import grpc
  2. import helloworld_pb2
  3. with open('roots.pem', 'rb') as f:
  4. creds = grpc.ssl_channel_credentials(f.read())
  5. channel = grpc.secure_channel('myservice.example.com:443', creds)
  6. stub = helloworld_pb2.GreeterStub(channel)

Server:

  1. import grpc
  2. import helloworld_pb2
  3. from concurrent import futures
  4. server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
  5. with open('key.pem', 'rb') as f:
  6. private_key = f.read()
  7. with open('chain.pem', 'rb') as f:
  8. certificate_chain = f.read()
  9. server_credentials = grpc.ssl_server_credentials( ( (private_key, certificate_chain), ) )
  10. # Adding GreeterServicer to server omitted
  11. server.add_secure_port('myservice.example.com:443', server_credentials)
  12. server.start()
  13. # Server sleep omitted

Authenticate with Google using a JWT

  1. import grpc
  2. import helloworld_pb2
  3. from google import auth as google_auth
  4. from google.auth import jwt as google_auth_jwt
  5. from google.auth.transport import grpc as google_auth_transport_grpc
  6. credentials, _ = google_auth.default()
  7. jwt_creds = google_auth_jwt.OnDemandCredentials.from_signing_credentials(
  8. credentials)
  9. channel = google_auth_transport_grpc.secure_authorized_channel(
  10. jwt_creds, None, 'greeter.googleapis.com:443')
  11. stub = helloworld_pb2.GreeterStub(channel)

Authenticate with Google using an Oauth2 token

  1. import grpc
  2. import helloworld_pb2
  3. from google import auth as google_auth
  4. from google.auth.transport import grpc as google_auth_transport_grpc
  5. from google.auth.transport import requests as google_auth_transport_requests
  6. credentials, _ = google_auth.default(scopes=(scope,))
  7. request = google_auth_transport_requests.Request()
  8. channel = google_auth_transport_grpc.secure_authorized_channel(
  9. credentials, request, 'greeter.googleapis.com:443')
  10. stub = helloworld_pb2.GreeterStub(channel)

Java

Base case - no encryption or authentication

  1. ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 50051)
  2. .usePlaintext(true)
  3. .build();
  4. GreeterGrpc.GreeterStub stub = GreeterGrpc.newStub(channel);

With server authentication SSL/TLS

In Java we recommend that you use OpenSSL when using gRPC over TLS. You can finddetails about installing and using OpenSSL and other required libraries for bothAndroid and non-Android Java in the gRPC JavaSecuritydocumentation.

To enable TLS on a server, a certificate chain and private key need to bespecified in PEM format. Such private key should not be using a password.The order of certificates in the chain matters: more specifically, the certificateat the top has to be the host CA, while the one at the very bottomhas to be the root CA. The standard TLS port is 443, but we use 8443 below toavoid needing extra permissions from the OS.

  1. Server server = ServerBuilder.forPort(8443)
  2. // Enable TLS
  3. .useTransportSecurity(certChainFile, privateKeyFile)
  4. .addService(TestServiceGrpc.bindService(serviceImplementation))
  5. .build();
  6. server.start();

If the issuing certificate authority is not known to the client then a properlyconfigured SslContext or SSLSocketFactory should be provided to theNettyChannelBuilder or OkHttpChannelBuilder, respectively.

On the client side, server authentication with SSL/TLS looks like this:

  1. // With server authentication SSL/TLS
  2. ManagedChannel channel = ManagedChannelBuilder.forAddress("myservice.example.com", 443)
  3. .build();
  4. GreeterGrpc.GreeterStub stub = GreeterGrpc.newStub(channel);
  5. // With server authentication SSL/TLS; custom CA root certificates; not on Android
  6. ManagedChannel channel = NettyChannelBuilder.forAddress("myservice.example.com", 443)
  7. .sslContext(GrpcSslContexts.forClient().trustManager(new File("roots.pem")).build())
  8. .build();
  9. GreeterGrpc.GreeterStub stub = GreeterGrpc.newStub(channel);

Authenticate with Google

The following code snippet shows how you can call theGoogle Cloud PubSubAPI using gRPC with a serviceaccount. The credentials are loaded from a key stored in a well-known locationor by detecting that the application is running in an environment that canprovide one automatically, e.g. Google Compute Engine. While this example isspecific to Google and its services, similar patterns can be followed for otherservice providers.

  1. GoogleCredentials creds = GoogleCredentials.getApplicationDefault();
  2. ManagedChannel channel = ManagedChannelBuilder.forTarget("greeter.googleapis.com")
  3. .build();
  4. GreeterGrpc.GreeterStub stub = GreeterGrpc.newStub(channel)
  5. .withCallCredentials(MoreCallCredentials.from(creds));

Node.js

Base case - No encryption/authentication

  1. var stub = new helloworld.Greeter('localhost:50051', grpc.credentials.createInsecure());

With server authentication SSL/TLS

  1. var ssl_creds = grpc.credentials.createSsl(root_certs);
  2. var stub = new helloworld.Greeter('myservice.example.com', ssl_creds);

Authenticate with Google

  1. // Authenticating with Google
  2. var GoogleAuth = require('google-auth-library'); // from https://www.npmjs.com/package/google-auth-library
  3. ...
  4. var ssl_creds = grpc.credentials.createSsl(root_certs);
  5. (new GoogleAuth()).getApplicationDefault(function(err, auth) {
  6. var call_creds = grpc.credentials.createFromGoogleCredential(auth);
  7. var combined_creds = grpc.credentials.combineChannelCredentials(ssl_creds, call_creds);
  8. var stub = new helloworld.Greeter('greeter.googleapis.com', combined_credentials);
  9. });

Authenticate with Google using Oauth2 token (legacy approach)

  1. var GoogleAuth = require('google-auth-library'); // from https://www.npmjs.com/package/google-auth-library
  2. ...
  3. var ssl_creds = grpc.Credentials.createSsl(root_certs); // load_certs typically loads a CA roots file
  4. var scope = 'https://www.googleapis.com/auth/grpc-testing';
  5. (new GoogleAuth()).getApplicationDefault(function(err, auth) {
  6. if (auth.createScopeRequired()) {
  7. auth = auth.createScoped(scope);
  8. }
  9. var call_creds = grpc.credentials.createFromGoogleCredential(auth);
  10. var combined_creds = grpc.credentials.combineChannelCredentials(ssl_creds, call_creds);
  11. var stub = new helloworld.Greeter('greeter.googleapis.com', combined_credentials);
  12. });

PHP

Base case - No encryption/authorization

  1. $client = new helloworld\GreeterClient('localhost:50051', [
  2. 'credentials' => Grpc\ChannelCredentials::createInsecure(),
  3. ]);

Authenticate with Google

  1. function updateAuthMetadataCallback($context)
  2. {
  3. $auth_credentials = ApplicationDefaultCredentials::getCredentials();
  4. return $auth_credentials->updateMetadata($metadata = [], $context->service_url);
  5. }
  6. $channel_credentials = Grpc\ChannelCredentials::createComposite(
  7. Grpc\ChannelCredentials::createSsl(file_get_contents('roots.pem')),
  8. Grpc\CallCredentials::createFromPlugin('updateAuthMetadataCallback')
  9. );
  10. $opts = [
  11. 'credentials' => $channel_credentials
  12. ];
  13. $client = new helloworld\GreeterClient('greeter.googleapis.com', $opts);

Authenticate with Google using Oauth2 token (legacy approach)

  1. // the environment variable "GOOGLE_APPLICATION_CREDENTIALS" needs to be set
  2. $scope = "https://www.googleapis.com/auth/grpc-testing";
  3. $auth = Google\Auth\ApplicationDefaultCredentials::getCredentials($scope);
  4. $opts = [
  5. 'credentials' => Grpc\Credentials::createSsl(file_get_contents('roots.pem'));
  6. 'update_metadata' => $auth->getUpdateMetadataFunc(),
  7. ];
  8. $client = new helloworld\GreeterClient('greeter.googleapis.com', $opts);

Dart

Base case - no encryption or authentication

  1. final channel = new ClientChannel('localhost',
  2. port: 50051,
  3. options: const ChannelOptions(
  4. credentials: const ChannelCredentials.insecure()));
  5. final stub = new GreeterClient(channel);

With server authentication SSL/TLS

  1. // Load a custom roots file.
  2. final trustedRoot = new File('roots.pem').readAsBytesSync();
  3. final channelCredentials =
  4. new ChannelCredentials.secure(certificates: trustedRoot);
  5. final channelOptions = new ChannelOptions(credentials: channelCredentials);
  6. final channel = new ClientChannel('myservice.example.com',
  7. options: channelOptions);
  8. final client = new GreeterClient(channel);

Authenticate with Google

  1. // Uses publicly trusted roots by default.
  2. final channel = new ClientChannel('greeter.googleapis.com');
  3. final serviceAccountJson =
  4. new File('service-account.json').readAsStringSync();
  5. final credentials = new JwtServiceAccountAuthenticator(serviceAccountJson);
  6. final client =
  7. new GreeterClient(channel, options: credentials.toCallOptions);

Authenticate a single RPC call

  1. // Uses publicly trusted roots by default.
  2. final channel = new ClientChannel('greeter.googleapis.com');
  3. final client = new GreeterClient(channel);
  4. ...
  5. final serviceAccountJson =
  6. new File('service-account.json').readAsStringSync();
  7. final credentials = new JwtServiceAccountAuthenticator(serviceAccountJson);
  8. final response =
  9. await client.sayHello(request, options: credentials.toCallOptions);