def machine_authentication(request):
  """Implementation of the machine authentication.

  See components.auth.handler.AuthenticatingHandler.get_auth_methods for details
  of the expected interface.

  Args:
    request: webapp2.Request with the incoming request.

  Returns:
    (auth.Identity, None) with machine ID ("bot:<fqdn>") on success or
    (None, None) if there's no machine token header (which means this
    authentication method is not applicable).

  Raises:
    BadTokenError (which is api.AuthenticationError) if machine token header is
    present, but the token is invalid. We also log the error details, but return
    only generic error message to the user.
  """
  token = request.headers.get(MACHINE_TOKEN_HEADER)
  if not token:
    return None, None

  # Deserialize both envelope and the body.
  try:
    token = b64_decode(token)
  except TypeError as exc:
    log_error(request, None, exc, 'Failed to decode base64')
    raise BadTokenError()

  try:
    envelope = machine_token_pb2.MachineTokenEnvelope()
    envelope.MergeFromString(token)
    body = machine_token_pb2.MachineTokenBody()
    body.MergeFromString(envelope.token_body)
  except message.DecodeError as exc:
    log_error(request, None, exc, 'Failed to deserialize the token')
    raise BadTokenError()

  # Construct an identity of a token server that signed the token to check that
  # it belongs to "auth-token-servers" group.
  try:
    signer_service_account = model.Identity.from_bytes('user:' + body.issued_by)
  except ValueError as exc:
    log_error(request, body, exc, 'Bad issued_by field - %s', body.issued_by)
    raise BadTokenError()

  # Reject tokens from unknown token servers right away.
  if not api.is_group_member(TOKEN_SERVERS_GROUP, signer_service_account):
    log_error(request, body, None, 'Unknown token issuer - %s', body.issued_by)
    raise BadTokenError()

  # Check the expiration time before doing any heavier checks.
  now = utils.time_time()
  if now < body.issued_at - ALLOWED_CLOCK_DRIFT_SEC:
    log_error(request, body, None, 'The token is not yet valid')
    raise BadTokenError()
  if now > body.issued_at + body.lifetime + ALLOWED_CLOCK_DRIFT_SEC:
    log_error(request, body, None, 'The token has expired')
    raise BadTokenError()

  # Check the token was actually signed by the server.
  try:
    certs = signature.get_service_account_certificates(body.issued_by)
    is_valid_sig = certs.check_signature(
        blob=envelope.token_body,
        key_name=envelope.key_id,
        signature=envelope.rsa_sha256)
    if not is_valid_sig:
      log_error(request, body, None, 'Bad signature')
      raise BadTokenError()
  except signature.CertificateError as exc:
    if exc.transient:
      raise TransientError(str(exc))
    log_error(
        request, body, exc, 'Unexpected error when checking the signature')
    raise BadTokenError()

  # The token is valid. Construct the bot identity.
  try:
    ident = model.Identity.from_bytes('bot:' + body.machine_fqdn)
  except ValueError as exc:
    log_error(request, body, exc, 'Bad machine_fqdn - %s', body.machine_fqdn)
    raise BadTokenError()

  # Unfortunately 'bot:*' identity namespace is shared between token-based
  # identities and old IP-whitelist based identity. They shouldn't intersect,
  # but better to enforce this.
  if ident == model.IP_WHITELISTED_BOT_ID:
    log_error(request, body, None, 'Bot ID %s is forbidden', ident.to_bytes())
    raise BadTokenError()

  return ident, None