/*
 * Copyright 2023 Signal Messenger, LLC
 * SPDX-License-Identifier: AGPL-3.0-only
 */

syntax = "proto3";

option java_multiple_files = true;

package org.signal.chat.credentials;

/**
 * Provides methods for obtaining and verifying credentials for "external" services
 * (i.e. services that are not a part of the chat server deployment).
 * All methods of this service require authentication.
 */
service ExternalServiceCredentials {

  /**
   * Generates and returns an external service credentials for the caller.
   *
   * `UNAUTHENTICATED` status is returned if the call is made on unauthenticated channel.
   *
   * `INVALID_ARGUMENT` status is returned if service is not configured for the service type
   * found in the request OR if `externalService` is not specified in the request.
   *
   * `RESOURCE_EXHAUSTED` status is returned if a rate limit for
   * generating credentials has been exceeded, in which case a
   * `retry-after` header containing an ISO 8601 duration string will be present
   * in the response trailers.
   */
  rpc GetExternalServiceCredentials(GetExternalServiceCredentialsRequest)
      returns (GetExternalServiceCredentialsResponse) {}
}

service ExternalServiceCredentialsAnonymous {
  /**
   * Given a list of secure value recovery (SVR) service credentials and a phone number,
   * checks, which of the provided credentials were generated by the user with the given phone number
   * and have not yet expired.
   *
   * `UNAUTHENTICATED` status is returned if the call is made on unauthenticated channel.
   *
   * `INVALID_ARGUMENT` status is returned if request contains more than 10 passwords to be checked.
   */
  rpc CheckSvrCredentials(CheckSvrCredentialsRequest)
      returns (CheckSvrCredentialsResponse) {}
}

enum ExternalServiceType {
  EXTERNAL_SERVICE_TYPE_UNSPECIFIED = 0;
  EXTERNAL_SERVICE_TYPE_ART = 1;
  EXTERNAL_SERVICE_TYPE_DIRECTORY = 2;
  EXTERNAL_SERVICE_TYPE_PAYMENTS = 3;
  EXTERNAL_SERVICE_TYPE_STORAGE = 4;
  EXTERNAL_SERVICE_TYPE_SVR = 5;
}

message GetExternalServiceCredentialsRequest {
  /**
   * A service to request credentials for.
   */
  ExternalServiceType externalService = 1;
}

message GetExternalServiceCredentialsResponse {
  /**
   * A username that can be presented to authenticate with the external service.
   */
  string username = 1;

  /**
   * A password that can be presented to authenticate with the external service.
   */
  string password = 2;
}

enum AuthCheckResult {
  AUTH_CHECK_RESULT_UNSPECIFIED = 0;
  /**
   * The credentials could be used to make a call to SVR service by the user
   * associated with the `CheckSvrCredentialsRequest.number` phone number.
   */
  AUTH_CHECK_RESULT_MATCH = 1;
  /**
   * The credentials were generated by a different user.
   */
  AUTH_CHECK_RESULT_NO_MATCH = 2;
  /**
   * This status indicates that the corresponding credentials token should no longer be used.
   * This may be because it has expired or invalid, but it can also mean that there is a more
   * recent token in the request which should be used instead.
   */
  AUTH_CHECK_RESULT_INVALID = 3;
}

message CheckSvrCredentialsRequest {
  /**
   * A phone number in the E164 format to check the passwords against.
   * Only passwords generated for the user associated with the given number will be marked as `AUTH_CHECK_RESULT_MATCH`.
   */
  string number = 1;

  /**
   * A list of credentials from previously made calls to `ExternalServiceCredentials.GetExternalServiceCredentials()`
   * for `EXTERNAL_SERVICE_TYPE_SVR`. This list may contain credentials generated by different users.
   */
  repeated string passwords = 2;
}

/**
 * For each of the credentials tokens in the `CheckSvrCredentialsRequest` contains the result of the check.
 */
message CheckSvrCredentialsResponse {

  map<string, AuthCheckResult> matches = 1;
}
