// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package google.cloud.iamconnectorcredentials.v1alpha;

import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/longrunning/operations.proto";
import "google/protobuf/timestamp.proto";

option go_package = "cloud.google.com/go/iamconnectorcredentials/apiv1alpha/iamconnectorcredentialspb;iamconnectorcredentialspb";
option java_multiple_files = true;
option java_outer_classname = "ConnectorCredentialsProto";
option java_package = "com.google.cloud.iamconnectorcredentials.v1alpha";
option (google.api.resource_definition) = {
  type: "iamconnectors.googleapis.com/Connector"
  pattern: "projects/{project}/locations/{location}/connectors/{connector}"
};

// Service for managing Connector Credentials.
service IAMConnectorCredentialsService {
  option (google.api.default_host) = "iamconnectorcredentials.googleapis.com";
  option (google.api.oauth_scopes) =
      "https://www.googleapis.com/auth/cloud-platform";

  // Generates a credential request operation.
  // Initiates the retrieval of authorization credentials for a connector.
  // If `operation.done` is `true`, the `operation.response` field contains a
  // `RetrieveCredentialsResponse` containing the token. Otherwise, the
  // `operation.metadata` field contains a `RetrieveCredentialsMetadata`.
  //
  // Depending on the type contained in `RetrieveCredentialsMetadata`
  // callers will need to take different actions to obtain the credential.
  // View the comments on each type for more information.
  rpc RetrieveCredentials(RetrieveCredentialsRequest)
      returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v1alpha/{connector=projects/*/locations/*/connectors/*}/credentials:retrieve"
      body: "*"
    };
    option (google.api.method_signature) = "connector,user_id";
    option (google.api.method_signature) =
        "connector,user_id,scopes,continue_uri,force_refresh";
    option (google.longrunning.operation_info) = {
      response_type: "RetrieveCredentialsResponse"
      metadata_type: "RetrieveCredentialsMetadata"
    };
  }

  // Finalizes the credentials after a successful consent flow.
  rpc FinalizeCredentials(FinalizeCredentialsRequest)
      returns (FinalizeCredentialsResponse) {
    option (google.api.http) = {
      post: "/v1alpha/{connector=projects/*/locations/*/connectors/*}/credentials:finalize"
      body: "*"
    };
  }
}

// Request message for RetrieveCredentials.
message RetrieveCredentialsRequest {
  // Required. The parent resource name of the Connector.
  // Format: `projects/{project}/locations/{location}/connectors/{connector}`
  string connector = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "iamconnectors.googleapis.com/Connector"
    }
  ];

  // Required. The identity of the end user.
  string user_id = 2 [(google.api.field_behavior) = REQUIRED];

  // Optional. The OAuth scopes required for this access.
  repeated string scopes = 3 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The URI to redirect the user to after consent is completed.
  string continue_uri = 4 [(google.api.field_behavior) = OPTIONAL];

  // Optional. If true, forces fetching a fresh access token. Use only if the
  // previously supplied token was expired or invalid. If the token cannot be
  // refreshed without a login, the user is prompted for consent.
  bool force_refresh = 5 [(google.api.field_behavior) = OPTIONAL];
}

// Response message for RetrieveCredentials.
// Contains the access tokens and related artifacts.
message RetrieveCredentialsResponse {
  // The retrieved access token or credential for the end user.
  //
  // On MCPTool call, for an invalid token OAuth spec says this should
  // return 401 or 403, but MCPServers may implement this differently. If you
  // get any flavor of `PERMISSION_DENIED`, retry your original request to
  // RetrieveCredentials with
  // [force_refresh][google.cloud.iamconnectorcredentials.v1alpha.RetrieveCredentialsRequest.force_refresh]
  // set to `true`, which will fetch a new token or initiate a new consent flow.
  string token = 1;

  // The HTTP header name where the token should be placed.
  string header = 2;

  // The expiration time of the token.
  //
  // This does not guarantee that the token will be valid until this time, since
  // the token could be revoked earlier.
  // There could also be clock skew between the auth provider and the client so
  // it may expire slightly earlier.
  // If not set, the token might be permanent or it may be that the service does
  // not (or cannot) know when it will expire.
  google.protobuf.Timestamp expire_time = 3;

  // The scopes actually associated with the retrieved token.
  //
  // End users may have rejected some requested scopes, or the third-party
  // authorization servers can return a different set of scopes than what was
  // asked for. Callers should verify that all required scopes for their
  // intended use are included in this list.
  repeated string scopes = 4;
}

// Metadata for the RetrieveCredentials operation.
message RetrieveCredentialsMetadata {
  // Indicates that the user must visit the provided URI to consent to
  // delegate permission to the agent to act on their behalf. The caller can
  // either poll the provided operation, or await the user ID validation
  // callback
  message UriConsentRequired {
    // Output only. The URL where the user should be redirected to grant
    // consent. This will always be present.
    string authorization_uri = 1 [(google.api.field_behavior) = OUTPUT_ONLY];

    // Output only. A one-time, randomly generated value that validates the
    // entire consent flow is handled by a single user, avoiding CSRF attacks.
    // It must be submitted with the FinalizeCredentials request to complete the
    // OAuth exchange. This will always be present. Implemented per
    // https://www.rfc-editor.org/rfc/rfc6819#section-5.3.5
    string consent_nonce = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
  }

  // Indicates that the consent flow is pending external action.
  // No action is required by the caller. Simply retry the RetrieveCredentials
  // request.
  message ConsentPending {}

  // Indicates the user has rejected the permission delegation or cancelled the
  // request.
  message ConsentRejected {}

  // Indicates what requirements, if any, must be fulfilled to acquire a token.
  // See the comments on the specific message for the client behavior.
  //
  // Note: All polling or retries should follow an exponential backoff
  // (seconds): `0.5`, `1`, `2`, `4`, `8`, etc...
  oneof status {
    // Message indicating consent is pending.
    ConsentPending consent_pending = 6;

    // Message indicating uri based consent is required.
    UriConsentRequired uri_consent_required = 4;

    // Message indicating consent was rejected.
    ConsentRejected consent_rejected = 5;
  }

  // Output only. The time when the operation was created.
  google.protobuf.Timestamp create_time = 1
      [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Request message for FinalizeCredentials.
message FinalizeCredentialsRequest {
  // Required. The resource name of the Connector.
  // Format: `projects/{project}/locations/{location}/connectors/{connector}`
  string connector = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "iamconnectors.googleapis.com/Connector"
    }
  ];

  // Required. The identity of the end user.
  string user_id = 2 [(google.api.field_behavior) = REQUIRED];

  // Required. The encrypted state passed back from the consent flow.
  bytes user_id_validation_state = 3 [(google.api.field_behavior) = REQUIRED];

  // Required. The same consent_nonce value that was provided during redirect in
  // the UriConsentRequired metadata.
  string consent_nonce = 4 [(google.api.field_behavior) = REQUIRED];
}

// Response message for FinalizeCredentials. Intentionally empty
message FinalizeCredentialsResponse {}
