2
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
3
* Licensed under the MIT License.
4
4
*/
5
- import { ICrypto , PkceCodes , SignedHttpRequest } from "@azure/msal-common" ;
5
+ import { ICrypto , PkceCodes } from "@azure/msal-common" ;
6
6
import { GuidGenerator } from "./GuidGenerator" ;
7
7
import { Base64Encode } from "../encode/Base64Encode" ;
8
8
import { Base64Decode } from "../encode/Base64Decode" ;
9
9
import { PkceGenerator } from "./PkceGenerator" ;
10
10
import { BrowserCrypto , KeyFormat } from "./BrowserCrypto" ;
11
- import { DatabaseStorage } from "../cache/DatabaseStorage" ;
12
11
import { BrowserStringUtils } from "../utils/BrowserStringUtils" ;
13
12
14
- type CachedKeyPair = {
15
- publicKey : CryptoKey ,
16
- privateKey : CryptoKey ,
17
- requestMethod : string ,
18
- requestUri : string
19
- } ;
20
-
21
13
/**
22
14
* This class implements MSAL's crypto interface, which allows it to perform base64 encoding and decoding, generating cryptographically random GUIDs and
23
15
* 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 {
34
26
private static EXTRACTABLE : boolean = true ;
35
27
private static POP_HASH_LENGTH = 43 ; // 256 bit digest / 6 bits per char = 43
36
28
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
-
42
29
constructor ( ) {
43
30
// Browser crypto needs to be validated first before any other classes can be set.
44
31
this . browserCrypto = new BrowserCrypto ( ) ;
45
32
this . b64Encode = new Base64Encode ( ) ;
46
33
this . b64Decode = new Base64Decode ( ) ;
47
34
this . guidGenerator = new GuidGenerator ( this . browserCrypto ) ;
48
35
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 ) ;
51
46
}
52
47
53
48
/**
@@ -80,53 +75,4 @@ export class CryptoOps implements ICrypto {
80
75
async generatePkceCodes ( ) : Promise < PkceCodes > {
81
76
return this . pkceGenerator . generateCodes ( ) ;
82
77
}
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
- }
132
78
}
0 commit comments