Como autenticar usuários

Com a autenticação, o Extensible Service Proxy (ESP) pode identificar os usuários que estão chamando seus métodos de serviço e, com base nisso, decidir se eles poderão usá-los ou não (autorização). Nesta página, descrevemos como a autenticação funciona com os serviços do Cloud Endpoints para gRPC, o que inclui como configurar o ESP em um serviço gRPC para ser compatível com as solicitações autenticadas e como chamar os métodos autenticados de um cliente gRPC.

O ESP é compatível com vários métodos de autenticação, incluindo o Firebase, o Auth0 e os tokens de código do Google, que podem ser definidos como parte da configuração da API gRPC. Em cada caso, a solicitação do cliente precisa conter um token da Web JSON (JWT, na sigla em inglês) para identificação. No ESP, o token é validado em nome da API, de modo que você não precisa adicionar nenhum código de autenticação especial.

Embora os requisitos de autenticação e chave de API permitam restringir quem pode chamar os métodos de serviço, eles não têm o mesmo nível de segurança e disponibilizam informações diferentes ao serviço chamado. Saiba mais sobre as diferenças entre as chaves de API e a autenticação e quando usar cada esquema em Por que e quando usar chaves de API.

Para ver um exemplo prático e completo do uso da autenticação, veja Como fazer autenticação usando uma conta de serviço, em que a autenticação é adicionada ao serviço Bookstore, nos nossos tutoriais.

Como configurar a autenticação do ESP

Configure a autenticação de um serviço do Endpoints para gRPC no respectivo arquivo YAML da configuração do serviço gRPC. Basta usar a seção authentication. Especifique o método de autenticação e os detalhes da origem da autenticação como providers, em que:

  • o valor id é usado para identificar o provedor de autenticação quando usado em rules: geralmente, o nome do método de autenticação é usado, mas isso não é uma regra;

  • o valor issuer é o emissor dos tokens obrigatórios e, portanto, especifica o método de autenticação;

  • o valor jwks_uri é o URI da chave pública do provedor, usado para validar tokens. Alguns métodos de autenticação não exigem que você especifique esse valor, como os tokens de código do Google, local do qual o ESP retira as informações automaticamente.

É possível definir vários provedores de segurança no mesmo arquivo, mas cada um precisa ter um issuer diferente. Para mais informações, consulte AuthProvider.

Especifique quais métodos da API precisam usar esses requisitos de autenticação com rules, como descrito em AuthenticationRule.

Os exemplos a seguir mostram como configurar o ESP em um serviço do gRPC em alguns métodos de autenticação compatíveis.

firebase

Para dar suporte à autenticação Firebase:

authentication:
  providers:
  - id: firebase
    jwks_uri: https://www.googleapis.com/service_accounts/v1/metadata/x509/securetoken@system.gserviceaccount.com
    # Replace YOUR-PROJECT-ID with your project ID
    issuer: https://securetoken.google.com/YOUR-PROJECT-ID
    # Optional. Replace YOUR-CLIENT-ID with your client ID
    audiences: "YOUR-CLIENT-ID"
  rules:
  - selector: "*"
    requirements:
      - provider_id: firebase

auth0

Para dar suporte à autenticação Auth0:

authentication:
  providers:
  - id: auth0_jwk
    # Replace YOUR-ACCOUNT-NAME with your service account's email address.
    issuer: https://YOUR-ACCOUNT-NAME.auth0.com/
    jwks_uri: "https://YOUR-ACCOUNT-NAME.auth0.com/.well-known/jwks.json"
    # Optional. Replace YOUR-CLIENT-ID with your client ID
    audiences: "YOUR-CLIENT-ID"
  rules:
  - selector: "*"
    requirements:
      - provider_id: auth0_jwk

Token de código do Google

Para dar suporte à autenticação usando um token de código do Google:

authentication:
  providers:
  - id: google_id_token
    issuer: https://accounts.google.com
    # Optional. Replace YOUR-CLIENT-ID with your client ID
    audiences: "YOUR-CLIENT-ID"
  rules:
  - selector: "*"
    requirements:
      - provider_id: google_id_token

personalizada

Para aceitar a autenticação personalizada:

authentication:
  providers:
  - id: custom_auth_id
    # The value below should be unique
    issuer: issuer of the token
    jwks_uri: url to the public key
    # Optional. Replace YOUR-CLIENT-ID with your client ID
    audiences: "YOUR-CLIENT-ID"
 rules:
 - selector: "*"
   requirements:
     - provider_id: custom_auth_id

