An overview of gRPC authentication, including built-in auth mechanisms, and how to plug in your own authentication systems.
gRPC is designed to work with a variety of authentication mechanisms, making it easy to safely use gRPC to talk to other systems. You can use our supported mechanisms - SSL/TLS with or without Google token-based authentication - or you can plug in your own authentication system by extending our provided code.
gRPC also provides a simple authentication API that lets you provide all the necessary authentication information as Credentials
when creating a channel or making a call.
The following authentication mechanisms are built-in to gRPC:
gRPC provides a simple authentication API based around the unified concept of Credentials objects, which can be used when creating an entire gRPC channel or an individual call.
Credentials can be of two types:
Channel
, such as SSL credentials.ClientContext
in C++).You can also combine these in a CompositeChannelCredentials
, allowing you to specify, for example, SSL details for the channel along with call credentials for each call made on the channel. A CompositeChannelCredentials
associates a ChannelCredentials
and a CallCredentials
to create a new ChannelCredentials
. The result will send the authentication data associated with the composed CallCredentials
with every call made on the channel.
For example, you could create a ChannelCredentials
from an SslCredentials
and an AccessTokenCredentials
. The result when applied to a Channel
would send the appropriate access token for each call on this channel.
Individual CallCredentials
can also be composed using CompositeCallCredentials
. The resulting CallCredentials
when used in a call will trigger the sending of the authentication data associated with the two CallCredentials
.
Now let’s look at how Credentials
work with one of our supported auth mechanisms. This is the simplest authentication scenario, where a client just wants 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 in more languages in our Examples section below.
// Create a default SSL ChannelCredentials object. auto channel_creds = grpc::SslCredentials(grpc::SslCredentialsOptions()); // Create a channel using the credentials created in the previous step. auto channel = grpc::CreateChannel(server_name, channel_creds); // Create a stub on the channel. std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel)); // Make actual RPC calls on the stub. 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
parameter passed to the factory method.
SslCredentialsOptions
, since the defaults are only configured for POSIX filesystems.OAuth 2.0 Protocol is the industry-standard protocol for authorization. It enables websites or applications to obtain limited access to user accounts using OAuth tokens.
gRPC offers a set of simple APIs to integrate OAuth 2.0 into applications, streamlining authentication.
At a high level, using OAuth token-based authentication includes 3 steps:
For details of how to use OAuth token in different languages, please refer to our examples below.
gRPC applications can use a simple API to create a credential that works for authentication with Google in various deployment scenarios. Again, our example is in C++ but you can find examples in other languages in our Examples section.
auto creds = grpc::GoogleDefaultCredentials(); // Create a channel, stub and make RPC calls (same as in the previous example) auto channel = grpc::CreateChannel(server_name, creds); std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel)); grpc::Status s = stub->sayHello(&context, *request, response);
This channel credentials object works for applications using Service Accounts as well as for applications running in Google Compute Engine (GCE). In the former case, the service account’s private keys are loaded from the file named in the environment variable GOOGLE_APPLICATION_CREDENTIALS
. The keys are used to generate bearer tokens that are attached to each outgoing RPC on the corresponding channel.
For applications running in GCE, a default service account and corresponding OAuth2 scopes can be configured during VM setup. At run-time, this credential handles communication with the authentication systems to obtain OAuth2 access tokens and attaches them to each outgoing RPC on the corresponding channel.
The Credentials plugin API allows developers to plug in their own type of credentials. This consists of:
MetadataCredentialsPlugin
abstract class, which contains the pure virtual GetMetadata
method that needs to be implemented by a sub-class created by the developer.MetadataCredentialsFromPlugin
function, which creates a CallCredentials
from the MetadataCredentialsPlugin
.Here is example of a simple credentials plugin which sets an authentication ticket in a custom header.
classMyCustomAuthenticator:public grpc::MetadataCredentialsPlugin { public: MyCustomAuthenticator(const grpc::string& ticket) : ticket_(ticket) {} grpc::Status GetMetadata( grpc::string_ref service_url, grpc::string_ref method_name, const grpc::AuthContext& channel_auth_context, std::multimap<grpc::string, grpc::string>* metadata) override { metadata->insert(std::make_pair("x-custom-auth-ticket", ticket_)); return grpc::Status::OK; } private: grpc::string ticket_; }; auto call_creds = grpc::MetadataCredentialsFromPlugin( std::unique_ptr<grpc::MetadataCredentialsPlugin>( new MyCustomAuthenticator("super-secret-ticket")));
A deeper integration can be achieved by plugging in a gRPC credentials implementation at the core level. gRPC internals also allow switching out SSL/TLS with other encryption mechanisms.
These authentication mechanisms will be available in all gRPC’s supported languages. The following table links to examples demonstrating authentication and authorization in various languages.
Language | Example | Documentation |
---|---|---|
C++ | N/A | N/A |
Go | Go Example | Go Documentation |
Java | Java Example TLS (Java Example ATLS) | Java Documentation |
Python | Python Example | Python Documentation |
The following table links to examples demonstrating OAuth token-based authentication and authorization in various languages.
Language | Example | Documentation |
---|---|---|
C++ | N/A | N/A |
Go | Go OAuth Example | Go OAuth Documentation |
Java | Java OAuth Example | Java OAuth Documentation |
Python | Python OAuth Example | Python OAuth Documentation |
The following sections demonstrate how authentication and authorization features described above appear in other languages not listed above.
stub =Helloworld::Greeter::Stub.new('localhost:50051', :this_channel_is_insecure) ...
creds =GRPC::Core::ChannelCredentials.new(load_certs) # load_certs typically loads a CA roots filestub =Helloworld::Greeter::Stub.new('myservice.example.com', creds)
require'googleauth'# from http://www.rubydoc.info/gems/googleauth/0.1.0...ssl_creds =GRPC::Core::ChannelCredentials.new(load_certs) # load_certs typically loads a CA roots fileauthentication =Google::Auth.get_application_default() call_creds =GRPC::Core::CallCredentials.new(authentication.updater_proc) combined_creds = ssl_creds.compose(call_creds) stub =Helloworld::Greeter::Stub.new('greeter.googleapis.com', combined_creds)
var stub =new helloworld.Greeter('localhost:50051', grpc.credentials.createInsecure());
const root_cert = fs.readFileSync('path/to/root-cert'); const ssl_creds = grpc.credentials.createSsl(root_cert); const stub =new helloworld.Greeter('myservice.example.com', ssl_creds);
// Authenticating with Google var GoogleAuth = require('google-auth-library'); // from https://www.npmjs.com/package/google-auth-library ... var ssl_creds = grpc.credentials.createSsl(root_certs); (new GoogleAuth()).getApplicationDefault(function(err, auth) { var call_creds = grpc.credentials.createFromGoogleCredential(auth); var combined_creds = grpc.credentials.combineChannelCredentials(ssl_creds, call_creds); var stub =new helloworld.Greeter('greeter.googleapis.com', combined_credentials); });
var GoogleAuth = require('google-auth-library'); // from https://www.npmjs.com/package/google-auth-library ... var ssl_creds = grpc.Credentials.createSsl(root_certs); // load_certs typically loads a CA roots file var scope ='https://www.googleapis.com/auth/grpc-testing'; (new GoogleAuth()).getApplicationDefault(function(err, auth) { if (auth.createScopeRequired()) { auth = auth.createScoped(scope); } var call_creds = grpc.credentials.createFromGoogleCredential(auth); var combined_creds = grpc.credentials.combineChannelCredentials(ssl_creds, call_creds); var stub =new helloworld.Greeter('greeter.googleapis.com', combined_credentials); });
const rootCert = fs.readFileSync('path/to/root-cert'); const channelCreds = grpc.credentials.createSsl(rootCert); const metaCallback = (_params, callback) => { const meta =new grpc.Metadata(); meta.add('custom-auth-header', 'token'); callback(null, meta); } const callCreds = grpc.credentials.createFromMetadataGenerator(metaCallback); const combCreds = grpc.credentials.combineChannelCredentials(channelCreds, callCreds); const stub =new helloworld.Greeter('myservice.example.com', combCreds);
$client=new helloworld\GreeterClient('localhost:50051', [ 'credentials'=> Grpc\ChannelCredentials::createInsecure(), ]);
$client=new helloworld\GreeterClient('myservice.example.com', [ 'credentials'=> Grpc\ChannelCredentials::createSsl(file_get_contents('roots.pem')), ]);
functionupdateAuthMetadataCallback($context) { $auth_credentials= ApplicationDefaultCredentials::getCredentials(); return$auth_credentials->updateMetadata($metadata= [], $context->service_url); } $channel_credentials= Grpc\ChannelCredentials::createComposite( Grpc\ChannelCredentials::createSsl(file_get_contents('roots.pem')), Grpc\CallCredentials::createFromPlugin('updateAuthMetadataCallback') ); $opts= [ 'credentials'=>$channel_credentials]; $client=new helloworld\GreeterClient('greeter.googleapis.com', $opts);
// the environment variable "GOOGLE_APPLICATION_CREDENTIALS" needs to be set $scope="https://www.googleapis.com/auth/grpc-testing"; $auth= Google\Auth\ApplicationDefaultCredentials::getCredentials($scope); $opts= [ 'credentials'=> Grpc\Credentials::createSsl(file_get_contents('roots.pem')); 'update_metadata'=>$auth->getUpdateMetadataFunc(), ]; $client=new helloworld\GreeterClient('greeter.googleapis.com', $opts);
final channel =new ClientChannel('localhost', port:50051, options:const ChannelOptions( credentials:const ChannelCredentials.insecure())); final stub =new GreeterClient(channel);
// Load a custom roots file. final trustedRoot =new File('roots.pem').readAsBytesSync(); final channelCredentials =new ChannelCredentials.secure(certificates: trustedRoot); final channelOptions =new ChannelOptions(credentials: channelCredentials); final channel =new ClientChannel('myservice.example.com', options: channelOptions); final client =new GreeterClient(channel);
// Uses publicly trusted roots by default. final channel =new ClientChannel('greeter.googleapis.com'); final serviceAccountJson =new File('service-account.json').readAsStringSync(); final credentials =new JwtServiceAccountAuthenticator(serviceAccountJson); final client =new GreeterClient(channel, options: credentials.toCallOptions);
// Uses publicly trusted roots by default. final channel =new ClientChannel('greeter.googleapis.com'); final client =new GreeterClient(channel); ... final serviceAccountJson =new File('service-account.json').readAsStringSync(); final credentials =new JwtServiceAccountAuthenticator(serviceAccountJson); final response =await client.sayHello(request, options: credentials.toCallOptions);