syntax = "proto3";

package nominal.public_app.authentication.v1;

import "google/api/annotations.proto";
import "nominal/protos/gen/v1/error.proto";

option java_multiple_files = true;
option java_package = "io.nominal.publicapp.authentication.v1";

enum PublicAppAuthenticationError {
  PUBLIC_APP_AUTHENTICATION_ERROR_UNSPECIFIED = 0;
  PUBLIC_APP_AUTHENTICATION_ERROR_NOT_SUPPORTED = 1 [(nominal.gen.v1.error) = {
    code: "NOT_FOUND"
    message: "authentication for public apps is not supported on this stack"
  }];
  PUBLIC_APP_AUTHENTICATION_ERROR_UNAUTHENTICATED = 2 [(nominal.gen.v1.error) = {
    code: "UNAUTHENTICATED"
    message: "client could not be authenticated"
  }];
  PUBLIC_APP_AUTHENTICATION_ERROR_EXPIRED = 3 [(nominal.gen.v1.error) = {
    code: "PERMISSION_DENIED"
    message: "attempted to authenticate with an expired client"
  }];
  PUBLIC_APP_AUTHENTICATION_ERROR_UNKNOWN_CLIENT = 4 [(nominal.gen.v1.error) = {
    code: "INVALID_ARGUMENT"
    message: "tried to authenticate with an unknown client id"
  }];
  PUBLIC_APP_AUTHENTICATION_ERROR_UNKNOWN_REDIRECT_URI = 5 [(nominal.gen.v1.error) = {
    code: "INVALID_ARGUMENT"
    message: "tried to authenticate with an unknown redirect URI"
  }];
  PUBLIC_APP_AUTHENTICATION_ERROR_INVALID_GRANT = 6 [(nominal.gen.v1.error) = {
    code: "INVALID_ARGUMENT"
    message: "could not grant an access token"
  }];
  PUBLIC_APP_AUTHENTICATION_ERROR_INVALID_CLIENT_CREDENTIALS = 7 [(nominal.gen.v1.error) = {
    code: "INVALID_ARGUMENT"
    message: "invalid client credentials used for authentication"
  }];
}

message HealthCheckRequest {}

message HealthCheckResponse {
  // If true, that means that the public app authentication signal used by the client is set to expire.
  // If received, users of public clients should be advised to update their client.
  bool will_expire = 1;
}

message GetOidcInitRequest {}

message GetOidcInitResponse {
  // The `client_id` field as described in RFC 8252: https://datatracker.ietf.org/doc/html/rfc7636.
  // Note that this is already included in the `loginUrl` field of this response.
  string client_id = 1;
  // A URL that public clients may use to prompt the user to authenticate in their browser, using the flow
  // described in RFC 8252: https://datatracker.ietf.org/doc/html/rfc8252.
  //
  // This URL must be extended with the following query parameters:
  //   * `redirect_uri`: one of the URLs included in the `redirectUris` field of this response.
  //   * `code_challenge` and `code_challenge_method`: described in RFC 8252
  //     https://datatracker.ietf.org/doc/html/rfc7636.
  string login_url = 2;
  // List of absolute URLs (usually on the localhost) that public applications may use to perform an OIDC
  // authentication flow.
  repeated string redirect_uris = 3;
}

message ExchangeAuthorizationCodeRequest {
  string client_id = 1;
  string code = 2;
  string redirect_uri = 3;
  string code_verifier = 4;
}

message ExchangeAuthorizationCodeResponse {
  string id_token = 1;
  optional int32 expires_in = 2;
  optional string scope = 3;
  optional string access_token = 4;
}

message GetNominalInstanceInfoRequest {}

message GetNominalInstanceInfoResponse {
  string instance_name = 1;
}

// Authentication intended for public applications developed by Nominal.
service PublicAppAuthenticationService {
  // Allows public applications to check compatibility with the target service.
  rpc HealthCheck(HealthCheckRequest) returns (HealthCheckResponse) {
    option (google.api.http) = {get: "/authentication/public/v1/health-check"};
  }
  // Allows public applications to obtain credentials used to initiate a user authentication flow using OIDC.
  rpc GetOidcInit(GetOidcInitRequest) returns (GetOidcInitResponse) {
    option (google.api.http) = {
      post: "/authentication/public/v1/oidc-init"
      body: "*"
    };
  }
  // Performs the authorization code exchange from OIDC on behalf of the client.
  rpc ExchangeAuthorizationCode(ExchangeAuthorizationCodeRequest) returns (ExchangeAuthorizationCodeResponse) {
    option (google.api.http) = {
      post: "/authentication/public/v1/oidc-exchange-authorization-code"
      body: "*"
    };
  }
  // Returns the name of the current instance of Nominal Core.
  rpc GetNominalInstanceInfo(GetNominalInstanceInfoRequest) returns (GetNominalInstanceInfoResponse) {
    option (google.api.http) = {get: "/authentication/public/v1/nominal-instance-info"};
  }
}
