Skip to content

Commit efe1dea

Browse files
author
Prithvi Kanherkar
committed
Revert "Returns token as Proof-of-possession token"
This reverts commit c5608c8.
1 parent c5608c8 commit efe1dea

31 files changed

+94
-410
lines changed

lib/msal-browser/src/cache/DatabaseStorage.ts

-84
This file was deleted.

lib/msal-browser/src/crypto/BrowserCrypto.ts

+2-71
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export class BrowserCrypto {
4949
modulusLength: keygenConfigModulusLength,
5050
publicExponent: keygenConfigPublicExponent
5151
};
52+
console.log(this._keygenAlgorithmOptions);
5253
}
5354

5455
/**
@@ -95,33 +96,6 @@ export class BrowserCrypto {
9596
return this.hasIECrypto() ? this.msCryptoExportKey(key, format) : window.crypto.subtle.exportKey(format, key);
9697
}
9798

98-
/**
99-
* Imports key as given KeyFormat, can set extractable and usages.
100-
* @param key
101-
* @param format
102-
* @param extractable
103-
* @param usages
104-
*/
105-
async importKey(key: JsonWebKey, format: KeyFormat, extractable: boolean, usages: Array<KeyUsage>): Promise<CryptoKey> {
106-
const keyString = BrowserCrypto.getJwkString(key);
107-
const keyBuffer = BrowserStringUtils.stringToArrayBuffer(keyString);
108-
109-
return this.hasIECrypto() ?
110-
this.msCryptoImportKey(keyBuffer, format, extractable, usages)
111-
: window.crypto.subtle.importKey(format, key, this._keygenAlgorithmOptions, extractable, usages);
112-
}
113-
114-
/**
115-
* Signs given data with given key
116-
* @param key
117-
* @param data
118-
*/
119-
async sign(key: CryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> {
120-
return this.hasIECrypto() ?
121-
this.msCryptoSign(key, data)
122-
: window.crypto.subtle.sign(this._keygenAlgorithmOptions, key, data);
123-
}
124-
12599
/**
126100
* Check whether IE crypto or other browser cryptography is available.
127101
*/
@@ -169,11 +143,6 @@ export class BrowserCrypto {
169143
});
170144
}
171145

