Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions lib/src/access.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,9 @@ export type RewrapRequest = {
/**
* Get a rewrapped access key to the document, if possible
* @param url Key access server rewrap endpoint
* @param requestBody a signed request with an encrypted document key
* @param authProvider Authorization middleware
* @param signedRequestToken Signed request token containing the encrypted document key.
* @param auth Connect interceptors or a legacy auth provider.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous tags named requestBody and authProvider, which are not parameters, and included a nonexistent clientVersion tag. TypeDoc could not associate them with this signature.

* @param fulfillableObligationFQNs client-configured list of obligation value FQNs that can be fulfilled in this PEP
* @param clientVersion
*/
export async function fetchWrappedKey(
url: string,
Expand Down Expand Up @@ -209,7 +208,7 @@ export async function fetchECKasPubKey(kasEndpoint: string): Promise<KasPublicKe
* This function will first try to fetch the base public key,
* then it will try to fetch the public key using the RPC method,
* and finally it will try to fetch the public key using the legacy method.
* If all attempts fail, it will return the error from RPC Public Key fetch.
* If all attempts fail, throws the legacy public-key fetch error.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fallback helper throws the second, legacy-fetch error when both attempts fail. The previous comment incorrectly said the RPC error was returned.

* @param kasEndpoint The KAS endpoint URL.
* @param algorithm Optional algorithm to fetch the public key for.
* @returns The public key information.
Expand Down
12 changes: 3 additions & 9 deletions lib/src/auth/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ import * as defaultCryptoService from '../../tdf3/src/crypto/index.js';
* This just expects a clientId and clientSecret to be provided in the clientConfig, and will use that
* to grant tokens via the OIDC clientCredentials flow.
*
* The client's public key must be set in all OIDC token requests in order to recieve a token with valid
* Virtru claims. The public key may be passed to this provider's constructor, or supplied post-construction by calling
* {@link updateClientPublicKey} which will force an explicit token refresh
* Bind the client public key after construction with `updateClientPublicKey()`.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This factory does not accept or forward a public key. The previous comment described an unsupported constructor input.

*
*/
export const clientSecretAuthProvider = async (
Expand Down Expand Up @@ -59,9 +57,7 @@ export const clientSecretAuthProvider = async (
* The client can supply this provider with a JWT issued by that trusted 3rd-party IdP, and that JWT will be exchanged
* for a tokenset with TDF claims.
*
* The client's public key must be set in all OIDC token requests in order to recieve a token with valid
* Virtru claims. The public key may be passed to this provider's constructor, or supplied post-construction by calling
* {@link updateClientPublicKey}, which will force an explicit token refresh.
* Bind the client public key after construction with `updateClientPublicKey()`.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This factory does not accept or forward a public key. The previous comment described an unsupported constructor input.

*/
export const externalAuthProvider = async (
clientConfig: ExternalJwtCredentials,
Expand Down Expand Up @@ -89,9 +85,7 @@ export const externalAuthProvider = async (
* IdP using the OIDC flow fo their choice, and can provide a Refresh Token which will be exchanged (along with the client pubkey)
* for a new tokenset containing valid TDF claims.
*
* The client's public key must be set in all OIDC token requests in order to recieve a token with valid
* Virtru claims. The public key may be passed to this provider's constructor, or supplied post-construction by calling
* {@link updateClientPublicKey} which will force an explicit token refresh
* Bind the client public key after construction with `updateClientPublicKey()`.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This factory does not accept or forward a public key. The previous comment described an unsupported constructor input.

*/
export const refreshAuthProvider = async (
clientConfig: RefreshTokenCredentials,
Expand Down
16 changes: 9 additions & 7 deletions lib/src/opentdf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export type CreateOptions = {
/** The KAS to use for creation, if none is specified by the attribute service. */
defaultKASEndpoint?: string;

/** Private (or shared) keys for signing assertions and bindings. */
/** Currently unused; supplying signer keys has no effect. */

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

createTDF() and createZTDF() never read or forward signers. The previous comment implied that this option affected signing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed as a dead public field: it is declared but never read or forwarded. Assertion signing uses assertionConfigs[].signingKey; DPoP uses dpopKeys; vendored JOSE helpers do not consume it. Tracked in #1004.

signers?: Keys;

/** Source of plaintext data. */
Expand Down Expand Up @@ -152,7 +152,7 @@ export type ReadOptions = {
/** Optionally disable assertion verification. */
noVerify?: boolean;

/** If set, prevents more than this number of concurrent requests to the KAS. */
/** Currently ignored; KAS request concurrency is fixed at 1. */

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reader ignores this option and passes concurrencyLimit: 1. The previous comment described behavior the option does not control.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is ignored only by the OpenTDF wrapper. Direct TDF3Client.decrypt() still honors concurrencyLimit; ZTDFReader.decrypt() hardcodes 1 instead of forwarding this.opts.concurrencyLimit. Tracked as a forwarding bug in #1005.

concurrencyLimit?: number;

/**
Expand Down Expand Up @@ -232,7 +232,7 @@ export type TDFReader = {
*/
decrypt: () => Promise<DecoratedStream>;
/**
* Mark this reader as closed and release any resources, such as open files.
* Marks the internal reader state as closed.
*/
close: () => Promise<void>;

Expand All @@ -256,8 +256,8 @@ export type TDFReader = {
* The main OpenTDF class that provides methods for creating and reading TDF files.
* It can be used to create new TDF files and read existing ones.
* This class is the entry point for using the OpenTDF SDK.
* It requires an authentication provider to be passed in the constructor.
* It also requires a platform URL to be set, which is used to fetch key access servers and policies.
* Configure authentication with interceptors or the deprecated `authProvider`.
* Reads require a platform URL unless a KAS allowlist is supplied or allowlist checks are disabled.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The constructor accepts interceptors instead of an auth provider, and reads can use explicit KAS settings instead of platformUrl. The previous requirements were unconditional.

* @example
* ```
* import { authTokenInterceptor, OpenTDF } from '@opentdf/sdk';
Expand All @@ -272,7 +272,9 @@ export type TDFReader = {
* autoconfigure: false,
* });
*
* const clearText = await client.read({ type: 'stream', location: cipherText });
* const clearText = await client.read({
* source: { type: 'stream', location: cipherText },

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

read() requires ReadOptions.source. The previous example passed a Source directly and did not type-check.

* });
* ```
*/
export class OpenTDF {
Expand Down Expand Up @@ -411,7 +413,7 @@ export class OpenTDF {
return reader.decrypt();
}

/** Closes the OpenTDF instance and releases any resources. */
/** No-op retained for API compatibility. */

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method body is a no-op. The previous comment incorrectly claimed that it released resources.

close() {
// No-op for now, but kept for API compatibility
}
Expand Down
31 changes: 20 additions & 11 deletions lib/tdf3/src/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,15 @@ const makeChunkable = async (source: DecryptSource) => {
};

export interface ClientConfig {
/** Cryptographic implementation used by the client. */
cryptoService?: CryptoService;
/// oauth client id; used to generate oauth authProvider
/** OIDC client ID used by the legacy authentication flow. */
clientId?: string;
/** Enables DPoP for requests. */
dpopEnabled?: boolean;
/** Signing keys used for DPoP and signed request bodies. Generated when omitted. */
dpopKeys?: Promise<KeyPair>;
/** Default Key Access Server URL. */
kasEndpoint: string;
/**
* Service to use to look up ABAC. Used during autoconfigure. Defaults to
Expand All @@ -158,9 +162,12 @@ export interface ClientConfig {
keyRewrapEndpoint?: string;
// DEPRECATED Ignored
keyUpsertEndpoint?: string;
/** Refresh token used by the legacy OIDC authentication flow. */
refreshToken?: string;
kasPublicKey?: string;
/** Authentication service URL used by the legacy OIDC flow. */
oidcOrigin?: string;
/** External JWT used by the legacy token-exchange flow. */
externalJwt?: string;
/** @deprecated since 0.14.0. Use `interceptors` instead. */
authProvider?: AuthProvider;
Expand Down Expand Up @@ -336,7 +343,7 @@ export class Client {

/**
* List of allowed KASes to connect to for rewrap requests.
* Defaults to `[this.kasEndpoint]`.
* If omitted, decrypt requires `platformUrl` and loads the platform allowlist.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This property remains undefined unless allowedKases is configured. The previous comment incorrectly claimed a default of kasEndpoint.

*/
readonly allowedKases?: OriginAllowList;

Expand Down Expand Up @@ -379,13 +386,15 @@ export class Client {

/**
* An abstraction for protecting and accessing data using TDF3 services.
* @param {Object} [config.keypair] - keypair generated for signing. Optional, will be generated by sdk if not passed
* @param {String} [config.clientId]
* @param {String} [config.kasEndpoint] - Key Access Server url
* @param {String} [config.refreshToken] - After logging in to browser OIDC interface user
* receives fresh token that needed by SDK for auth needs
* @param {String} [config.externalJwt] - JWT from external authority (eg Google)
* @param {String} [config.oidcOrigin] - Endpoint of authentication service
* @param config TDF3 client configuration.
* @param config.kasEndpoint Default Key Access Server URL.
* @param config.dpopKeys Signing keys used for DPoP and signed request bodies. Generated when omitted.
* @param config.interceptors Connect RPC authentication interceptors.
* @param config.authProvider Deprecated authentication provider.
* @param config.clientId OIDC client ID used by the legacy authentication flow.
* @param config.refreshToken Refresh token used by the legacy OIDC authentication flow.
* @param config.externalJwt External JWT used by the legacy token-exchange flow.
* @param config.oidcOrigin Authentication service URL used by the legacy OIDC flow.
*/
constructor(config: ClientConfig) {
const clientConfig = { ...defaultClientConfig, ...config };
Expand Down Expand Up @@ -517,7 +526,7 @@ export class Client {
* @param [keyMiddleware] - function that handle keys
* @param [streamMiddleware] - function that handle stream
* @param [eo] - (deprecated) entity object
* @return a {@link https://nodejs.org/api/stream.html#stream_class_stream_readable|Readable} a new stream containing the TDF ciphertext
* @returns A decorated stream whose Web ReadableStream contains the TDF ciphertext.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return value wraps a Web ReadableStream; it is not a Node.js stream.Readable as previously documented.

*/
async encrypt(opts: EncryptParams): Promise<DecoratedReadableStream> {
if (opts.offline === false) {
Expand Down Expand Up @@ -791,7 +800,7 @@ export class Client {
* @param params.eo Optional entity object (legacy AuthZ)
* @param params.assertionVerificationKeys Optional verification keys for assertions.
* @param params.fulfillableObligationFQNs Optional fulfillable obligation value FQNs (overrides those on the Client)
* @return a {@link https://nodejs.org/api/stream.html#stream_class_stream_readable|Readable} stream containing the decrypted plaintext.
* @returns A decorated stream whose Web ReadableStream contains the decrypted plaintext.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return value wraps a Web ReadableStream; it is not a Node.js stream.Readable as previously documented.

* @see DecryptParamsBuilder
*/
async decrypt({
Expand Down
Loading