@web5/agent
Version:
247 lines • 12.6 kB
TypeScript
import { RequireOnly } from '@web5/common';
import type { ConnectPermissionRequest } from './connect.js';
import { DidDocument, PortableDid, type BearerDid } from '@web5/dids';
import { DwnDataEncodedRecordsWriteMessage, DwnPermissionScope } from './types/dwn.js';
import type { Web5Agent } from './types/agent.js';
/**
* Sent to an OIDC server to authorize a client. Allows clients
* to securely send authorization request parameters directly to
* the server via POST. This avoids exposing sensitive data in URLs
* and ensures the server validates the request before user interaction.
*
* @see {@link https://www.rfc-editor.org/rfc/rfc9126.html | OAuth 2.0 Pushed Authorization Requests}
*/
export type PushedAuthRequest = {
/** The JWT which contains the {@link Web5ConnectAuthRequest} */
request: string;
};
/**
* Sent back by OIDC server in response to {@link PushedAuthRequest}
* The server generates a TTL and a unique request_uri. The request_uri can be shared
* with the Provider using a link or a QR code along with additional params
* to access the url and decrypt the payload.
*/
export type PushedAuthResponse = {
request_uri: string;
expires_in: number;
};
/**
* Used in decentralized apps. The SIOPv2 Auth Request is created by a client relying party (RP)
* often a web service or an app who wants to obtain information from a provider
* The contents of this are inserted into a JWT inside of the {@link PushedAuthRequest}.
* @see {@link https://github.com/TBD54566975/known-customer-credential | TBD OIDC Documentation for SIOPv2 }
*/
export type SIOPv2AuthRequest = {
/** The DID of the client (RP) */
client_id: string;
/** The scope of the access request (e.g., `openid profile`). */
scope: string;
/** The type of response desired (e.g. `id_token`) */
response_type: string;
/** the URL to which the Identity Provider will post the Authorization Response */
redirect_uri: string;
/** The URI to which the SIOPv2 Authorization Response will be sent (Tim's note: not used with encrypted request JWT)*/
response_uri?: string;
/**
* An opaque value used to maintain state between the request and the callback.
* Recommended for security to prevent CSRF attacks.
*/
state: string;
/**
* A string value used to associate a client session with an ID token to mitigate replay attacks.
* Recommended when requesting ID tokens.
*/
nonce: string;
/**
* The PKCE code challenge.
* Required if `code_challenge_method` is used. Enhances security for public clients (e.g., single-page apps,
* mobile apps) by requiring an additional verification step during token exchange.
*/
code_challenge?: string;
/** The method used for the PKCE challenge (typically `S256`). Must be present if `code_challenge` is included. */
code_challenge_method?: 'S256';
/**
* An ID token previously issued to the client, passed as a hint about the end-user’s current or past authenticated
* session with the client. Can streamline user experience if already logged in.
*/
id_token_hint?: string;
/** A hint to the authorization server about the login identifier the user might use. Useful for pre-filling login information. */
login_hint?: string;
/** Requested Authentication Context Class Reference values. Specifies the authentication context requirements. */
acr_values?: string;
/** When using a PAR for secure cross device flows we use a "form_post" rather than a "direct_post" */
response_mode: 'direct_post';
/** Used by PFI to request VCs as input to IDV process. If present, `response_type: "vp_token""` MUST also be present */
presentation_definition?: any;
/** A JSON object containing the Verifier metadata values (Tim's note: from TBD KCC Repo) */
client_metadata?: {
/** Array of strings, each a DID method supported for the subject of ID Token */
subject_syntax_types_supported: string[];
/** Human-readable string name of the client to be presented to the end-user during authorization */
client_name?: string;
/** URI of a web page providing information about the client */
client_uri?: string;
/** URI of an image logo for the client */
logo_uri?: string;
/** Array of strings representing ways to contact people responsible for this client, typically email addresses */
contacts?: string[];
/** URI that points to a terms of service document for the client */
tos_uri?: string;
/** URI that points to a privacy policy document */
policy_uri?: string;
};
};
/**
* An auth request that is compatible with both Web5 Connect and (hopefully, WIP) OIDC SIOPv2
* The contents of this are inserted into a JWT inside of the {@link PushedAuthRequest}.
*/
export type Web5ConnectAuthRequest = {
/** The user friendly name of the client/app to be displayed when prompting end-user with permission requests. */
displayName: string;
/** PermissionGrants that are to be sent to the provider */
permissionRequests: ConnectPermissionRequest[];
} & SIOPv2AuthRequest;
/** The fields for an OIDC SIOPv2 Auth Repsonse */
export type SIOPv2AuthResponse = {
/** Issuer MUST match the value of sub (Applicant's DID) */
iss: string;
/** Subject Identifier. A locally unique and never reassigned identifier
* within the Issuer for the End-User, which is intended to be consumed
* by the Client. */
sub: string;
/** Audience(s) that this ID Token is intended for. It MUST contain the
* OAuth 2.0 client_id of the Relying Party as an audience value. */
aud: string;
/** Time at which the JWT was issued. */
iat: number;
/** Expiration time on or after which the ID Token MUST NOT be accepted
* for processing. */
exp: number;
/** Time when the End-User authentication occurred. */
auth_time?: number;
/** b64url encoded nonce used to associate a Client session with an ID Token, and to
* mitigate replay attacks. */
nonce?: string;
/** Custom claims. */
[key: string]: any;
};
/** An auth response that is compatible with both Web5 Connect and (hopefully, WIP) OIDC SIOPv2 */
export type Web5ConnectAuthResponse = {
delegateGrants: DwnDataEncodedRecordsWriteMessage[];
delegatePortableDid: PortableDid;
} & SIOPv2AuthResponse;
/** Represents the different OIDC endpoint types.
* 1. `pushedAuthorizationRequest`: client sends {@link PushedAuthRequest} receives {@link PushedAuthResponse}
* 2. `authorize`: provider gets the {@link Web5ConnectAuthRequest} JWT that was stored by the PAR
* 3. `callback`: provider sends {@link Web5ConnectAuthResponse} to this endpoint
* 4. `token`: client gets {@link Web5ConnectAuthResponse} from this endpoint
*/
type OidcEndpoint = 'pushedAuthorizationRequest' | 'authorize' | 'callback' | 'token';
/**
* Gets the correct OIDC endpoint out of the {@link OidcEndpoint} options provided.
* Handles a trailing slash on baseURL
*
* @param {Object} options the options object
* @param {string} options.baseURL for example `http://foo.com/connect/
* @param {OidcEndpoint} options.endpoint the OIDC endpoint desired
* @param {string} options.authParam this is the unique id which must be provided when getting the `authorize` endpoint
* @param {string} options.tokenParam this is the random state as b64url which must be provided with the `token` endpoint
*/
declare function buildOidcUrl({ baseURL, endpoint, authParam, tokenParam, }: {
baseURL: string;
endpoint: OidcEndpoint;
authParam?: string;
tokenParam?: string;
}): string;
/**
* Generates a cryptographically random "code challenge" in
* accordance with the RFC 7636 PKCE specification.
*
* @see {@link https://datatracker.ietf.org/doc/html/rfc7636#section-4.2 | RFC 7636 }
*/
declare function generateCodeChallenge(): Promise<{
codeChallengeBytes: Uint8Array;
codeChallengeBase64Url: string;
}>;
/** Client creates the {@link Web5ConnectAuthRequest} */
declare function createAuthRequest(options: RequireOnly<Web5ConnectAuthRequest, 'client_id' | 'scope' | 'redirect_uri' | 'permissionRequests' | 'displayName'>): Promise<Web5ConnectAuthRequest>;
/** Encrypts the auth request with the key which will be passed through QR code */
declare function encryptAuthRequest({ jwt, encryptionKey, }: {
jwt: string;
encryptionKey: Uint8Array;
}): Promise<string>;
/** Create a response object compatible with Web5 Connect and OIDC SIOPv2 */
declare function createResponseObject(options: RequireOnly<Web5ConnectAuthResponse, 'iss' | 'sub' | 'aud' | 'delegateGrants' | 'delegatePortableDid'>): Promise<Web5ConnectAuthResponse>;
/** sign an object and transform it into a jwt using a did */
declare function signJwt({ did, data, }: {
did: BearerDid;
data: Record<string, unknown>;
}): Promise<string>;
/** Take the decrypted JWT and verify it was signed by its public DID. Return parsed object. */
declare function verifyJwt({ jwt }: {
jwt: string;
}): Promise<object>;
/** Take the encrypted JWE, decrypt using the code challenge and return a JWT string which will need to be verified */
declare function decryptAuthRequest({ jwe, encryption_key, }: {
jwe: string;
encryption_key: string;
}): string;
/**
* The client uses to decrypt the jwe obtained from the auth server which contains
* the {@link Web5ConnectAuthResponse} that was sent by the provider to the auth server.
*
* @async
* @param {BearerDid} clientDid - The did that was initially used by the client for ECDH at connect init.
* @param {string} jwe - The encrypted data as a jwe.
* @param {string} pin - The pin that was obtained from the user.
*/
declare function decryptAuthResponse(clientDid: BearerDid, jwe: string, pin: string): Promise<string>;
/** Derives a shared ECDH private key in order to encrypt the {@link Web5ConnectAuthResponse} */
declare function deriveSharedKey(privateKeyDid: BearerDid, publicKeyDid: DidDocument): Promise<Uint8Array>;
/**
* Encrypts the auth response jwt. Requires a randomPin is added to the AAD of the
* encryption algorithm in order to prevent man in the middle and eavesdropping attacks.
* The keyid of the delegate did is used to pass the public key to the client in order
* for the client to derive the shared ECDH private key.
*/
declare function encryptAuthResponse({ jwt, encryptionKey, delegateDidKeyId, randomPin, }: {
jwt: string;
encryptionKey: Uint8Array;
delegateDidKeyId: string;
randomPin: string;
}): string;
/**
* Creates the permission grants that assign to the selectedDid the level of
* permissions that the web app requested in the {@link Web5ConnectAuthRequest}
*/
declare function createPermissionGrants(selectedDid: string, delegateBearerDid: BearerDid, agent: Web5Agent, scopes: DwnPermissionScope[]): Promise<(import("@tbd54566975/dwn-sdk-js").RecordsWriteMessage & {
encodedData: string;
})[]>;
/**
* Creates a delegate did which the web app will use as its future indentity.
* Assigns to that DID the level of permissions that the web app requested in
* the {@link Web5ConnectAuthRequest}. Encrypts via ECDH key that the web app
* will have access to because the web app has the public key which it provided
* in the {@link Web5ConnectAuthRequest}. Then sends the ciphertext of this
* {@link Web5ConnectAuthResponse} to the callback endpoint. Which the
* web app will need to retrieve from the token endpoint and decrypt with the pin to access.
*/
declare function submitAuthResponse(selectedDid: string, authRequest: Web5ConnectAuthRequest, randomPin: string, agent: Web5Agent): Promise<void>;
export declare const Oidc: {
createAuthRequest: typeof createAuthRequest;
encryptAuthRequest: typeof encryptAuthRequest;
getAuthRequest: (request_uri: string, encryption_key: string) => Promise<Web5ConnectAuthRequest>;
decryptAuthRequest: typeof decryptAuthRequest;
createPermissionGrants: typeof createPermissionGrants;
createResponseObject: typeof createResponseObject;
encryptAuthResponse: typeof encryptAuthResponse;
decryptAuthResponse: typeof decryptAuthResponse;
deriveSharedKey: typeof deriveSharedKey;
signJwt: typeof signJwt;
verifyJwt: typeof verifyJwt;
buildOidcUrl: typeof buildOidcUrl;
generateCodeChallenge: typeof generateCodeChallenge;
submitAuthResponse: typeof submitAuthResponse;
};
export {};
//# sourceMappingURL=oidc.d.ts.map