Estructura inicial del proyecto

This commit is contained in:
2026-06-02 16:57:08 +00:00
commit 8b306b9afc
9864 changed files with 1435687 additions and 0 deletions

View File

@ -0,0 +1,128 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import {
ClientAuthErrorCodes,
createClientAuthError,
} from "../error/ClientAuthError.js";
import type { BaseAuthRequest } from "../request/BaseAuthRequest.js";
import type { ShrOptions, SignedHttpRequest } from "./SignedHttpRequest.js";
/**
* The PkceCodes type describes the structure
* of objects that contain PKCE code
* challenge and verifier pairs
*/
export type PkceCodes = {
verifier: string;
challenge: string;
};
export type SignedHttpRequestParameters = Pick<
BaseAuthRequest,
| "resourceRequestMethod"
| "resourceRequestUri"
| "shrClaims"
| "shrNonce"
| "shrOptions"
> & {
correlationId: string;
};
/**
* Interface for crypto functions used by library
*/
export interface ICrypto {
/**
* Creates a guid randomly.
*/
createNewGuid(): string;
/**
* base64 Encode string
* @param input
*/
base64Encode(input: string): string;
/**
* base64 decode string
* @param input
*/
base64Decode(input: string): string;
/**
* base64 URL safe encoded string
*/
base64UrlEncode(input: string): string;
/**
* Stringifies and base64Url encodes input public key
* @param inputKid
* @returns Base64Url encoded public key
*/
encodeKid(inputKid: string): string;
/**
* Generates an JWK RSA S256 Thumbprint
* @param request
*/
getPublicKeyThumbprint(
request: SignedHttpRequestParameters
): Promise<string>;
/**
* Removes cryptographic keypair from key store matching the keyId passed in
* @param kid
* @param correlationId
*/
removeTokenBindingKey(kid: string, correlationId: string): Promise<void>;
/**
* Removes all cryptographic keys from IndexedDB storage
* @param correlationId
*/
clearKeystore(correlationId: string): Promise<boolean>;
/**
* Returns a signed proof-of-possession token with a given acces token that contains a cnf claim with the required kid.
* @param accessToken
*/
signJwt(
payload: SignedHttpRequest,
kid: string,
shrOptions?: ShrOptions,
correlationId?: string
): Promise<string>;
/**
* Returns the SHA-256 hash of an input string
* @param plainText
*/
hashString(plainText: string): Promise<string>;
}
export const DEFAULT_CRYPTO_IMPLEMENTATION: ICrypto = {
createNewGuid: (): string => {
throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);
},
base64Decode: (): string => {
throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);
},
base64Encode: (): string => {
throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);
},
base64UrlEncode: (): string => {
throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);
},
encodeKid: (): string => {
throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);
},
async getPublicKeyThumbprint(): Promise<string> {
throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);
},
async removeTokenBindingKey(): Promise<void> {
throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);
},
async clearKeystore(): Promise<boolean> {
throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);
},
async signJwt(): Promise<string> {
throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);
},
async hashString(): Promise<string> {
throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);
},
};

View File