O campo audiences não é obrigatório. O ESP é compatível com todos os JWTs que apresentam o nome do serviço de back-end no formato https://SERVICE_NAME na declaração aud. Para colocar outros IDs de cliente na lista de permissões de acesso ao serviço de back-end, especifique os IDs de cliente permitidos no campo audiences com valores separados por vírgulas. Em seguida, o ESP aceita, por meio da declaração aud, os JWTs com os IDs de cliente na lista de permissões.

Como chamar um método autenticado do gRPC

Se um método exigir autenticação, o token de autenticação precisará ser transmitido pelos clientes gRPC como metadados com a chamada do respectivo método, em que a chave é authorization e o valor é Bearer <JWT_TOKEN>. Veja um exemplo de como fazer isso na chamada do exemplo do Bookstore em Python, Node.js ou Java:

Python

def run(host, port, api_key, auth_token, timeout):
    """Makes a basic ListShelves call against a gRPC Bookstore server."""

    channel = grpc.insecure_channel('{}:{}'.format(host, port))

    stub = bookstore_pb2_grpc.BookstoreStub(channel)
    metadata = []
    if api_key:
        metadata.append(('x-api-key', api_key))
    if auth_token:
        metadata.append(('authorization', 'Bearer ' + auth_token))
    shelves = stub.ListShelves(empty_pb2.Empty(), timeout, metadata=metadata)
    print('ListShelves: {}'.format(shelves))

Java

private static final class Interceptor implements ClientInterceptor {
  private final String apiKey;
  private final String authToken;

  private static Logger LOGGER = Logger.getLogger("InfoLogging");

  private static Metadata.Key<String> API_KEY_HEADER =
      Metadata.Key.of("x-api-key", Metadata.ASCII_STRING_MARSHALLER);
  private static Metadata.Key<String> AUTHORIZATION_HEADER =
      Metadata.Key.of("authorization", Metadata.ASCII_STRING_MARSHALLER);

  public Interceptor(String apiKey, String authToken) {
    this.apiKey = apiKey;
    this.authToken = authToken;
  }

  @Override
  public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
      MethodDescriptor<ReqT,RespT> method, CallOptions callOptions, Channel next) {
    LOGGER.info("Intercepted " + method.getFullMethodName());
    ClientCall<ReqT, RespT> call = next.newCall(method, callOptions);

    call = new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(call) {
      @Override
      public void start(Listener<RespT> responseListener, Metadata headers) {
        if (apiKey != null && !apiKey.isEmpty()) {
          LOGGER.info("Attaching API Key: " + apiKey);
          headers.put(API_KEY_HEADER, apiKey);
        }
        if (authToken != null && !authToken.isEmpty()) {
          System.out.println("Attaching auth token");
          headers.put(AUTHORIZATION_HEADER, "Bearer " + authToken);
        }
        super.start(responseListener, headers);
      }
    };
    return call;
  }
}

Node.js

function makeGrpcRequest(JWT_AUTH_TOKEN, API_KEY, HOST, GREETEE) {
  // Uncomment these lines to set their values
  // const JWT_AUTH_TOKEN = 'YOUR_JWT_AUTH_TOKEN';
  // const API_KEY = 'YOUR_API_KEY';
  // const HOST = 'localhost:50051'; // The IP address of your endpoints host
  // const GREETEE = 'world';

  // Import required libraries
  const grpc = require('grpc');
  const path = require('path');

  // Load protobuf spec for an example API
  const PROTO_PATH = path.join(__dirname, '/protos/helloworld.proto');
  const protoObj = grpc.load(PROTO_PATH).helloworld;

  // Create a client for the protobuf spec
  const client = new protoObj.Greeter(HOST, grpc.credentials.createInsecure());

  // Build gRPC request
  const metadata = new grpc.Metadata();
  if (API_KEY) {
    metadata.add('x-api-key', API_KEY);
  } else if (JWT_AUTH_TOKEN) {
    metadata.add('authorization', `Bearer ${JWT_AUTH_TOKEN}`);
  }

  // Execute gRPC request
  client.sayHello({name: GREETEE}, metadata, (err, response) => {
    if (err) {
      console.error(err);
    }

    if (response) {
      console.log(response.message);
    }
  });
}

A maneira como um JWT válido para envio é recebido pelo cliente depende do método de autenticação.

Como receber os resultados da autenticação na API

O resultado da autenticação é transmitido para o serviço gRPC como metadados gRPC x-endpoint-api-userinfo. Saiba como isso funciona para APIs OpenAPI em Como autenticar usuários (OpenAPI).

A seguir

Esta página foi útil? Conte sua opinião sobre:

Enviar comentários sobre…

Cloud Endpoints com gRPC
Precisa de ajuda? Acesse nossa página de suporte.