@tdxvolt/volt-client-grpc 0.20.7 → 0.20.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.cjs CHANGED
@@ -15,6 +15,7 @@ var fs = require('fs');
15
15
  var path = require('path');
16
16
  var jwt = require('jsonwebtoken');
17
17
  var crypto = require('crypto');
18
+ var voltUtility = require('@tdxvolt/volt-utility');
18
19
 
19
20
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
20
21
 
@@ -135,12 +136,14 @@ function createClient(
135
136
  address,
136
137
  credentials,
137
138
  noSerialise,
138
- voltId,
139
- serviceId
139
+ voltId = "",
140
+ serviceId = ""
140
141
  ) {
141
142
  let grpcCredentials;
142
143
  if (credentials) {
143
- const relaying = !!credentials.config?.volt?.relay && !Array.isArray(credentials.config?.volt?.relay);
144
+ const relaying =
145
+ !!credentials.config?.volt?.relay &&
146
+ !Array.isArray(credentials.config?.volt?.relay);
144
147
  const ca = relaying
145
148
  ? credentials.config?.volt?.relay?.ca_pem
146
149
  : credentials.cache.ca;
@@ -1426,10 +1429,13 @@ message DIDRegistryUpdate {
1426
1429
  }
1427
1430
 
1428
1431
  message VerifiablePresentation {
1429
- // The credential JSON.
1432
+ // DEPRECATED - use 'credential'
1430
1433
  string credential_json = 1;
1431
1434
 
1432
- // A signature of the credential JSON. The signature should usually be that of the credential subject.
1435
+ // Array of credential JSON.
1436
+ repeated string credential = 3;
1437
+
1438
+ // A signature of the credential JSON. The signature should be that of the credential holder over the concatenation of the contents of the \`credential\` array.
1433
1439
  string signature = 2;
1434
1440
  }
1435
1441
 
@@ -1593,7 +1599,7 @@ message ParseCredentialResponse {
1593
1599
  tdx.volt_api.volt.v1.Status status = 1;
1594
1600
 
1595
1601
  // The parsed credential details.
1596
- VerifiableCredential verifiable_credential = 2;
1602
+ repeated VerifiableCredential verifiable_credential = 2;
1597
1603
  }
1598
1604
 
1599
1605
  message ResolveDIDRequest {
@@ -1723,6 +1729,7 @@ enum SyncState {
1723
1729
  SYNC_STATE_SYNCING = 1;
1724
1730
  SYNC_STATE_DONE = 2;
1725
1731
  SYNC_STATE_UPDATE = 3;
1732
+ SYNC_STATE_AWARENESS = 4;
1726
1733
  }
1727
1734
 
1728
1735
  message SyncDocumentStart {
@@ -1791,7 +1798,8 @@ message GetDocumentJSONResponse {
1791
1798
  // The current JSON snapshot of the document
1792
1799
  string json = 2;
1793
1800
  }
1794
- }`;
1801
+ }
1802
+ `;
1795
1803
  const terminal_api = `syntax = "proto3";
1796
1804
 
1797
1805
  package tdx.volt_api.volt.v1;
@@ -2507,6 +2515,9 @@ message SessionCredential {
2507
2515
 
2508
2516
  // More type-specific data stored with the credential.
2509
2517
  string extra_2 = 16;
2518
+
2519
+ // The verification status of the credential.
2520
+ string status = 17;
2510
2521
  }
2511
2522
 
2512
2523
  message Session {
@@ -2530,7 +2541,6 @@ message Session {
2530
2541
 
2531
2542
  SessionStatus status = 10;
2532
2543
  }
2533
-
2534
2544
  `;
2535
2545
  const volt_api = `syntax = "proto3";
2536
2546
 
@@ -2541,7 +2551,7 @@ import "tdx/volt_api/volt/v1/remote.proto";
2541
2551
  import "tdx/volt_api/volt/v1/ssi.proto";
2542
2552
  import "tdx/volt_api/volt/v1/volt.proto";
2543
2553
 
2544
- // The top-level volt management service.
2554
+ // The top-level volt management service.
2545
2555
  // With the exception of \`Authenticate\`, all RPCs on this service must submit either a valid client certificate signed by the volt CA, or a signed JWT.
2546
2556
  // A client certificate can be obtained from the \`Authenticate\` method.
2547
2557
  // All methods include a \`tdx.volt_api.volt.v1.Status\` in the response. If the status contains a non-OK error code the client should assume the remainder of the message is invalid, unless otherwise indicated in the response documentation.
@@ -2732,7 +2742,7 @@ message AuthenticateResponse {
2732
2742
  // This should be persisted by the client, and submitted with all subsequent API calls as part of the call metadata.
2733
2743
  string session_id = 2;
2734
2744
 
2735
- // The identity id assigned to this authentication.
2745
+ // The 'primary' session identity assigned to this authentication. This will be the DID in DID-based sessions, otherwise it will be the first email-based credential found, if any, otherwise it will be the public key fingerprint.
2736
2746
  string identity_did = 3;
2737
2747
 
2738
2748
  // A certificate issued by the volt CA, binding the request public key to the identity.
@@ -2788,6 +2798,9 @@ message CanAccessResourceResponse {
2788
2798
 
2789
2799
  // The policy decision for this access request.
2790
2800
  PolicyDecision decision = 6;
2801
+
2802
+ // The session that the access relates to.
2803
+ string session_id = 7;
2791
2804
  }
2792
2805
 
2793
2806
  message CheckCompatibilityRequest {
@@ -2901,9 +2914,19 @@ message ConnectResource {
2901
2914
  Resource resource = 2;
2902
2915
  }
2903
2916
 
2917
+ enum ConnectAuthRequestType {
2918
+ CONNECT_AUTH_REQUEST_TYPE_UNKNOWN = 0;
2919
+ CONNECT_AUTH_REQUEST_TYPE_NEW_SESSION = 1;
2920
+ CONNECT_AUTH_REQUEST_TYPE_UPDATE_SESSION = 2;
2921
+ CONNECT_AUTH_REQUEST_TYPE_DELETE_SESSION = 3;
2922
+ CONNECT_AUTH_REQUEST_TYPE_SIGN_REQUEST = 4;
2923
+ }
2924
+
2904
2925
  message ConnectAuthRequest {
2905
2926
  Session session = 1;
2906
2927
 
2928
+ ConnectAuthRequestType request_type = 2;
2929
+
2907
2930
  string context = 5;
2908
2931
 
2909
2932
  string challenge = 6;
@@ -3123,6 +3146,9 @@ message GetIdentityResponse {
3123
3146
  message GetOneTimeTokenRequest {
3124
3147
  // Optional token TTL, in seconds. Default is 10 seconds.
3125
3148
  int32 ttl = 1;
3149
+
3150
+ // Optional token context.
3151
+ string context = 2;
3126
3152
  }
3127
3153
 
3128
3154
  message GetOneTimeTokenResponse {
@@ -3185,6 +3211,9 @@ message GetResourceResponse {
3185
3211
  message GetResourcesRequest {
3186
3212
  repeated string id = 1;
3187
3213
 
3214
+ // Wildcards permitted.
3215
+ repeated string alias = 16;
3216
+
3188
3217
  // Wildcards permitted.
3189
3218
  repeated string name = 2;
3190
3219
 
@@ -3313,6 +3342,8 @@ message GetSessionsRequest {
3313
3342
  string identity_name = 3;
3314
3343
 
3315
3344
  SessionStatus status = 4;
3345
+
3346
+ string identity_email_id = 5;
3316
3347
  }
3317
3348
 
3318
3349
  message GetSessionsResponse {
@@ -4827,8 +4858,6 @@ class VoltConnection extends EventEmitter__default["default"] {
4827
4858
 
4828
4859
  const { publicKeyToPem: publicKeyToPem$1, removeCarriageReturn, signBase64 } = js.voltUtils;
4829
4860
 
4830
- const { filter, pick } = lodash__default["default"];
4831
-
4832
4861
  const log$2 = debug__default["default"]("volt-client-grpc:volt-client-internal");
4833
4862
 
4834
4863
  function issueAuthenticate(authenticateRequest, ttl) {
@@ -4842,13 +4871,18 @@ function issueAuthenticate(authenticateRequest, ttl) {
4842
4871
  return Promise.reject(new Error(authenticateResponse.status.message));
4843
4872
  } else {
4844
4873
  switch (authenticateResponse.decision) {
4845
- case "POLICY_DECISION_PERMIT": {
4874
+ case "POLICY_DECISION_PERMIT":
4875
+ case "POLICY_DECISION_PROMPT":
4876
+ case "POLICY_DECISION_PENDING": {
4846
4877
  //
4847
- // The request status is permit => cache the bind response info.
4878
+ // The request status is not deny => cache the bind response info.
4848
4879
  //
4880
+ log$2("decision is %s", authenticateResponse.decision);
4849
4881
 
4850
4882
  // This is the certificate assigned to us by the volt.
4851
- this._credential.cache.cert = authenticateResponse.cert;
4883
+ if (authenticateResponse.cert) {
4884
+ this._credential.cache.cert = authenticateResponse.cert;
4885
+ }
4852
4886
 
4853
4887
  // This is the signing CA used by the volt.
4854
4888
  this._credential.cache.ca = authenticateResponse.chain;
@@ -4862,12 +4896,20 @@ function issueAuthenticate(authenticateRequest, ttl) {
4862
4896
  authenticateResponse.identity_did;
4863
4897
  }
4864
4898
 
4899
+ // Maintain a unique list of verifiable credentials.
4900
+ const uniqueVCs = new Map();
4865
4901
  this._credential.cache.vc = this._credential.cache.vc || [];
4902
+ for (const existingVC of this._credential.cache.vc) {
4903
+ uniqueVCs.set(existingVC.id, existingVC);
4904
+ }
4905
+
4866
4906
  for (const credential of authenticateResponse.credential) {
4867
4907
  const vc = JSON.parse(credential);
4868
- this._credential.cache.vc.push(vc);
4908
+ uniqueVCs.set(vc.id, vc);
4869
4909
  }
4870
4910
 
4911
+ this._credential.cache.vc = Array.from(uniqueVCs.values());
4912
+
4871
4913
  this._credential.saveCache();
4872
4914
  break;
4873
4915
  }
@@ -4875,25 +4917,6 @@ function issueAuthenticate(authenticateRequest, ttl) {
4875
4917
  log$2(">>>>>>>>>>>>>>> access request is DENIED <<<<<<<<<<<<<<<<<<<");
4876
4918
  break;
4877
4919
  }
4878
- case "POLICY_DECISION_PROMPT":
4879
- case "POLICY_DECISION_PENDING": {
4880
- log$2("access pending approval - waiting...");
4881
-
4882
- // This is the signing CA used by the volt.
4883
- this._credential.cache.ca = authenticateResponse.chain;
4884
-
4885
- // The session id is assigned by the volt.
4886
- this._credential.cache.session_id = authenticateResponse.session_id;
4887
-
4888
- if (!this._credential.cache.identity_did) {
4889
- // Identity DID has been assigned by the volt.
4890
- this._credential.cache.identity_did =
4891
- authenticateResponse.identity_did;
4892
- }
4893
-
4894
- this._credential.saveCache();
4895
- break;
4896
- }
4897
4920
  default:
4898
4921
  log$2(
4899
4922
  "ignoring unknown bind descision %s",
@@ -4907,16 +4930,12 @@ function issueAuthenticate(authenticateRequest, ttl) {
4907
4930
  });
4908
4931
  }
4909
4932
 
4910
- function findDIDDocumentService(document, serviceType) {
4911
- if (!document.service) {
4912
- return [];
4913
- }
4914
-
4915
- const matches = filter(document.service, (svc) => svc.type === serviceType);
4916
- return matches;
4917
- }
4918
-
4919
- async function authenticateInternal(noDID = false, ownDID = false, exchangeToken = "") {
4933
+ async function authenticateInternal(
4934
+ noDID = false,
4935
+ ownDID = false,
4936
+ exchangeToken = "",
4937
+ waitForPermit = true
4938
+ ) {
4920
4939
  try {
4921
4940
  if (!this._credential.cache.ca) {
4922
4941
  this._credential.cache.ca = this._voltConfig.ca_pem;
@@ -4947,6 +4966,27 @@ async function authenticateInternal(noDID = false, ownDID = false, exchangeToken
4947
4966
  host: this._credential.cache.bindIp
4948
4967
  };
4949
4968
 
4969
+ if (this._credential.cache.vc?.length > 0) {
4970
+ const presentation = {
4971
+ credential: []
4972
+ };
4973
+
4974
+ let presentationData = "";
4975
+ for (let credential of this._credential.cache.vc) {
4976
+ const vc = JSON.stringify(credential, null, 2);
4977
+ log$2(vc);
4978
+ presentation.credential.push(vc);
4979
+ presentationData += vc;
4980
+ }
4981
+
4982
+ presentation.signature = signBase64(
4983
+ this._credential.cache.key,
4984
+ presentationData
4985
+ );
4986
+
4987
+ authenticateRequest.verifiable_presentation = [presentation];
4988
+ }
4989
+
4950
4990
  if (exchangeToken) {
4951
4991
  log$2("setting request exchange token");
4952
4992
  authenticateRequest.exchange_token = exchangeToken;
@@ -4958,9 +4998,7 @@ async function authenticateInternal(noDID = false, ownDID = false, exchangeToken
4958
4998
  log$2("setting request challenge code");
4959
4999
  authenticateRequest.challenge = this._credential.cache.challenge_code;
4960
5000
  } else {
4961
- log$2(
4962
- "no challenge code in request"
4963
- );
5001
+ log$2("no challenge code in request");
4964
5002
  }
4965
5003
 
4966
5004
  if (noDID) {
@@ -5038,8 +5076,8 @@ async function authenticateInternal(noDID = false, ownDID = false, exchangeToken
5038
5076
  );
5039
5077
  log$2("authenticate decision: %s", decision);
5040
5078
  } while (
5041
- decision === "POLICY_DECISION_PROMPT" ||
5042
- decision === "POLICY_DECISION_PENDING"
5079
+ decision === "POLICY_DECISION_PENDING" ||
5080
+ (waitForPermit && decision === "POLICY_DECISION_PROMPT")
5043
5081
  );
5044
5082
 
5045
5083
  return decision === "POLICY_DECISION_PERMIT";
@@ -5154,7 +5192,11 @@ function getVoltAPIClientInternal() {
5154
5192
  const serviceAddress = this.isRelayed
5155
5193
  ? this._voltConfig.relay.address
5156
5194
  : this._voltConfig.address;
5157
- log$2("creating cached VoltAPI service client on %s", serviceAddress);
5195
+ log$2(
5196
+ "creating cached VoltAPI service client on %s for %j",
5197
+ serviceAddress,
5198
+ this._voltConfig
5199
+ );
5158
5200
 
5159
5201
  const serviceDescriptors = getBuiltInServiceDescriptors();
5160
5202
 
@@ -5163,9 +5205,7 @@ function getVoltAPIClientInternal() {
5163
5205
  serviceDescriptors,
5164
5206
  serviceAddress,
5165
5207
  this._credential,
5166
- this.isRelayed,
5167
- this._voltConfig?.relay?.cloud ? this._voltConfig.id : "",
5168
- this._voltConfig?.relay?.cloud ? this._voltConfig.id : ""
5208
+ this.isRelayed
5169
5209
  );
5170
5210
  }
5171
5211
 
@@ -5250,211 +5290,6 @@ function streamingCallInternal(methodType, method, request, service) {
5250
5290
  return call;
5251
5291
  }
5252
5292
 
5253
- async function fetchVoltConfig(discovery_url) {
5254
- try {
5255
- const response = await fetch(discovery_url);
5256
-
5257
- if (!response.ok) {
5258
- log$2("fetchVoltConfig - error [%s]", response.status);
5259
- return null;
5260
- }
5261
-
5262
- const fullVoltConfig = await response.json();
5263
-
5264
- if (!fullVoltConfig || typeof fullVoltConfig !== "object") {
5265
- log$2("fetchVoltConfig - invalid config resolved from: %s", discovery_url);
5266
- return null;
5267
- }
5268
-
5269
- const voltConfig = pick(
5270
- fullVoltConfig,
5271
- "id",
5272
- "display_name",
5273
- "public_key",
5274
- "fingerprint",
5275
- "address",
5276
- "http_address",
5277
- "ca_pem",
5278
- "relay"
5279
- );
5280
-
5281
- log$2("fetchVoltConfig from %s", discovery_url);
5282
-
5283
- return voltConfig;
5284
- } catch (err) {
5285
- log$2("fetchVoltConfig - %s error [%s]", discovery_url, err.message);
5286
- return null;
5287
- }
5288
- }
5289
-
5290
- async function fetchVoltConfigFromDIDInternal(volt_did, registryUrl) {
5291
- try {
5292
- const didResolution = getDIDResolutionURL(volt_did, registryUrl);
5293
- if (!didResolution) {
5294
- throw new Error(`Invalid Volt DID: ${volt_did}`);
5295
- }
5296
-
5297
- const response = await fetch(didResolution);
5298
-
5299
- if (!response.ok) {
5300
- throw new Error(`HTTP error, status: ${response.status}`);
5301
- }
5302
-
5303
- const didDocument = await response.json();
5304
- const voltConfigServices = findDIDDocumentService(
5305
- didDocument,
5306
- constants.didServiceType.voltConfig
5307
- );
5308
- if (voltConfigServices.length !== 1) {
5309
- log$2(
5310
- "Unexpected number of Volt configuration endpoints found in DID document for %s, services found: %d",
5311
- volt_did,
5312
- voltConfigServices.length
5313
- );
5314
- }
5315
-
5316
- log$2("resolved DID from %s", didResolution);
5317
-
5318
- const serviceEndpoint = voltConfigServices[0].serviceEndpoint;
5319
- const voltConfig = await fetchVoltConfig.call(this, serviceEndpoint);
5320
- if (!voltConfig) {
5321
- throw new Error(`failed to resolve Volt config from ${serviceEndpoint}`);
5322
- }
5323
-
5324
- return voltConfig;
5325
- } catch (err) {
5326
- throw new Error(
5327
- `Failure fetching Volt config from DID document ${volt_did}: ${err.message}`
5328
- );
5329
- }
5330
- }
5331
-
5332
- async function fetchVoltConfigFromDID(volt_did, registryListIn) {
5333
- let registryList;
5334
- if (!registryListIn) {
5335
- // If no registry list is provided, use the default registry list.
5336
- registryList = constants.defaultRegistryList;
5337
- } else {
5338
- // If a registry list is provided, merge it with the default registry list.
5339
- registryList = Array.from(
5340
- new Set(registryListIn.concat(constants.defaultRegistryList))
5341
- );
5342
- }
5343
-
5344
- let voltConfig;
5345
- for (let registryUrl of registryList) {
5346
- try {
5347
- voltConfig = await fetchVoltConfigFromDIDInternal.call(
5348
- this,
5349
- volt_did,
5350
- registryUrl
5351
- );
5352
-
5353
- // If we've found a config, break out of the loop.
5354
- break;
5355
- } catch (err) {
5356
- log$2("unable to fetch Volt config from %s: %s", registryUrl, err.message);
5357
- }
5358
- }
5359
-
5360
- if (!voltConfig) {
5361
- log$2("failed to fetch Volt config for %s from any registry", volt_did);
5362
- }
5363
-
5364
- return voltConfig;
5365
- }
5366
-
5367
- async function resolveVoltConfig(cfg, didRegistryList) {
5368
- // Start by resolving the relay if one is specified.
5369
- let relay = cfg?.relay?.http_address || cfg?.relay;
5370
- if (relay) {
5371
- relay = await resolveVoltConfig.call(this, relay, didRegistryList);
5372
- }
5373
-
5374
- let voltDID = "";
5375
- let voltHttpAddress = "";
5376
-
5377
- if (typeof cfg === "string") {
5378
- // If the configuration is a string, determine if it is a DID or HTTP address.
5379
- if (cfg.indexOf("did:") === 0) {
5380
- voltDID = cfg;
5381
- } else {
5382
- voltHttpAddress = cfg;
5383
- }
5384
- cfg = {};
5385
- } else if (typeof cfg === "object") {
5386
- voltDID = cfg.id;
5387
- voltHttpAddress = cfg.http_address;
5388
- } else {
5389
- throw new Error("configuration is missing the 'volt' object");
5390
- }
5391
-
5392
- let resolvedConfig;
5393
-
5394
- if (relay) {
5395
- if (!voltDID) {
5396
- throw new Error("relay specified but no Volt DID provided");
5397
- }
5398
-
5399
- // Build the sub-domain URL for the Volt discovery service by inserting the volt DID into the relay URL.
5400
- const relayURL = relay.http_address;
5401
- const relayParts = relayURL.split("://");
5402
- const subdomain = voltDID.substring(constants.voltDIDPrefix.length);
5403
- voltHttpAddress = `${relayParts[0]}://${subdomain}.${relayParts[1]}`;
5404
- } else if (voltDID) {
5405
- resolvedConfig = await fetchVoltConfigFromDID.call(
5406
- this,
5407
- voltDID,
5408
- didRegistryList
5409
- );
5410
- }
5411
-
5412
- if (!resolvedConfig && voltHttpAddress) {
5413
- try {
5414
- resolvedConfig = await fetchVoltConfig.call(
5415
- this,
5416
- `${voltHttpAddress}/discover`
5417
- );
5418
-
5419
- // Update the http address in the resolved config to the one we used to
5420
- // fetch it, since we may have used the relay rather than local address.
5421
- resolvedConfig.http_address = voltHttpAddress;
5422
- } catch (err) {
5423
- log$2(
5424
- "failed to resolve Volt configuration %s [%s]",
5425
- voltHttpAddress,
5426
- err.message
5427
- );
5428
- }
5429
- }
5430
-
5431
- if (!resolvedConfig) {
5432
- if (cfg.address && cfg.ca_pem) {
5433
- log$2(
5434
- "unable to resolve %s / %s, using existing configuration",
5435
- voltDID,
5436
- voltHttpAddress
5437
- );
5438
- } else {
5439
- throw new Error(
5440
- `failed to resolve Volt ${voltDID} / ${voltHttpAddress} and no existing configuration`
5441
- );
5442
- }
5443
- } else {
5444
- log$2("resolved config from: %s", voltDID || voltHttpAddress);
5445
- log$2(JSON.stringify(resolvedConfig, null, 2));
5446
-
5447
- cfg = {
5448
- ...cfg,
5449
- ...resolvedConfig
5450
- };
5451
- }
5452
-
5453
- cfg.relay = relay;
5454
-
5455
- return cfg;
5456
- }
5457
-
5458
5293
  /* eslint-disable no-underscore-dangle */
5459
5294
 
5460
5295
  const {
@@ -5710,9 +5545,16 @@ class VoltClient extends EventEmitter__default["default"] {
5710
5545
  * @param {boolean} [options.noDID] - whether to create a key-based authentication session
5711
5546
  * instead of a DID-based authentication session.
5712
5547
  * @param {string} [options.exchangeToken] - optional token to exchange in return for an authenticated session.
5548
+ * @param {boolean} [options.waitForAuth] - whether to block and poll on 'prompt' authenticate decisions. Default is true.
5713
5549
  */
5714
5550
  async initialise(config, options = {}) {
5715
- const { ownDID, noDID, didRegistryList, exchangeToken, extraConfig } = options;
5551
+ log("initialise ", config, options);
5552
+
5553
+ const { ownDID, noDID, didRegistryList, exchangeToken, extraConfig } =
5554
+ options;
5555
+ const waitForAuth =
5556
+ options.waitForAuth === undefined ? true : !!options.waitForAuth;
5557
+
5716
5558
  try {
5717
5559
  if (!config) {
5718
5560
  throw new Error(
@@ -5759,14 +5601,15 @@ class VoltClient extends EventEmitter__default["default"] {
5759
5601
  throw new Error("client_name property required in config");
5760
5602
  }
5761
5603
 
5762
- this._config.volt = await resolveVoltConfig.call(
5763
- this,
5604
+ this._config.volt = await voltUtility.resolveVoltConfig(
5764
5605
  this._config.volt,
5765
5606
  didRegistryList
5766
5607
  );
5767
5608
 
5768
5609
  this._voltConfig = this._config.volt;
5769
5610
 
5611
+ log("config is ", this._voltConfig);
5612
+
5770
5613
  if (!this._voltConfig.id || typeof this._voltConfig.id !== "string") {
5771
5614
  throw new Error("'id' property is missing in Volt configuration");
5772
5615
  }
@@ -5798,7 +5641,13 @@ class VoltClient extends EventEmitter__default["default"] {
5798
5641
  } else {
5799
5642
  // No certificate present in the cache yet => we need to authenticate.
5800
5643
  try {
5801
- isBound = await authenticateInternal.call(this, noDID, ownDID, exchangeToken);
5644
+ isBound = await authenticateInternal.call(
5645
+ this,
5646
+ noDID,
5647
+ ownDID,
5648
+ exchangeToken,
5649
+ waitForAuth
5650
+ );
5802
5651
  } catch (bindErr) {
5803
5652
  if (bindErr.message === "invalid arguments") {
5804
5653
  // This is usually the result of a missing challenge signature or credential.
@@ -6235,6 +6084,21 @@ class VoltClient extends EventEmitter__default["default"] {
6235
6084
  return call.start(grpcClient, request);
6236
6085
  }
6237
6086
 
6087
+ /**
6088
+ * TerminalAPI
6089
+ */
6090
+ CommandStream(request, service) {
6091
+ const grpcClient = this.getVoltAPIClient();
6092
+
6093
+ const commandStreamCall = new GRPCCall(
6094
+ this,
6095
+ "CommandStream",
6096
+ "METHOD_TYPE_BIDI",
6097
+ service
6098
+ );
6099
+ return commandStreamCall.start(grpcClient, request);
6100
+ }
6101
+
6238
6102
  /**
6239
6103
  * WireAPI
6240
6104
  */
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.20.7",
6
+ "version": "0.20.10",
7
7
  "description": "tdx Volt library for nodejs clients",
8
8
  "type": "module",
9
9
  "exports": {
@@ -33,7 +33,8 @@
33
33
  "author": "toby.ealden@gmail.com",
34
34
  "license": "ISC",
35
35
  "dependencies": {
36
- "@tdxvolt/volt-client-web": "^0.20.7",
36
+ "@tdxvolt/volt-client-web": "^0.20.10",
37
+ "@tdxvolt/volt-utility": "^0.20.10",
37
38
  "debug": "^4.1.1",
38
39
  "ip": "^1.1.5",
39
40
  "jsonwebtoken": "^8.5.1",
@@ -42,4 +43,4 @@
42
43
  "protobufjs": "^7.4.0",
43
44
  "uuid": "^8.1.0"
44
45
  }
45
- }
46
+ }
package/src/grpc-utils.js CHANGED
@@ -15,12 +15,14 @@ export function createClient(
15
15
  address,
16
16
  credentials,
17
17
  noSerialise,
18
- voltId,
19
- serviceId
18
+ voltId = "",
19
+ serviceId = ""
20
20
  ) {
21
21
  let grpcCredentials;
22
22
  if (credentials) {
23
- const relaying = !!credentials.config?.volt?.relay && !Array.isArray(credentials.config?.volt?.relay);
23
+ const relaying =
24
+ !!credentials.config?.volt?.relay &&
25
+ !Array.isArray(credentials.config?.volt?.relay);
24
26
  const ca = relaying
25
27
  ? credentials.config?.volt?.relay?.ca_pem
26
28
  : credentials.cache.ca;
@@ -4,7 +4,6 @@ import debug from "debug";
4
4
  import ip from "ip";
5
5
  import lodash from "lodash";
6
6
  import { v4 as generateId } from "uuid";
7
- import { constants } from "./constants.js";
8
7
  import GRPCCall from "./grpc-call.js";
9
8
  import { createClient as createGrpcClient } from "./grpc-utils.js";
10
9
  import {
@@ -12,7 +11,6 @@ import {
12
11
  getServiceDescriptors
13
12
  } from "./proto-utils.js";
14
13
  import RpcInvocation from "./rpc-invocation.js";
15
- import * as voltUtils from "./utils.js";
16
14
  import VoltConnection from "./volt-connection.js";
17
15
 
18
16
  const { publicKeyToPem, removeCarriageReturn, signBase64 } = voltClientUtils;
@@ -32,13 +30,18 @@ function issueAuthenticate(authenticateRequest, ttl) {
32
30
  return Promise.reject(new Error(authenticateResponse.status.message));
33
31
  } else {
34
32
  switch (authenticateResponse.decision) {
35
- case "POLICY_DECISION_PERMIT": {
33
+ case "POLICY_DECISION_PERMIT":
34
+ case "POLICY_DECISION_PROMPT":
35
+ case "POLICY_DECISION_PENDING": {
36
36
  //
37
- // The request status is permit => cache the bind response info.
37
+ // The request status is not deny => cache the bind response info.
38
38
  //
39
+ log("decision is %s", authenticateResponse.decision);
39
40
 
40
41
  // This is the certificate assigned to us by the volt.
41
- this._credential.cache.cert = authenticateResponse.cert;
42
+ if (authenticateResponse.cert) {
43
+ this._credential.cache.cert = authenticateResponse.cert;
44
+ }
42
45
 
43
46
  // This is the signing CA used by the volt.
44
47
  this._credential.cache.ca = authenticateResponse.chain;
@@ -52,12 +55,20 @@ function issueAuthenticate(authenticateRequest, ttl) {
52
55
  authenticateResponse.identity_did;
53
56
  }
54
57
 
58
+ // Maintain a unique list of verifiable credentials.
59
+ const uniqueVCs = new Map();
55
60
  this._credential.cache.vc = this._credential.cache.vc || [];
61
+ for (const existingVC of this._credential.cache.vc) {
62
+ uniqueVCs.set(existingVC.id, existingVC);
63
+ }
64
+
56
65
  for (const credential of authenticateResponse.credential) {
57
66
  const vc = JSON.parse(credential);
58
- this._credential.cache.vc.push(vc);
67
+ uniqueVCs.set(vc.id, vc);
59
68
  }
60
69
 
70
+ this._credential.cache.vc = Array.from(uniqueVCs.values());
71
+
61
72
  this._credential.saveCache();
62
73
  break;
63
74
  }
@@ -65,25 +76,6 @@ function issueAuthenticate(authenticateRequest, ttl) {
65
76
  log(">>>>>>>>>>>>>>> access request is DENIED <<<<<<<<<<<<<<<<<<<");
66
77
  break;
67
78
  }
68
- case "POLICY_DECISION_PROMPT":
69
- case "POLICY_DECISION_PENDING": {
70
- log("access pending approval - waiting...");
71
-
72
- // This is the signing CA used by the volt.
73
- this._credential.cache.ca = authenticateResponse.chain;
74
-
75
- // The session id is assigned by the volt.
76
- this._credential.cache.session_id = authenticateResponse.session_id;
77
-
78
- if (!this._credential.cache.identity_did) {
79
- // Identity DID has been assigned by the volt.
80
- this._credential.cache.identity_did =
81
- authenticateResponse.identity_did;
82
- }
83
-
84
- this._credential.saveCache();
85
- break;
86
- }
87
79
  default:
88
80
  log(
89
81
  "ignoring unknown bind descision %s",
@@ -97,16 +89,12 @@ function issueAuthenticate(authenticateRequest, ttl) {
97
89
  });
98
90
  }
99
91
 
100
- function findDIDDocumentService(document, serviceType) {
101
- if (!document.service) {
102
- return [];
103
- }
104
-
105
- const matches = filter(document.service, (svc) => svc.type === serviceType);
106
- return matches;
107
- }
108
-
109
- export async function authenticateInternal(noDID = false, ownDID = false, exchangeToken = "") {
92
+ export async function authenticateInternal(
93
+ noDID = false,
94
+ ownDID = false,
95
+ exchangeToken = "",
96
+ waitForPermit = true
97
+ ) {
110
98
  try {
111
99
  if (!this._credential.cache.ca) {
112
100
  this._credential.cache.ca = this._voltConfig.ca_pem;
@@ -137,6 +125,27 @@ export async function authenticateInternal(noDID = false, ownDID = false, exchan
137
125
  host: this._credential.cache.bindIp
138
126
  };
139
127
 
128
+ if (this._credential.cache.vc?.length > 0) {
129
+ const presentation = {
130
+ credential: []
131
+ };
132
+
133
+ let presentationData = "";
134
+ for (let credential of this._credential.cache.vc) {
135
+ const vc = JSON.stringify(credential, null, 2);
136
+ log(vc);
137
+ presentation.credential.push(vc);
138
+ presentationData += vc;
139
+ }
140
+
141
+ presentation.signature = signBase64(
142
+ this._credential.cache.key,
143
+ presentationData
144
+ );
145
+
146
+ authenticateRequest.verifiable_presentation = [presentation];
147
+ }
148
+
140
149
  if (exchangeToken) {
141
150
  log("setting request exchange token");
142
151
  authenticateRequest.exchange_token = exchangeToken;
@@ -148,9 +157,7 @@ export async function authenticateInternal(noDID = false, ownDID = false, exchan
148
157
  log("setting request challenge code");
149
158
  authenticateRequest.challenge = this._credential.cache.challenge_code;
150
159
  } else {
151
- log(
152
- "no challenge code in request"
153
- );
160
+ log("no challenge code in request");
154
161
  }
155
162
 
156
163
  if (noDID) {
@@ -228,8 +235,8 @@ export async function authenticateInternal(noDID = false, ownDID = false, exchan
228
235
  );
229
236
  log("authenticate decision: %s", decision);
230
237
  } while (
231
- decision === "POLICY_DECISION_PROMPT" ||
232
- decision === "POLICY_DECISION_PENDING"
238
+ decision === "POLICY_DECISION_PENDING" ||
239
+ (waitForPermit && decision === "POLICY_DECISION_PROMPT")
233
240
  );
234
241
 
235
242
  return decision === "POLICY_DECISION_PERMIT";
@@ -344,7 +351,11 @@ export function getVoltAPIClientInternal() {
344
351
  const serviceAddress = this.isRelayed
345
352
  ? this._voltConfig.relay.address
346
353
  : this._voltConfig.address;
347
- log("creating cached VoltAPI service client on %s", serviceAddress);
354
+ log(
355
+ "creating cached VoltAPI service client on %s for %j",
356
+ serviceAddress,
357
+ this._voltConfig
358
+ );
348
359
 
349
360
  const serviceDescriptors = getBuiltInServiceDescriptors();
350
361
 
@@ -353,9 +364,7 @@ export function getVoltAPIClientInternal() {
353
364
  serviceDescriptors,
354
365
  serviceAddress,
355
366
  this._credential,
356
- this.isRelayed,
357
- this._voltConfig?.relay?.cloud ? this._voltConfig.id : "",
358
- this._voltConfig?.relay?.cloud ? this._voltConfig.id : ""
367
+ this.isRelayed
359
368
  );
360
369
  }
361
370
 
@@ -439,208 +448,3 @@ export function streamingCallInternal(methodType, method, request, service) {
439
448
 
440
449
  return call;
441
450
  }
442
-
443
- export async function fetchVoltConfig(discovery_url) {
444
- try {
445
- const response = await fetch(discovery_url);
446
-
447
- if (!response.ok) {
448
- log("fetchVoltConfig - error [%s]", response.status);
449
- return null;
450
- }
451
-
452
- const fullVoltConfig = await response.json();
453
-
454
- if (!fullVoltConfig || typeof fullVoltConfig !== "object") {
455
- log("fetchVoltConfig - invalid config resolved from: %s", discovery_url);
456
- return null;
457
- }
458
-
459
- const voltConfig = pick(
460
- fullVoltConfig,
461
- "id",
462
- "display_name",
463
- "public_key",
464
- "fingerprint",
465
- "address",
466
- "http_address",
467
- "ca_pem",
468
- "relay"
469
- );
470
-
471
- log("fetchVoltConfig from %s", discovery_url);
472
-
473
- return voltConfig;
474
- } catch (err) {
475
- log("fetchVoltConfig - %s error [%s]", discovery_url, err.message);
476
- return null;
477
- }
478
- }
479
-
480
- async function fetchVoltConfigFromDIDInternal(volt_did, registryUrl) {
481
- try {
482
- const didResolution = voltUtils.getDIDResolutionURL(volt_did, registryUrl);
483
- if (!didResolution) {
484
- throw new Error(`Invalid Volt DID: ${volt_did}`);
485
- }
486
-
487
- const response = await fetch(didResolution);
488
-
489
- if (!response.ok) {
490
- throw new Error(`HTTP error, status: ${response.status}`);
491
- }
492
-
493
- const didDocument = await response.json();
494
- const voltConfigServices = findDIDDocumentService(
495
- didDocument,
496
- constants.didServiceType.voltConfig
497
- );
498
- if (voltConfigServices.length !== 1) {
499
- log(
500
- "Unexpected number of Volt configuration endpoints found in DID document for %s, services found: %d",
501
- volt_did,
502
- voltConfigServices.length
503
- );
504
- }
505
-
506
- log("resolved DID from %s", didResolution);
507
-
508
- const serviceEndpoint = voltConfigServices[0].serviceEndpoint;
509
- const voltConfig = await fetchVoltConfig.call(this, serviceEndpoint);
510
- if (!voltConfig) {
511
- throw new Error(`failed to resolve Volt config from ${serviceEndpoint}`);
512
- }
513
-
514
- return voltConfig;
515
- } catch (err) {
516
- throw new Error(
517
- `Failure fetching Volt config from DID document ${volt_did}: ${err.message}`
518
- );
519
- }
520
- }
521
-
522
- export async function fetchVoltConfigFromDID(volt_did, registryListIn) {
523
- let registryList;
524
- if (!registryListIn) {
525
- // If no registry list is provided, use the default registry list.
526
- registryList = constants.defaultRegistryList;
527
- } else {
528
- // If a registry list is provided, merge it with the default registry list.
529
- registryList = Array.from(
530
- new Set(registryListIn.concat(constants.defaultRegistryList))
531
- );
532
- }
533
-
534
- let voltConfig;
535
- for (let registryUrl of registryList) {
536
- try {
537
- voltConfig = await fetchVoltConfigFromDIDInternal.call(
538
- this,
539
- volt_did,
540
- registryUrl
541
- );
542
-
543
- // If we've found a config, break out of the loop.
544
- break;
545
- } catch (err) {
546
- log("unable to fetch Volt config from %s: %s", registryUrl, err.message);
547
- }
548
- }
549
-
550
- if (!voltConfig) {
551
- log("failed to fetch Volt config for %s from any registry", volt_did);
552
- }
553
-
554
- return voltConfig;
555
- }
556
-
557
- export async function resolveVoltConfig(cfg, didRegistryList) {
558
- // Start by resolving the relay if one is specified.
559
- let relay = cfg?.relay?.http_address || cfg?.relay;
560
- if (relay) {
561
- relay = await resolveVoltConfig.call(this, relay, didRegistryList);
562
- }
563
-
564
- let voltDID = "";
565
- let voltHttpAddress = "";
566
-
567
- if (typeof cfg === "string") {
568
- // If the configuration is a string, determine if it is a DID or HTTP address.
569
- if (cfg.indexOf("did:") === 0) {
570
- voltDID = cfg;
571
- } else {
572
- voltHttpAddress = cfg;
573
- }
574
- cfg = {};
575
- } else if (typeof cfg === "object") {
576
- voltDID = cfg.id;
577
- voltHttpAddress = cfg.http_address;
578
- } else {
579
- throw new Error("configuration is missing the 'volt' object");
580
- }
581
-
582
- let resolvedConfig;
583
-
584
- if (relay) {
585
- if (!voltDID) {
586
- throw new Error("relay specified but no Volt DID provided");
587
- }
588
-
589
- // Build the sub-domain URL for the Volt discovery service by inserting the volt DID into the relay URL.
590
- const relayURL = relay.http_address;
591
- const relayParts = relayURL.split("://");
592
- const subdomain = voltDID.substring(constants.voltDIDPrefix.length);
593
- voltHttpAddress = `${relayParts[0]}://${subdomain}.${relayParts[1]}`;
594
- } else if (voltDID) {
595
- resolvedConfig = await fetchVoltConfigFromDID.call(
596
- this,
597
- voltDID,
598
- didRegistryList
599
- );
600
- }
601
-
602
- if (!resolvedConfig && voltHttpAddress) {
603
- try {
604
- resolvedConfig = await fetchVoltConfig.call(
605
- this,
606
- `${voltHttpAddress}/discover`
607
- );
608
-
609
- // Update the http address in the resolved config to the one we used to
610
- // fetch it, since we may have used the relay rather than local address.
611
- resolvedConfig.http_address = voltHttpAddress;
612
- } catch (err) {
613
- log(
614
- "failed to resolve Volt configuration %s [%s]",
615
- voltHttpAddress,
616
- err.message
617
- );
618
- }
619
- }
620
-
621
- if (!resolvedConfig) {
622
- if (cfg.address && cfg.ca_pem) {
623
- log(
624
- "unable to resolve %s / %s, using existing configuration",
625
- voltDID,
626
- voltHttpAddress
627
- );
628
- } else {
629
- throw new Error(
630
- `failed to resolve Volt ${voltDID} / ${voltHttpAddress} and no existing configuration`
631
- );
632
- }
633
- } else {
634
- log("resolved config from: %s", voltDID || voltHttpAddress);
635
- log(JSON.stringify(resolvedConfig, null, 2));
636
-
637
- cfg = {
638
- ...cfg,
639
- ...resolvedConfig
640
- };
641
- }
642
-
643
- cfg.relay = relay;
644
-
645
- return cfg;
646
- }
@@ -7,11 +7,11 @@ import {
7
7
  authenticateInternal,
8
8
  connectInternal,
9
9
  getVoltAPIClientInternal,
10
- resolveVoltConfig,
11
10
  streamingCallInternal,
12
11
  unaryCallInternal
13
12
  } from "./volt-client-internal.js";
14
13
  import { VoltCredential } from "./volt-credential.js";
14
+ import { resolveVoltConfig } from "@tdxvolt/volt-utility";
15
15
 
16
16
  const { readFile } = fs.promises;
17
17
  const log = debug("volt-client-grpc:volt-client");
@@ -85,9 +85,16 @@ export class VoltClient extends EventEmitter {
85
85
  * @param {boolean} [options.noDID] - whether to create a key-based authentication session
86
86
  * instead of a DID-based authentication session.
87
87
  * @param {string} [options.exchangeToken] - optional token to exchange in return for an authenticated session.
88
+ * @param {boolean} [options.waitForAuth] - whether to block and poll on 'prompt' authenticate decisions. Default is true.
88
89
  */
89
90
  async initialise(config, options = {}) {
90
- const { ownDID, noDID, didRegistryList, exchangeToken, extraConfig } = options;
91
+ log("initialise ", config, options);
92
+
93
+ const { ownDID, noDID, didRegistryList, exchangeToken, extraConfig } =
94
+ options;
95
+ const waitForAuth =
96
+ options.waitForAuth === undefined ? true : !!options.waitForAuth;
97
+
91
98
  try {
92
99
  if (!config) {
93
100
  throw new Error(
@@ -134,14 +141,15 @@ export class VoltClient extends EventEmitter {
134
141
  throw new Error("client_name property required in config");
135
142
  }
136
143
 
137
- this._config.volt = await resolveVoltConfig.call(
138
- this,
144
+ this._config.volt = await resolveVoltConfig(
139
145
  this._config.volt,
140
146
  didRegistryList
141
147
  );
142
148
 
143
149
  this._voltConfig = this._config.volt;
144
150
 
151
+ log("config is ", this._voltConfig);
152
+
145
153
  if (!this._voltConfig.id || typeof this._voltConfig.id !== "string") {
146
154
  throw new Error("'id' property is missing in Volt configuration");
147
155
  }
@@ -173,7 +181,13 @@ export class VoltClient extends EventEmitter {
173
181
  } else {
174
182
  // No certificate present in the cache yet => we need to authenticate.
175
183
  try {
176
- isBound = await authenticateInternal.call(this, noDID, ownDID, exchangeToken);
184
+ isBound = await authenticateInternal.call(
185
+ this,
186
+ noDID,
187
+ ownDID,
188
+ exchangeToken,
189
+ waitForAuth
190
+ );
177
191
  } catch (bindErr) {
178
192
  if (bindErr.message === "invalid arguments") {
179
193
  // This is usually the result of a missing challenge signature or credential.
@@ -612,6 +626,21 @@ export class VoltClient extends EventEmitter {
612
626
  return call.start(grpcClient, request);
613
627
  }
614
628
 
629
+ /**
630
+ * TerminalAPI
631
+ */
632
+ CommandStream(request, service) {
633
+ const grpcClient = this.getVoltAPIClient();
634
+
635
+ const commandStreamCall = new GRPCCall(
636
+ this,
637
+ "CommandStream",
638
+ "METHOD_TYPE_BIDI",
639
+ service
640
+ );
641
+ return commandStreamCall.start(grpcClient, request);
642
+ }
643
+
615
644
  /**
616
645
  * WireAPI
617
646
  */
@@ -881,10 +881,13 @@ message DIDRegistryUpdate {
881
881
  }
882
882
 
883
883
  message VerifiablePresentation {
884
- // The credential JSON.
884
+ // DEPRECATED - use 'credential'
885
885
  string credential_json = 1;
886
886
 
887
- // A signature of the credential JSON. The signature should usually be that of the credential subject.
887
+ // Array of credential JSON.
888
+ repeated string credential = 3;
889
+
890
+ // A signature of the credential JSON. The signature should be that of the credential holder over the concatenation of the contents of the \`credential\` array.
888
891
  string signature = 2;
889
892
  }
890
893
 
@@ -1048,7 +1051,7 @@ message ParseCredentialResponse {
1048
1051
  tdx.volt_api.volt.v1.Status status = 1;
1049
1052
 
1050
1053
  // The parsed credential details.
1051
- VerifiableCredential verifiable_credential = 2;
1054
+ repeated VerifiableCredential verifiable_credential = 2;
1052
1055
  }
1053
1056
 
1054
1057
  message ResolveDIDRequest {
@@ -1178,6 +1181,7 @@ enum SyncState {
1178
1181
  SYNC_STATE_SYNCING = 1;
1179
1182
  SYNC_STATE_DONE = 2;
1180
1183
  SYNC_STATE_UPDATE = 3;
1184
+ SYNC_STATE_AWARENESS = 4;
1181
1185
  }
1182
1186
 
1183
1187
  message SyncDocumentStart {
@@ -1246,7 +1250,8 @@ message GetDocumentJSONResponse {
1246
1250
  // The current JSON snapshot of the document
1247
1251
  string json = 2;
1248
1252
  }
1249
- }`;
1253
+ }
1254
+ `;
1250
1255
  export const terminal_api = `syntax = "proto3";
1251
1256
 
1252
1257
  package tdx.volt_api.volt.v1;
@@ -1962,6 +1967,9 @@ message SessionCredential {
1962
1967
 
1963
1968
  // More type-specific data stored with the credential.
1964
1969
  string extra_2 = 16;
1970
+
1971
+ // The verification status of the credential.
1972
+ string status = 17;
1965
1973
  }
1966
1974
 
1967
1975
  message Session {
@@ -1985,7 +1993,6 @@ message Session {
1985
1993
 
1986
1994
  SessionStatus status = 10;
1987
1995
  }
1988
-
1989
1996
  `;
1990
1997
  export const volt_api = `syntax = "proto3";
1991
1998
 
@@ -1996,7 +2003,7 @@ import "tdx/volt_api/volt/v1/remote.proto";
1996
2003
  import "tdx/volt_api/volt/v1/ssi.proto";
1997
2004
  import "tdx/volt_api/volt/v1/volt.proto";
1998
2005
 
1999
- // The top-level volt management service.
2006
+ // The top-level volt management service.
2000
2007
  // With the exception of \`Authenticate\`, all RPCs on this service must submit either a valid client certificate signed by the volt CA, or a signed JWT.
2001
2008
  // A client certificate can be obtained from the \`Authenticate\` method.
2002
2009
  // All methods include a \`tdx.volt_api.volt.v1.Status\` in the response. If the status contains a non-OK error code the client should assume the remainder of the message is invalid, unless otherwise indicated in the response documentation.
@@ -2187,7 +2194,7 @@ message AuthenticateResponse {
2187
2194
  // This should be persisted by the client, and submitted with all subsequent API calls as part of the call metadata.
2188
2195
  string session_id = 2;
2189
2196
 
2190
- // The identity id assigned to this authentication.
2197
+ // The 'primary' session identity assigned to this authentication. This will be the DID in DID-based sessions, otherwise it will be the first email-based credential found, if any, otherwise it will be the public key fingerprint.
2191
2198
  string identity_did = 3;
2192
2199
 
2193
2200
  // A certificate issued by the volt CA, binding the request public key to the identity.
@@ -2243,6 +2250,9 @@ message CanAccessResourceResponse {
2243
2250
 
2244
2251
  // The policy decision for this access request.
2245
2252
  PolicyDecision decision = 6;
2253
+
2254
+ // The session that the access relates to.
2255
+ string session_id = 7;
2246
2256
  }
2247
2257
 
2248
2258
  message CheckCompatibilityRequest {
@@ -2356,9 +2366,19 @@ message ConnectResource {
2356
2366
  Resource resource = 2;
2357
2367
  }
2358
2368
 
2369
+ enum ConnectAuthRequestType {
2370
+ CONNECT_AUTH_REQUEST_TYPE_UNKNOWN = 0;
2371
+ CONNECT_AUTH_REQUEST_TYPE_NEW_SESSION = 1;
2372
+ CONNECT_AUTH_REQUEST_TYPE_UPDATE_SESSION = 2;
2373
+ CONNECT_AUTH_REQUEST_TYPE_DELETE_SESSION = 3;
2374
+ CONNECT_AUTH_REQUEST_TYPE_SIGN_REQUEST = 4;
2375
+ }
2376
+
2359
2377
  message ConnectAuthRequest {
2360
2378
  Session session = 1;
2361
2379
 
2380
+ ConnectAuthRequestType request_type = 2;
2381
+
2362
2382
  string context = 5;
2363
2383
 
2364
2384
  string challenge = 6;
@@ -2578,6 +2598,9 @@ message GetIdentityResponse {
2578
2598
  message GetOneTimeTokenRequest {
2579
2599
  // Optional token TTL, in seconds. Default is 10 seconds.
2580
2600
  int32 ttl = 1;
2601
+
2602
+ // Optional token context.
2603
+ string context = 2;
2581
2604
  }
2582
2605
 
2583
2606
  message GetOneTimeTokenResponse {
@@ -2640,6 +2663,9 @@ message GetResourceResponse {
2640
2663
  message GetResourcesRequest {
2641
2664
  repeated string id = 1;
2642
2665
 
2666
+ // Wildcards permitted.
2667
+ repeated string alias = 16;
2668
+
2643
2669
  // Wildcards permitted.
2644
2670
  repeated string name = 2;
2645
2671
 
@@ -2768,6 +2794,8 @@ message GetSessionsRequest {
2768
2794
  string identity_name = 3;
2769
2795
 
2770
2796
  SessionStatus status = 4;
2797
+
2798
+ string identity_email_id = 5;
2771
2799
  }
2772
2800
 
2773
2801
  message GetSessionsResponse {