172-
/**
173-
* IE Helper function for generating a keypair
174-
* @param extractable
175-
* @param usages
176-
*/
177146
private async msCryptoGenerateKey(extractable: boolean, usages: Array<KeyUsage>): Promise<CryptoKeyPair> {
178147
return new Promise((resolve: any, reject: any) => {
179148
const msGenerateKey = window["msCrypto"].subtle.generateKey(this._keygenAlgorithmOptions, extractable, usages);
@@ -188,7 +157,7 @@ export class BrowserCrypto {
188157
}
189158

190159
/**
191-
* IE Helper function for exportKey
160+
* IE Helper function for exporting keys
192161
* @param key
193162
* @param format
194163
*/
@@ -218,44 +187,6 @@ export class BrowserCrypto {
218187
});
219188
}
220189

221-
/**
222-
* IE Helper function for importKey
223-
* @param key
224-
* @param format
225-
* @param extractable
226-
* @param usages
227-
*/
228-
private async msCryptoImportKey(keyBuffer: ArrayBuffer, format: KeyFormat, extractable: boolean, usages: Array<KeyUsage>): Promise<CryptoKey> {
229-
return new Promise((resolve: any, reject: any) => {
230-
const msImportKey = window["msCrypto"].subtle.importKey(format, keyBuffer, this._keygenAlgorithmOptions, extractable, usages);
231-
msImportKey.addEventListener("complete", (e: { target: { result: CryptoKey | PromiseLike<CryptoKey>; }; }) => {
232-
resolve(e.target.result);
233-
});
234-
235-
msImportKey.addEventListener("error", (error: any) => {
236-
reject(error);
237-
});
238-
});
239-
}
240-
241-
/**
242-
* IE Helper function for sign JWT
243-
* @param key
244-
* @param data
245-
*/
246-
private async msCryptoSign(key: CryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> {
247-
return new Promise((resolve: any, reject: any) => {
248-
const msSign = window["msCrypto"].subtle.sign(this._keygenAlgorithmOptions, key, data);
249-
msSign.addEventListener("complete", (e: { target: { result: ArrayBuffer | PromiseLike<ArrayBuffer>; }; }) => {
250-
resolve(e.target.result);
251-
});
252-
253-
msSign.addEventListener("error", (error: any) => {
254-
reject(error);
255-
});
256-
});
257-
}
258-
259190
/**
260191
* Returns stringified jwk.
261192
* @param jwk

lib/msal-browser/src/crypto/CryptoOps.ts

+11-65
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,14 @@
22
* Copyright (c) Microsoft Corporation. All rights reserved.
33
* Licensed under the MIT License.
44
*/
5-
import { ICrypto, PkceCodes, SignedHttpRequest } from "@azure/msal-common";
5+
import { ICrypto, PkceCodes } from "@azure/msal-common";
66
import { GuidGenerator } from "./GuidGenerator";
77
import { Base64Encode } from "../encode/Base64Encode";
88
import { Base64Decode } from "../encode/Base64Decode";
99
import { PkceGenerator } from "./PkceGenerator";
1010
import { BrowserCrypto, KeyFormat } from "./BrowserCrypto";
11-
import { DatabaseStorage } from "../cache/DatabaseStorage";
1211
import { BrowserStringUtils } from "../utils/BrowserStringUtils";
1312

14-
type CachedKeyPair = {
15-
publicKey: CryptoKey,
16-
privateKey: CryptoKey,
17-
requestMethod: string,
18-
requestUri: string
19-
};
20-
2113
/**
2214
* This class implements MSAL's crypto interface, which allows it to perform base64 encoding and decoding, generating cryptographically random GUIDs and
2315
* implementing Proof Key for Code Exchange specs for the OAuth Authorization Code Flow using PKCE (rfc here: https://tools.ietf.org/html/rfc7636).
@@ -34,20 +26,23 @@ export class CryptoOps implements ICrypto {
3426
private static EXTRACTABLE: boolean = true;
3527
private static POP_HASH_LENGTH = 43; // 256 bit digest / 6 bits per char = 43
3628

37-
private static DB_VERSION = 1;
38-
private static DB_NAME = "msal.db";
39-
private static TABLE_NAME =`${CryptoOps.DB_NAME}.keys`;
40-
private _cache: DatabaseStorage<CachedKeyPair>;
41-
4229
constructor() {
4330
// Browser crypto needs to be validated first before any other classes can be set.
4431
this.browserCrypto = new BrowserCrypto();
4532
this.b64Encode = new Base64Encode();
4633
this.b64Decode = new Base64Decode();
4734
this.guidGenerator = new GuidGenerator(this.browserCrypto);
4835
this.pkceGenerator = new PkceGenerator(this.browserCrypto);
49-
this._cache = new DatabaseStorage(CryptoOps.DB_NAME, CryptoOps.TABLE_NAME, CryptoOps.DB_VERSION);
50-
this._cache.open();
36+
}
37+
38+
async getPublicKeyThumprint(): Promise<string> {
39+
const keyPair = await this.browserCrypto.generateKeyPair(CryptoOps.EXTRACTABLE, CryptoOps.POP_KEY_USAGES);
40+
// TODO: Store keypair
41+
const publicKeyJwk: JsonWebKey = await this.browserCrypto.exportKey(keyPair.publicKey, KeyFormat.jwk);
42+
const publicJwkString: string = BrowserCrypto.getJwkString(publicKeyJwk);
43+
const publicJwkBuffer: ArrayBuffer = await this.browserCrypto.sha256Digest(publicJwkString);
44+
const publicJwkDigest: string = this.b64Encode.urlEncodeArr(new Uint8Array(publicJwkBuffer));
45+
return this.base64Encode(publicJwkDigest).substr(0, CryptoOps.POP_HASH_LENGTH);
5146
}
5247

5348
/**
@@ -80,53 +75,4 @@ export class CryptoOps implements ICrypto {
8075
async generatePkceCodes(): Promise<PkceCodes> {
8176
return this.pkceGenerator.generateCodes();
8277
}
83-
84-
/**
85-
* Generates a keypair, stores it and returns a thumbprint
86-
* @param resourceRequestMethod
87-
* @param resourceRequestUri
88-
*/
89-
async getPublicKeyThumprint(resourceRequestMethod: string, resourceRequestUri: string): Promise<string> {
90-
const keyPair = await this.browserCrypto.generateKeyPair(CryptoOps.EXTRACTABLE, CryptoOps.POP_KEY_USAGES);
91-
const publicKeyJwk: JsonWebKey = await this.browserCrypto.exportKey(keyPair.publicKey, KeyFormat.jwk);
92-
const privateKeyJwk: JsonWebKey = await this.browserCrypto.exportKey(keyPair.privateKey, KeyFormat.jwk);
93-
const publicJwkString: string = BrowserCrypto.getJwkString(publicKeyJwk);
94-
const publicJwkBuffer: ArrayBuffer = await this.browserCrypto.sha256Digest(publicJwkString);
95-
const publicJwkDigest: string = this.b64Encode.urlEncodeArr(new Uint8Array(publicJwkBuffer));
96-
const unextractablePrivateKey: CryptoKey = await this.browserCrypto.importKey(privateKeyJwk, KeyFormat.jwk, false, ["sign"]);
97-
const publicKeyHash = this.base64Encode(publicJwkDigest).substr(0, CryptoOps.POP_HASH_LENGTH);
98-
this._cache.put(publicKeyHash, {
99-
privateKey: unextractablePrivateKey,
100-
publicKey: keyPair.publicKey,
101-
requestMethod: resourceRequestMethod,
102-
requestUri: resourceRequestUri
103-
});
104-
return publicKeyHash;
105-
}
106-
107-
/**
108-
* Signs the given object as a jwt payload with private key retrieved by given kid.
109-
* @param payload
110-
* @param kid
111-
*/
112-
async signJwt(payload: SignedHttpRequest, kid: string): Promise<string> {
113-
const cachedKeyPair: CachedKeyPair = await this._cache.get(kid);
114-
const publicKeyJwk = await this.browserCrypto.exportKey(cachedKeyPair.publicKey, KeyFormat.jwk);
115-
const publicKeyJwkString = BrowserCrypto.getJwkString(publicKeyJwk);
116-
117-
const header = {
118-
alg: publicKeyJwk.alg,
119-
type: KeyFormat.jwk,
120-
jwk: JSON.parse(publicKeyJwkString)
121-
};
122-
123-
const encodedHeader = this.b64Encode.urlEncode(JSON.stringify(header));
124-
const encodedPayload = this.b64Encode.urlEncode(JSON.stringify(payload));
125-
const tokenString = `${encodedHeader}.${encodedPayload}`;
126-
const tokenBuffer = BrowserStringUtils.stringToArrayBuffer(tokenString);
127-
const signatureBuffer = await this.browserCrypto.sign(cachedKeyPair.privateKey, tokenBuffer);
128-
const encodedSignature = this.b64Encode.urlEncode(BrowserStringUtils.utf8ArrToString(new Uint8Array(signatureBuffer)));
129-
130-
return `${tokenString}.${encodedSignature}`;
131-
}
13278
}

lib/msal-browser/src/utils/BrowserStringUtils.ts

-13
Original file line numberDiff line numberDiff line change
@@ -68,19 +68,6 @@ export class BrowserStringUtils {
6868
return aBytes;
6969
}
7070

71-
/**
72-
* Converst string to ArrayBuffer
73-
* @param dataString
74-
*/
75-
static stringToArrayBuffer(dataString: string): ArrayBuffer {
76-
const data = new ArrayBuffer(dataString.length);
77-
const dataView = new Uint8Array(data);
78-
for (let i: number = 0; i < dataString.length; i++) {
79-
dataView[i] = dataString.charCodeAt(i);
80-
}
81-
return data;
82-
}
83-
8471
/**
8572
* Converts Uint8Array to a string
8673
* @param aBytes

lib/msal-common/src/account/JwtToken.ts renamed to lib/msal-common/src/account/IdToken.ts

+14-14
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Copyright (c) Microsoft Corporation. All rights reserved.
33
* Licensed under the MIT License.
44
*/
5-
import { TokenClaims } from "./TokenClaims";
5+
import { IdTokenClaims } from "./IdTokenClaims";
66
import { DecodedJwt } from "./DecodedJwt";
77
import { ClientAuthError } from "../error/ClientAuthError";
88
import { StringUtils } from "../utils/StringUtils";
@@ -11,39 +11,39 @@ import { ICrypto } from "../crypto/ICrypto";
1111
/**
1212
* Id Token representation class. Parses id token string and generates claims object.
1313
*/
14-
export class JwtToken {
14+
export class IdToken {
1515

1616
// Raw Id Token string
17-
rawToken: string;
17+
rawIdToken: string;
1818
// Claims inside Id Token
19-
claims: TokenClaims;
20-
constructor(rawToken: string, crypto: ICrypto) {
21-
if (StringUtils.isEmpty(rawToken)) {
22-
throw ClientAuthError.createTokenNullOrEmptyError(rawToken);
19+
claims: IdTokenClaims;
20+
constructor(rawIdToken: string, crypto: ICrypto) {
21+
if (StringUtils.isEmpty(rawIdToken)) {
22+
throw ClientAuthError.createIdTokenNullOrEmptyError(rawIdToken);
2323
}
2424

25-
this.rawToken = rawToken;
26-
this.claims = JwtToken.extractTokenClaims(rawToken, crypto);
25+
this.rawIdToken = rawIdToken;
26+
this.claims = IdToken.extractIdToken(rawIdToken, crypto);
2727
}
2828

2929
/**
3030
* Extract IdToken by decoding the RAWIdToken
3131
*
3232
* @param encodedIdToken
3333
*/
34-
static extractTokenClaims(encodedIdToken: string, crypto: ICrypto): TokenClaims {
34+
static extractIdToken(encodedIdToken: string, crypto: ICrypto): IdTokenClaims {
3535
// id token will be decoded to get the username
3636
const decodedToken: DecodedJwt = StringUtils.decodeJwt(encodedIdToken);
3737
if (!decodedToken) {
3838
return null;
3939
}
4040
try {
41-
const base64TokenPayload = decodedToken.JWSPayload;
41+
const base64IdTokenPayload = decodedToken.JWSPayload;
4242
// base64Decode() should throw an error if there is an issue
43-
const base64Decoded = crypto.base64Decode(base64TokenPayload);
44-
return JSON.parse(base64Decoded) as TokenClaims;
43+
const base64Decoded = crypto.base64Decode(base64IdTokenPayload);
44+
return JSON.parse(base64Decoded) as IdTokenClaims;
4545
} catch (err) {
46-
throw ClientAuthError.createTokenParsingError(err);
46+
throw ClientAuthError.createIdTokenParsingError(err);
4747
}
4848
}
4949
}

0 commit comments

Comments
 (0)