@adobe/helix-onedrive-support 9.1.32 → 10.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/package.json +2 -1
- package/src/OneDriveAuth.js +1 -1
- package/src/index.d.ts +0 -6
- package/src/index.js +0 -5
- package/src/cache/FSCacheManager.d.ts +0 -28
- package/src/cache/FSCacheManager.js +0 -77
- package/src/cache/FSCachePlugin.d.ts +0 -29
- package/src/cache/FSCachePlugin.js +0 -73
- package/src/cache/MemCachePlugin.d.ts +0 -34
- package/src/cache/MemCachePlugin.js +0 -88
- package/src/cache/S3CacheManager.d.ts +0 -40
- package/src/cache/S3CacheManager.js +0 -107
- package/src/cache/S3CachePlugin.d.ts +0 -49
- package/src/cache/S3CachePlugin.js +0 -116
- package/src/cache/encrypt.js +0 -70
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# [10.0.0](https://github.com/adobe/helix-onedrive-support/compare/v9.1.32...v10.0.0) (2023-05-02)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* use helix-shared-tokencache ([#373](https://github.com/adobe/helix-onedrive-support/issues/373)) ([d6d2ab0](https://github.com/adobe/helix-onedrive-support/commit/d6d2ab0bce1987ad4f46d3a5e84d986dff1c54b2))
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### BREAKING CHANGES
|
|
10
|
+
|
|
11
|
+
* token cache moved to @adobe/helix-shared-tokencache
|
|
12
|
+
|
|
1
13
|
## [9.1.32](https://github.com/adobe/helix-onedrive-support/compare/v9.1.31...v9.1.32) (2023-04-29)
|
|
2
14
|
|
|
3
15
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/helix-onedrive-support",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "10.0.0",
|
|
4
4
|
"description": "Helix OneDrive Support",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"homepage": "https://github.com/adobe/helix-onedrive-support#readme",
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@adobe/fetch": "4.0.10",
|
|
31
|
+
"@adobe/helix-shared-tokencache": "1.0.0",
|
|
31
32
|
"@aws-sdk/client-s3": "3.321.1",
|
|
32
33
|
"@azure/msal-node": "1.17.1",
|
|
33
34
|
"jose": "4.14.3"
|
package/src/OneDriveAuth.js
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
// eslint-disable-next-line max-classes-per-file
|
|
14
14
|
import { keepAliveNoCache } from '@adobe/fetch';
|
|
15
15
|
import { ConfidentialClientApplication, LogLevel, PublicClientApplication } from '@azure/msal-node';
|
|
16
|
+
import { MemCachePlugin } from '@adobe/helix-shared-tokencache';
|
|
16
17
|
import { decodeJwt } from 'jose';
|
|
17
|
-
import { MemCachePlugin } from './cache/MemCachePlugin.js';
|
|
18
18
|
|
|
19
19
|
const AZ_AUTHORITY_HOST_URL = 'https://login.windows.net';
|
|
20
20
|
const AZ_COMMON_TENANT = 'common';
|
package/src/index.d.ts
CHANGED
|
@@ -18,9 +18,3 @@ export * from './excel/Worksheet';
|
|
|
18
18
|
export * from './excel/NamedItem';
|
|
19
19
|
export * from './excel/Table';
|
|
20
20
|
export * from './excel/Range';
|
|
21
|
-
|
|
22
|
-
export * from './cache/FSCacheManager';
|
|
23
|
-
export * from './cache/FSCachePlugin';
|
|
24
|
-
export * from './cache/MemCachePlugin';
|
|
25
|
-
export * from './cache/S3CacheManager';
|
|
26
|
-
export * from './cache/S3CachePlugin';
|
package/src/index.js
CHANGED
|
@@ -12,11 +12,6 @@
|
|
|
12
12
|
export { OneDrive } from './OneDrive.js';
|
|
13
13
|
export { OneDriveAuth, AcquireMethod } from './OneDriveAuth.js';
|
|
14
14
|
|
|
15
|
-
export { FSCachePlugin } from './cache/FSCachePlugin.js';
|
|
16
|
-
export { FSCacheManager } from './cache/FSCacheManager.js';
|
|
17
|
-
export { MemCachePlugin } from './cache/MemCachePlugin.js';
|
|
18
|
-
export { S3CachePlugin } from './cache/S3CachePlugin.js';
|
|
19
|
-
export { S3CacheManager } from './cache/S3CacheManager.js';
|
|
20
15
|
export { OneDriveMock } from './OneDriveMock.js';
|
|
21
16
|
export { StatusCodeError } from './StatusCodeError.js';
|
|
22
17
|
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2022 Adobe. All rights reserved.
|
|
3
|
-
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
-
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
-
*
|
|
7
|
-
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
-
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
-
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
-
* governing permissions and limitations under the License.
|
|
11
|
-
*/
|
|
12
|
-
import { FSCachePlugin } from "./FSCachePlugin";
|
|
13
|
-
|
|
14
|
-
export declare interface FSCacheManagerOptions {
|
|
15
|
-
log: Console;
|
|
16
|
-
dirPath: string;
|
|
17
|
-
type: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export declare class FSCacheManager {
|
|
21
|
-
constructor(opts: FSCacheManagerOptions);
|
|
22
|
-
|
|
23
|
-
listCacheKeys():Promise<string[]>;
|
|
24
|
-
|
|
25
|
-
hasCache(key:string):Promise<boolean>;
|
|
26
|
-
|
|
27
|
-
getCache(key:string):Promise<FSCachePlugin>;
|
|
28
|
-
}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2022 Adobe. All rights reserved.
|
|
3
|
-
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
-
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
-
*
|
|
7
|
-
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
-
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
-
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
-
* governing permissions and limitations under the License.
|
|
11
|
-
*/
|
|
12
|
-
import fs from 'fs/promises';
|
|
13
|
-
import path from 'path';
|
|
14
|
-
import { FSCachePlugin } from './FSCachePlugin.js';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* aliases
|
|
18
|
-
* @typedef {import("@azure/msal-node").ICachePlugin} ICachePlugin
|
|
19
|
-
* @typedef {import("@azure/msal-node").TokenCacheContext} TokenCacheContext
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
export class FSCacheManager {
|
|
23
|
-
constructor(opts) {
|
|
24
|
-
this.dirPath = opts.dirPath;
|
|
25
|
-
this.log = opts.log || console;
|
|
26
|
-
this.type = opts.type;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
getCacheFilePath(key) {
|
|
30
|
-
return path.resolve(this.dirPath, `auth-${this.type}-${key}.json`);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async listCacheKeys() {
|
|
34
|
-
try {
|
|
35
|
-
const files = await fs.readdir(this.dirPath);
|
|
36
|
-
return files
|
|
37
|
-
.filter((name) => (name.startsWith('auth-') && name.endsWith('.json')))
|
|
38
|
-
.map((name) => name.replace(/auth-([a-z0-9]+)-([a-z0-9]+).json/i, '$2'));
|
|
39
|
-
} catch (e) {
|
|
40
|
-
if (e.code === 'ENOENT') {
|
|
41
|
-
return [];
|
|
42
|
-
}
|
|
43
|
-
throw e;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async hasCache(key) {
|
|
48
|
-
try {
|
|
49
|
-
await fs.lstat(this.getCacheFilePath(key));
|
|
50
|
-
return true;
|
|
51
|
-
} catch (e) {
|
|
52
|
-
if (e.code !== 'ENOENT') {
|
|
53
|
-
throw e;
|
|
54
|
-
}
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* @param key
|
|
61
|
-
* @returns {FSCachePlugin}
|
|
62
|
-
*/
|
|
63
|
-
async getCache(key) {
|
|
64
|
-
try {
|
|
65
|
-
await fs.lstat(this.dirPath);
|
|
66
|
-
} catch (e) {
|
|
67
|
-
if (e.code !== 'ENOENT') {
|
|
68
|
-
throw e;
|
|
69
|
-
}
|
|
70
|
-
await fs.mkdir(this.dirPath);
|
|
71
|
-
}
|
|
72
|
-
return new FSCachePlugin({
|
|
73
|
-
log: this.log,
|
|
74
|
-
filePath: this.getCacheFilePath(key),
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2022 Adobe. All rights reserved.
|
|
3
|
-
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
-
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
-
*
|
|
7
|
-
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
-
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
-
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
-
* governing permissions and limitations under the License.
|
|
11
|
-
*/
|
|
12
|
-
import { ICachePlugin, TokenCacheContext } from '@azure/msal-node';
|
|
13
|
-
|
|
14
|
-
import { Logger } from "../OneDrive";
|
|
15
|
-
|
|
16
|
-
export declare interface FSCachePluginOptions {
|
|
17
|
-
log: Console;
|
|
18
|
-
filePath: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export declare class FSCachePlugin implements ICachePlugin {
|
|
22
|
-
constructor(opts: FSCachePluginOptions);
|
|
23
|
-
|
|
24
|
-
deleteCache(): Promise<void>;
|
|
25
|
-
|
|
26
|
-
afterCacheAccess(tokenCacheContext: TokenCacheContext): Promise<boolean>;
|
|
27
|
-
|
|
28
|
-
beforeCacheAccess(tokenCacheContext: TokenCacheContext): Promise<boolean>;
|
|
29
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2022 Adobe. All rights reserved.
|
|
3
|
-
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
-
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
-
*
|
|
7
|
-
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
-
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
-
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
-
* governing permissions and limitations under the License.
|
|
11
|
-
*/
|
|
12
|
-
import fs from 'fs/promises';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* aliases
|
|
16
|
-
* @typedef {import("@azure/msal-node").ICachePlugin} ICachePlugin
|
|
17
|
-
* @typedef {import("@azure/msal-node").TokenCacheContext} TokenCacheContext
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Cache plugin for MSAL
|
|
22
|
-
* @param {FSCachePluginOptions} opts
|
|
23
|
-
* @class FSCachePlugin
|
|
24
|
-
* @implements ICachePlugin
|
|
25
|
-
*/
|
|
26
|
-
export class FSCachePlugin {
|
|
27
|
-
constructor(opts) {
|
|
28
|
-
this.filePath = opts.filePath;
|
|
29
|
-
this.log = opts.log || console;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async deleteCache() {
|
|
33
|
-
try {
|
|
34
|
-
await fs.rm(this.filePath);
|
|
35
|
-
} catch (e) {
|
|
36
|
-
this.log.warn(`error deleting cache: ${e.message}`);
|
|
37
|
-
// ignore
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* @param {TokenCacheContext} cacheContext
|
|
43
|
-
* @returns {Promise<boolean>} if cache was updated
|
|
44
|
-
*/
|
|
45
|
-
async beforeCacheAccess(cacheContext) {
|
|
46
|
-
const { log, filePath } = this;
|
|
47
|
-
try {
|
|
48
|
-
cacheContext.tokenCache.deserialize(await fs.readFile(filePath, 'utf-8'));
|
|
49
|
-
return true;
|
|
50
|
-
} catch (e) {
|
|
51
|
-
if (e.code !== 'ENOENT') {
|
|
52
|
-
// only log warnings if file exists, otherwise ignore
|
|
53
|
-
log.warn('FSCachePlugin: unable to deserialize', e);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* @param {TokenCacheContext} cacheContext
|
|
61
|
-
* @returns {Promise<boolean>} if cache was updated
|
|
62
|
-
*/
|
|
63
|
-
async afterCacheAccess(cacheContext) {
|
|
64
|
-
const { filePath } = this;
|
|
65
|
-
if (cacheContext.cacheHasChanged) {
|
|
66
|
-
// reparse and create a nice formatted JSON
|
|
67
|
-
const tokens = JSON.parse(cacheContext.tokenCache.serialize());
|
|
68
|
-
await fs.writeFile(filePath, JSON.stringify(tokens, null, 2), 'utf-8');
|
|
69
|
-
return true;
|
|
70
|
-
}
|
|
71
|
-
return false;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2022 Adobe. All rights reserved.
|
|
3
|
-
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
-
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
-
*
|
|
7
|
-
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
-
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
-
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
-
* governing permissions and limitations under the License.
|
|
11
|
-
*/
|
|
12
|
-
import { ICachePlugin, TokenCacheContext } from '@azure/msal-node';
|
|
13
|
-
|
|
14
|
-
import { Logger } from "../OneDrive";
|
|
15
|
-
|
|
16
|
-
export declare interface MemCachePluginOptions {
|
|
17
|
-
log: Console;
|
|
18
|
-
/**
|
|
19
|
-
* memory cache key
|
|
20
|
-
*/
|
|
21
|
-
key: string;
|
|
22
|
-
base: ICachePlugin;
|
|
23
|
-
caches?: Map<string, any>;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export declare class MemCachePlugin implements ICachePlugin {
|
|
27
|
-
constructor(opts: MemCachePluginOptions);
|
|
28
|
-
|
|
29
|
-
deleteCache(): Promise<void>;
|
|
30
|
-
|
|
31
|
-
afterCacheAccess(tokenCacheContext: TokenCacheContext): Promise<boolean>;
|
|
32
|
-
|
|
33
|
-
beforeCacheAccess(tokenCacheContext: TokenCacheContext): Promise<boolean>;
|
|
34
|
-
}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2022 Adobe. All rights reserved.
|
|
3
|
-
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
-
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
-
*
|
|
7
|
-
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
-
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
-
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
-
* governing permissions and limitations under the License.
|
|
11
|
-
*/
|
|
12
|
-
const caches = new Map();
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* aliases
|
|
16
|
-
* @typedef {import("@azure/msal-node").ICachePlugin} ICachePlugin
|
|
17
|
-
* @typedef {import("@azure/msal-node").TokenCacheContext} TokenCacheContext
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Cache plugin for MSAL
|
|
22
|
-
* @class MemCachePlugin
|
|
23
|
-
* @implements ICachePlugin
|
|
24
|
-
*/
|
|
25
|
-
export class MemCachePlugin {
|
|
26
|
-
/**
|
|
27
|
-
* @param {MemCachePluginOptions} opts
|
|
28
|
-
*/
|
|
29
|
-
constructor(opts = {}) {
|
|
30
|
-
this.log = opts.log || console;
|
|
31
|
-
this.key = opts.key;
|
|
32
|
-
this.base = opts.base;
|
|
33
|
-
this.caches = opts.caches || caches;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
clear() {
|
|
37
|
-
this.caches.clear();
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async deleteCache() {
|
|
41
|
-
this.log.debug('mem: delete token cache', this.key);
|
|
42
|
-
this.caches.delete(this.key);
|
|
43
|
-
if (this.base) {
|
|
44
|
-
await this.base.deleteCache();
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* @param {TokenCacheContext} cacheContext
|
|
50
|
-
*/
|
|
51
|
-
async beforeCacheAccess(cacheContext) {
|
|
52
|
-
try {
|
|
53
|
-
this.log.debug('mem: read token cache', this.key);
|
|
54
|
-
const cache = this.caches.get(this.key);
|
|
55
|
-
if (cache) {
|
|
56
|
-
cacheContext.tokenCache.deserialize(cache);
|
|
57
|
-
return true;
|
|
58
|
-
} else if (this.base) {
|
|
59
|
-
this.log.debug('mem: read token cache failed. asking base');
|
|
60
|
-
const ret = await this.base.beforeCacheAccess(cacheContext);
|
|
61
|
-
if (ret) {
|
|
62
|
-
this.log.debug('mem: base updated. remember.');
|
|
63
|
-
this.caches.set(this.key, cacheContext.tokenCache.serialize());
|
|
64
|
-
}
|
|
65
|
-
return ret;
|
|
66
|
-
}
|
|
67
|
-
} catch (e) {
|
|
68
|
-
this.log.warn('mem: unable to deserialize token cache.', e);
|
|
69
|
-
}
|
|
70
|
-
return false;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* @param {TokenCacheContext} cacheContext
|
|
75
|
-
*/
|
|
76
|
-
async afterCacheAccess(cacheContext) {
|
|
77
|
-
if (cacheContext.cacheHasChanged) {
|
|
78
|
-
this.log.debug('mem: write token cache', this.key);
|
|
79
|
-
this.caches.set(this.key, cacheContext.tokenCache.serialize());
|
|
80
|
-
if (this.base) {
|
|
81
|
-
this.log.debug('mem: write token cache done. telling base', this.key);
|
|
82
|
-
return this.base.afterCacheAccess(cacheContext);
|
|
83
|
-
}
|
|
84
|
-
return true;
|
|
85
|
-
}
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2022 Adobe. All rights reserved.
|
|
3
|
-
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
-
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
-
*
|
|
7
|
-
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
-
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
-
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
-
* governing permissions and limitations under the License.
|
|
11
|
-
*/
|
|
12
|
-
import { S3CachePlugin } from "./FSCachePlugin";
|
|
13
|
-
|
|
14
|
-
export declare interface S3CacheManagerOptions {
|
|
15
|
-
log: Console;
|
|
16
|
-
type: string;
|
|
17
|
-
bucket: string;
|
|
18
|
-
prefix: string;
|
|
19
|
-
secret: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export declare class S3CacheManager {
|
|
23
|
-
/**
|
|
24
|
-
* Find the first cache with the given opts, that exists, otherwise the plugin using the
|
|
25
|
-
* default options is returned.
|
|
26
|
-
* @param {string} key
|
|
27
|
-
* @param {object} defaultOpts
|
|
28
|
-
* @param {object} opts
|
|
29
|
-
* @returns {Promise<S3CachePlugin>}
|
|
30
|
-
*/
|
|
31
|
-
static findCache(key:string, defaultOpts:S3CacheManagerOptions, ...opts:S3CacheManagerOptions[]):Promise<S3CachePlugin>;
|
|
32
|
-
|
|
33
|
-
constructor(opts: S3CacheManagerOptions);
|
|
34
|
-
|
|
35
|
-
listCacheKeys():Promise<string[]>;
|
|
36
|
-
|
|
37
|
-
hasCache(key:string):Promise<boolean>;
|
|
38
|
-
|
|
39
|
-
getCache(key:string):Promise<S3CachePlugin>;
|
|
40
|
-
}
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2022 Adobe. All rights reserved.
|
|
3
|
-
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
-
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
-
*
|
|
7
|
-
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
-
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
-
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
-
* governing permissions and limitations under the License.
|
|
11
|
-
*/
|
|
12
|
-
import { basename } from 'path';
|
|
13
|
-
import { HeadObjectCommand, ListObjectsV2Command, S3Client } from '@aws-sdk/client-s3';
|
|
14
|
-
import { S3CachePlugin } from './S3CachePlugin.js';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* aliases
|
|
18
|
-
* @typedef {import("@azure/msal-node").ICachePlugin} ICachePlugin
|
|
19
|
-
* @typedef {import("@azure/msal-node").TokenCacheContext} TokenCacheContext
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
export class S3CacheManager {
|
|
23
|
-
/**
|
|
24
|
-
* Find the first cache with the given opts, that exists, otherwise the plugin using the
|
|
25
|
-
* default options is returned.
|
|
26
|
-
* @param {string} key
|
|
27
|
-
* @param {object} defaultOpts
|
|
28
|
-
* @param {object} opts
|
|
29
|
-
* @returns {Promise<S3CachePlugin>}
|
|
30
|
-
*/
|
|
31
|
-
static async findCache(key, defaultOpts, ...opts) {
|
|
32
|
-
for (const opt of opts) {
|
|
33
|
-
const cacheManager = new S3CacheManager({
|
|
34
|
-
...defaultOpts,
|
|
35
|
-
...opt,
|
|
36
|
-
});
|
|
37
|
-
// eslint-disable-next-line no-await-in-loop
|
|
38
|
-
if (await cacheManager.hasCache(key)) {
|
|
39
|
-
return cacheManager.getCache(key);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return new S3CacheManager(defaultOpts).getCache(key);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
constructor(opts) {
|
|
46
|
-
this.log = opts.log || console;
|
|
47
|
-
this.bucket = opts.bucket;
|
|
48
|
-
this.prefix = opts.prefix;
|
|
49
|
-
this.secret = opts.secret;
|
|
50
|
-
this.type = opts.type;
|
|
51
|
-
this.s3 = new S3Client();
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
getAuthObjectKey(key) {
|
|
55
|
-
return `${this.prefix}/auth-${this.type}-${key}.json`;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async listCacheKeys() {
|
|
59
|
-
const {
|
|
60
|
-
log, s3, bucket, prefix,
|
|
61
|
-
} = this;
|
|
62
|
-
log.debug('s3: list token cache', prefix);
|
|
63
|
-
try {
|
|
64
|
-
const res = await s3.send(new ListObjectsV2Command({
|
|
65
|
-
Bucket: bucket,
|
|
66
|
-
Prefix: `${prefix}/`,
|
|
67
|
-
}));
|
|
68
|
-
return (res.Contents || [])
|
|
69
|
-
.map((entry) => basename(entry.Key))
|
|
70
|
-
.filter((name) => (name.startsWith(`auth-${this.type}-`) && name.endsWith('.json')))
|
|
71
|
-
.map((name) => name.replace(/auth-([a-z0-9]+)-([a-z0-9]+).json/i, '$2'));
|
|
72
|
-
} catch (e) {
|
|
73
|
-
log.info('s3: unable to list token caches', e);
|
|
74
|
-
return [];
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
async hasCache(key) {
|
|
79
|
-
const { log, bucket } = this;
|
|
80
|
-
try {
|
|
81
|
-
await this.s3.send(new HeadObjectCommand({
|
|
82
|
-
Bucket: bucket,
|
|
83
|
-
Key: this.getAuthObjectKey(key),
|
|
84
|
-
}));
|
|
85
|
-
return true;
|
|
86
|
-
} catch (e) {
|
|
87
|
-
if (e.$metadata?.httpStatusCode !== 404) {
|
|
88
|
-
log.warn('s3: unable to check token cache', e);
|
|
89
|
-
throw e;
|
|
90
|
-
}
|
|
91
|
-
return false;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* @param key
|
|
97
|
-
* @returns {S3CachePlugin}
|
|
98
|
-
*/
|
|
99
|
-
async getCache(key) {
|
|
100
|
-
return new S3CachePlugin({
|
|
101
|
-
log: this.log,
|
|
102
|
-
key: this.getAuthObjectKey(key),
|
|
103
|
-
secret: this.secret,
|
|
104
|
-
bucket: this.bucket,
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2022 Adobe. All rights reserved.
|
|
3
|
-
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
-
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
-
*
|
|
7
|
-
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
-
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
-
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
-
* governing permissions and limitations under the License.
|
|
11
|
-
*/
|
|
12
|
-
import { ICachePlugin, TokenCacheContext } from '@azure/msal-node';
|
|
13
|
-
|
|
14
|
-
import { Logger } from "../OneDrive";
|
|
15
|
-
|
|
16
|
-
export declare interface S3CachePluginOptions {
|
|
17
|
-
log: Console;
|
|
18
|
-
bucket: string;
|
|
19
|
-
key: string;
|
|
20
|
-
secret: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export declare class S3CachePlugin implements ICachePlugin {
|
|
24
|
-
/**
|
|
25
|
-
* Decrypts a AES-GCM encrypted digest.
|
|
26
|
-
* @param {string} key encryption key / password
|
|
27
|
-
* @param {Buffer} data the encrypted data
|
|
28
|
-
* @returns {Buffer} the plain text
|
|
29
|
-
* @throws an error if the given key cannot decrypt the digest.
|
|
30
|
-
*/
|
|
31
|
-
static encrypt(key:string, data:Buffer):Buffer;
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Decrypts a AES-GCM encrypted digest.
|
|
35
|
-
* @param {string} key encryption key / password
|
|
36
|
-
* @param {Buffer} data the encrypted data
|
|
37
|
-
* @returns {Buffer} the plain text
|
|
38
|
-
* @throws an error if the given key cannot decrypt the digest.
|
|
39
|
-
*/
|
|
40
|
-
static decrypt(key: string, data: Buffer):Buffer;
|
|
41
|
-
|
|
42
|
-
constructor(opts: S3CachePluginOptions);
|
|
43
|
-
|
|
44
|
-
deleteCache(): Promise<void>;
|
|
45
|
-
|
|
46
|
-
afterCacheAccess(tokenCacheContext: TokenCacheContext): Promise<boolean>;
|
|
47
|
-
|
|
48
|
-
beforeCacheAccess(tokenCacheContext: TokenCacheContext): Promise<boolean>;
|
|
49
|
-
}
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2021 Adobe. All rights reserved.
|
|
3
|
-
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
-
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
-
*
|
|
7
|
-
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
-
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
-
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
-
* governing permissions and limitations under the License.
|
|
11
|
-
*/
|
|
12
|
-
import {
|
|
13
|
-
DeleteObjectCommand,
|
|
14
|
-
GetObjectCommand,
|
|
15
|
-
PutObjectCommand,
|
|
16
|
-
S3Client,
|
|
17
|
-
} from '@aws-sdk/client-s3';
|
|
18
|
-
import { Response } from '@adobe/fetch';
|
|
19
|
-
import { decrypt, encrypt } from './encrypt.js';
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* aliases
|
|
23
|
-
* @typedef {import("@azure/msal-node").ICachePlugin} ICachePlugin
|
|
24
|
-
* @typedef {import("@azure/msal-node").TokenCacheContext} TokenCacheContext
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Cache plugin for MSAL
|
|
29
|
-
* @class MemCachePlugin
|
|
30
|
-
* @implements ICachePlugin
|
|
31
|
-
*/
|
|
32
|
-
export class S3CachePlugin {
|
|
33
|
-
/**
|
|
34
|
-
* @param {S3CachePluginOptions} opts
|
|
35
|
-
*/
|
|
36
|
-
constructor(opts) {
|
|
37
|
-
this.log = opts.log || console;
|
|
38
|
-
this.bucket = opts.bucket;
|
|
39
|
-
this.key = opts.key;
|
|
40
|
-
this.secret = opts.secret;
|
|
41
|
-
this.s3 = new S3Client();
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
async deleteCache() {
|
|
45
|
-
const { log, key, bucket } = this;
|
|
46
|
-
try {
|
|
47
|
-
log.debug('s3: read token cache', key);
|
|
48
|
-
await this.s3.send(new DeleteObjectCommand({
|
|
49
|
-
Bucket: bucket,
|
|
50
|
-
Key: key,
|
|
51
|
-
}));
|
|
52
|
-
} catch (e) {
|
|
53
|
-
if (e.$metadata?.httpStatusCode === 404) {
|
|
54
|
-
log.info('s3: unable to deserialize token cache: not found');
|
|
55
|
-
} else {
|
|
56
|
-
log.warn('s3: unable to deserialize token cache', e);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
async beforeCacheAccess(cacheContext) {
|
|
62
|
-
const {
|
|
63
|
-
log, secret, key, bucket,
|
|
64
|
-
} = this;
|
|
65
|
-
try {
|
|
66
|
-
log.debug('s3: read token cache', key);
|
|
67
|
-
const res = await this.s3.send(new GetObjectCommand({
|
|
68
|
-
Bucket: bucket,
|
|
69
|
-
Key: key,
|
|
70
|
-
}));
|
|
71
|
-
let data = await new Response(res.Body, {}).buffer();
|
|
72
|
-
if (secret) {
|
|
73
|
-
data = decrypt(secret, data).toString('utf-8');
|
|
74
|
-
} else {
|
|
75
|
-
data = data.toString('utf-8');
|
|
76
|
-
}
|
|
77
|
-
cacheContext.tokenCache.deserialize(data);
|
|
78
|
-
return true;
|
|
79
|
-
} catch (e) {
|
|
80
|
-
if (e.$metadata?.httpStatusCode === 404) {
|
|
81
|
-
log.info('s3: unable to deserialize token cache: not found');
|
|
82
|
-
} else {
|
|
83
|
-
log.warn('s3: unable to deserialize token cache', e);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
async afterCacheAccess(cacheContext) {
|
|
90
|
-
if (cacheContext.cacheHasChanged) {
|
|
91
|
-
const {
|
|
92
|
-
log, secret, key, bucket,
|
|
93
|
-
} = this;
|
|
94
|
-
try {
|
|
95
|
-
log.debug('s3: write token cache', key);
|
|
96
|
-
let data = cacheContext.tokenCache.serialize();
|
|
97
|
-
if (secret) {
|
|
98
|
-
data = encrypt(secret, Buffer.from(data, 'utf-8'));
|
|
99
|
-
}
|
|
100
|
-
await this.s3.send(new PutObjectCommand({
|
|
101
|
-
Bucket: bucket,
|
|
102
|
-
Key: key,
|
|
103
|
-
Body: data,
|
|
104
|
-
ContentType: secret ? 'application/octet-stream' : 'text/plain',
|
|
105
|
-
}));
|
|
106
|
-
return true;
|
|
107
|
-
} catch (e) {
|
|
108
|
-
log.warn('s3: unable to serialize token cache', e);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
return false;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
S3CachePlugin.encrypt = encrypt;
|
|
116
|
-
S3CachePlugin.decrypt = decrypt;
|
package/src/cache/encrypt.js
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2021 Adobe. All rights reserved.
|
|
3
|
-
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
-
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
-
*
|
|
7
|
-
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
-
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
-
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
-
* governing permissions and limitations under the License.
|
|
11
|
-
*/
|
|
12
|
-
import crypto from 'crypto';
|
|
13
|
-
|
|
14
|
-
const ALGO = 'aes-256-gcm';
|
|
15
|
-
const SALT_SIZE = 8;
|
|
16
|
-
const IV_SIZE = 12;
|
|
17
|
-
const AUTH_TAG_SIZE = 16;
|
|
18
|
-
|
|
19
|
-
function deriveKey(key, salt) {
|
|
20
|
-
return crypto.pbkdf2Sync(key, salt, 10000, 32, 'sha512');
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Provides an AES-GCM symmetric encryption using a key derivation from a generic password.
|
|
25
|
-
* The resulting string is a base64 encoded buffer of the salt, iv, auth and encrypted text.
|
|
26
|
-
* Using GCM has the advantage over plain AES, that the validity of the key can be verified.
|
|
27
|
-
* (similar to a AES + HMAC approach).
|
|
28
|
-
*
|
|
29
|
-
* result = base64( salt | iv | auth | enc )
|
|
30
|
-
*
|
|
31
|
-
* @param {string} key encryption key / password
|
|
32
|
-
* @param {Buffer} plain Plain text to encrypt
|
|
33
|
-
* @return {Buffer} digest.
|
|
34
|
-
*/
|
|
35
|
-
export function encrypt(key, plain) {
|
|
36
|
-
const salt = crypto.randomBytes(SALT_SIZE);
|
|
37
|
-
const iv = crypto.randomBytes(IV_SIZE);
|
|
38
|
-
const derivedKey = deriveKey(key, salt);
|
|
39
|
-
const cipher = crypto.createCipheriv(ALGO, derivedKey, iv);
|
|
40
|
-
|
|
41
|
-
const data = [salt, iv, null];
|
|
42
|
-
data.push(cipher.update(plain));
|
|
43
|
-
data.push(cipher.final());
|
|
44
|
-
data[2] = cipher.getAuthTag();
|
|
45
|
-
return Buffer.concat(data);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Decrypts a AES-GCM encrypted digest.
|
|
50
|
-
* @param {string} key encryption key / password
|
|
51
|
-
* @param {Buffer} data the encrypted data
|
|
52
|
-
* @returns {Buffer} the plain text
|
|
53
|
-
* @throws an error if the given key cannot decrypt the digest.
|
|
54
|
-
*/
|
|
55
|
-
export function decrypt(key, data) {
|
|
56
|
-
const salt = data.slice(0, SALT_SIZE);
|
|
57
|
-
const iv = data.slice(SALT_SIZE, SALT_SIZE + IV_SIZE);
|
|
58
|
-
const authTag = data.slice(SALT_SIZE + IV_SIZE, SALT_SIZE + IV_SIZE + AUTH_TAG_SIZE);
|
|
59
|
-
const enc = data.slice(SALT_SIZE + IV_SIZE + AUTH_TAG_SIZE);
|
|
60
|
-
|
|
61
|
-
const derivedKey = deriveKey(key, salt);
|
|
62
|
-
const decipher = crypto.createDecipheriv(ALGO, derivedKey, iv);
|
|
63
|
-
decipher.setAuthTag(authTag);
|
|
64
|
-
|
|
65
|
-
const ret = [
|
|
66
|
-
decipher.update(enc),
|
|
67
|
-
decipher.final(),
|
|
68
|
-
];
|
|
69
|
-
return Buffer.concat(ret);
|
|
70
|
-
}
|