@ -0,0 +1,9 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
export interface IGuidGenerator {
generateGuid(): string;
isGuid(guid: string): boolean;
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import {
JoseHeaderErrorCodes,
createJoseHeaderError,
} from "../error/JoseHeaderError.js";
import { JsonWebTokenTypes } from "../utils/Constants.js";
export type JoseHeaderOptions = {
typ?: JsonWebTokenTypes;
alg?: string;
kid?: string;
};
/** @internal */
export class JoseHeader {
public typ?: JsonWebTokenTypes;
public alg?: string;
public kid?: string;
constructor(options: JoseHeaderOptions) {
this.typ = options.typ;
this.alg = options.alg;
this.kid = options.kid;
}
/**
* Builds SignedHttpRequest formatted JOSE Header from the
* JOSE Header options provided or previously set on the object and returns
* the stringified header object.
* Throws if keyId or algorithm aren't provided since they are required for Access Token Binding.
* @param shrHeaderOptions
* @returns
*/
static getShrHeaderString(shrHeaderOptions: JoseHeaderOptions): string {
// KeyID is required on the SHR header
if (!shrHeaderOptions.kid) {
throw createJoseHeaderError(JoseHeaderErrorCodes.missingKidError);
}
// Alg is required on the SHR header
if (!shrHeaderOptions.alg) {
throw createJoseHeaderError(JoseHeaderErrorCodes.missingAlgError);
}
const shrHeader = new JoseHeader({
// Access Token PoP headers must have type pop, but the type header can be overriden for special cases
typ: shrHeaderOptions.typ || JsonWebTokenTypes.Pop,
kid: shrHeaderOptions.kid,
alg: shrHeaderOptions.alg,
});
return JSON.stringify(shrHeader);
}
}

View File

@ -0,0 +1,150 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import { ICrypto, SignedHttpRequestParameters } from "./ICrypto.js";
import * as TimeUtils from "../utils/TimeUtils.js";
import { UrlString } from "../url/UrlString.js";
import { IPerformanceClient } from "../telemetry/performance/IPerformanceClient.js";
import * as PerformanceEvents from "../telemetry/performance/PerformanceEvents.js";
import { invokeAsync } from "../utils/FunctionWrappers.js";
import { Logger } from "../logger/Logger.js";
/**
* See eSTS docs for more info.
* - A kid element, with the value containing an RFC 7638-compliant JWK thumbprint that is base64 encoded.
* - xms_ksl element, representing the storage location of the key's secret component on the client device. One of two values:
* - sw: software storage
* - uhw: hardware storage
*/
type ReqCnf = {
kid: string;
xms_ksl: KeyLocation;
};
export type ReqCnfData = {
kid: string;
reqCnfString: string;
};
const KeyLocation = {
SW: "sw",
UHW: "uhw",
} as const;
export type KeyLocation = (typeof KeyLocation)[keyof typeof KeyLocation];
/** @internal */
export class PopTokenGenerator {
private cryptoUtils: ICrypto;
private performanceClient: IPerformanceClient;
constructor(cryptoUtils: ICrypto, performanceClient: IPerformanceClient) {
this.cryptoUtils = cryptoUtils;
this.performanceClient = performanceClient;
}
/**
* Generates the req_cnf validated at the RP in the POP protocol for SHR parameters
* and returns an object containing the keyid, the full req_cnf string and the req_cnf string hash
* @param request
* @returns
*/
async generateCnf(
request: SignedHttpRequestParameters,
logger: Logger
): Promise<ReqCnfData> {
const reqCnf = await invokeAsync(
this.generateKid.bind(this),
PerformanceEvents.PopTokenGenerateCnf,
logger,
this.performanceClient,
request.correlationId
)(request);
const reqCnfString: string = this.cryptoUtils.base64UrlEncode(
JSON.stringify(reqCnf)
);
return {
kid: reqCnf.kid,
reqCnfString,
};
}
/**
* Generates key_id for a SHR token request
* @param request
* @returns
*/
async generateKid(request: SignedHttpRequestParameters): Promise<ReqCnf> {
const kidThumbprint = await this.cryptoUtils.getPublicKeyThumbprint(
request
);
return {
kid: kidThumbprint,
xms_ksl: KeyLocation.SW,
};
}
/**
* Signs the POP access_token with the local generated key-pair
* @param accessToken
* @param request
* @returns
*/
async signPopToken(
accessToken: string,
keyId: string,
request: SignedHttpRequestParameters
): Promise<string> {
return this.signPayload(accessToken, keyId, request);
}
/**
* Utility function to generate the signed JWT for an access_token
* @param payload
* @param kid
* @param request
* @param claims
* @returns
*/
async signPayload(
payload: string,
keyId: string,
request: SignedHttpRequestParameters,
claims?: object
): Promise<string> {
// Deconstruct request to extract SHR parameters
const {
resourceRequestMethod,
resourceRequestUri,
shrClaims,
shrNonce,
shrOptions,
} = request;
const resourceUrlString = resourceRequestUri
? new UrlString(resourceRequestUri)
: undefined;
const resourceUrlComponents = resourceUrlString?.getUrlComponents();
return this.cryptoUtils.signJwt(
{
at: payload,
ts: TimeUtils.nowSeconds(),
m: resourceRequestMethod?.toUpperCase(),
u: resourceUrlComponents?.HostNameAndPort,
nonce: shrNonce || this.cryptoUtils.createNewGuid(),
p: resourceUrlComponents?.AbsolutePath,
q: resourceUrlComponents?.QueryString
? [[], resourceUrlComponents.QueryString]
: undefined,
client_claims: shrClaims || undefined,
...claims,
},
keyId,
shrOptions,
request.correlationId
);
}
}

View File

@ -0,0 +1,22 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import { JoseHeaderOptions } from "./JoseHeader.js";
export type SignedHttpRequest = {
at?: string;
cnf?: object;
m?: string;
u?: string;
p?: string;
q?: [Array<string>, string];
ts?: number;
nonce?: string;
client_claims?: string;
};
export type ShrOptions = {
header: JoseHeaderOptions;
};