@enfuce/nextgen-sdk 0.0.4 → 0.0.5
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/dist/esm/oauth/axios.d.ts +10 -4
- package/dist/esm/oauth/axios.js +15 -4
- package/dist/esm/oauth/index.js +5 -2
- package/dist/oauth/axios.d.ts +10 -4
- package/dist/oauth/axios.js +15 -4
- package/dist/oauth/index.js +5 -2
- package/package.json +1 -1
- package/src/oauth/axios.ts +16 -4
- package/src/oauth/index.ts +5 -2
- package/test/oauth.test.ts +19 -0
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { AxiosInstance } from 'axios';
|
|
2
2
|
import { TokenManager } from './tokenManager';
|
|
3
3
|
/**
|
|
4
|
-
* Returns an {@link AxiosInstance} with
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Returns an {@link AxiosInstance} with OAuth bearer-token handling built in:
|
|
5
|
+
*
|
|
6
|
+
* - **Proactive:** a request interceptor attaches a fresh bearer token (from the
|
|
7
|
+
* {@link TokenManager}) to *every* request. This authenticates API modules whose spec declares no
|
|
8
|
+
* security scheme (e.g. exchange-rate), so no `accessToken` on the `Configuration` is required.
|
|
9
|
+
* - **Reactive:** a response interceptor, on a `401`, forces a token refresh and retries the request
|
|
10
|
+
* exactly once with the new bearer token.
|
|
11
|
+
*
|
|
12
|
+
* Pass it as the third argument of a generated API class:
|
|
7
13
|
*
|
|
8
14
|
* ```ts
|
|
9
15
|
* const http = createOAuthAxios(tokens);
|
|
10
|
-
* const config = new card.Configuration({
|
|
16
|
+
* const config = new card.Configuration({ basePath });
|
|
11
17
|
* const api = new card.CardApi(config, undefined, http);
|
|
12
18
|
* ```
|
|
13
19
|
*/
|
package/dist/esm/oauth/axios.js
CHANGED
|
@@ -22,18 +22,29 @@ function stripBearer(header) {
|
|
|
22
22
|
: header;
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
|
-
* Returns an {@link AxiosInstance} with
|
|
26
|
-
*
|
|
27
|
-
*
|
|
25
|
+
* Returns an {@link AxiosInstance} with OAuth bearer-token handling built in:
|
|
26
|
+
*
|
|
27
|
+
* - **Proactive:** a request interceptor attaches a fresh bearer token (from the
|
|
28
|
+
* {@link TokenManager}) to *every* request. This authenticates API modules whose spec declares no
|
|
29
|
+
* security scheme (e.g. exchange-rate), so no `accessToken` on the `Configuration` is required.
|
|
30
|
+
* - **Reactive:** a response interceptor, on a `401`, forces a token refresh and retries the request
|
|
31
|
+
* exactly once with the new bearer token.
|
|
32
|
+
*
|
|
33
|
+
* Pass it as the third argument of a generated API class:
|
|
28
34
|
*
|
|
29
35
|
* ```ts
|
|
30
36
|
* const http = createOAuthAxios(tokens);
|
|
31
|
-
* const config = new card.Configuration({
|
|
37
|
+
* const config = new card.Configuration({ basePath });
|
|
32
38
|
* const api = new card.CardApi(config, undefined, http);
|
|
33
39
|
* ```
|
|
34
40
|
*/
|
|
35
41
|
export function createOAuthAxios(manager, instance) {
|
|
36
42
|
const http = instance !== null && instance !== void 0 ? instance : axios.create();
|
|
43
|
+
// Proactive: attach a fresh bearer token to every outgoing request.
|
|
44
|
+
http.interceptors.request.use((config) => __awaiter(this, void 0, void 0, function* () {
|
|
45
|
+
config.headers.set('Authorization', BEARER_PREFIX + (yield manager.getToken()));
|
|
46
|
+
return config;
|
|
47
|
+
}));
|
|
37
48
|
http.interceptors.response.use(undefined, (error) => __awaiter(this, void 0, void 0, function* () {
|
|
38
49
|
var _a, _b, _c;
|
|
39
50
|
const response = error.response;
|
package/dist/esm/oauth/index.js
CHANGED
|
@@ -13,10 +13,13 @@
|
|
|
13
13
|
* clientSecret: 'my-secret',
|
|
14
14
|
* scopes: ['cards:read'],
|
|
15
15
|
* });
|
|
16
|
-
* const http = oauth.createOAuthAxios(tokens);
|
|
17
|
-
* const config = new card.Configuration({
|
|
16
|
+
* const http = oauth.createOAuthAxios(tokens); // attaches the token + retries on 401
|
|
17
|
+
* const config = new card.Configuration({ basePath: 'https://api.example.com' });
|
|
18
18
|
* const api = new card.CardApi(config, undefined, http);
|
|
19
19
|
*
|
|
20
|
+
* The same `http` instance authenticates every API module, including ones whose spec declares no
|
|
21
|
+
* security scheme (e.g. exchange-rate) — no `accessToken` on the `Configuration` is required.
|
|
22
|
+
*
|
|
20
23
|
* Server-side only — a client secret must never ship to a browser.
|
|
21
24
|
*/
|
|
22
25
|
export { TokenManager } from './tokenManager';
|
package/dist/oauth/axios.d.ts
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { AxiosInstance } from 'axios';
|
|
2
2
|
import { TokenManager } from './tokenManager';
|
|
3
3
|
/**
|
|
4
|
-
* Returns an {@link AxiosInstance} with
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Returns an {@link AxiosInstance} with OAuth bearer-token handling built in:
|
|
5
|
+
*
|
|
6
|
+
* - **Proactive:** a request interceptor attaches a fresh bearer token (from the
|
|
7
|
+
* {@link TokenManager}) to *every* request. This authenticates API modules whose spec declares no
|
|
8
|
+
* security scheme (e.g. exchange-rate), so no `accessToken` on the `Configuration` is required.
|
|
9
|
+
* - **Reactive:** a response interceptor, on a `401`, forces a token refresh and retries the request
|
|
10
|
+
* exactly once with the new bearer token.
|
|
11
|
+
*
|
|
12
|
+
* Pass it as the third argument of a generated API class:
|
|
7
13
|
*
|
|
8
14
|
* ```ts
|
|
9
15
|
* const http = createOAuthAxios(tokens);
|
|
10
|
-
* const config = new card.Configuration({
|
|
16
|
+
* const config = new card.Configuration({ basePath });
|
|
11
17
|
* const api = new card.CardApi(config, undefined, http);
|
|
12
18
|
* ```
|
|
13
19
|
*/
|
package/dist/oauth/axios.js
CHANGED
|
@@ -25,18 +25,29 @@ function stripBearer(header) {
|
|
|
25
25
|
: header;
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
|
-
* Returns an {@link AxiosInstance} with
|
|
29
|
-
*
|
|
30
|
-
*
|
|
28
|
+
* Returns an {@link AxiosInstance} with OAuth bearer-token handling built in:
|
|
29
|
+
*
|
|
30
|
+
* - **Proactive:** a request interceptor attaches a fresh bearer token (from the
|
|
31
|
+
* {@link TokenManager}) to *every* request. This authenticates API modules whose spec declares no
|
|
32
|
+
* security scheme (e.g. exchange-rate), so no `accessToken` on the `Configuration` is required.
|
|
33
|
+
* - **Reactive:** a response interceptor, on a `401`, forces a token refresh and retries the request
|
|
34
|
+
* exactly once with the new bearer token.
|
|
35
|
+
*
|
|
36
|
+
* Pass it as the third argument of a generated API class:
|
|
31
37
|
*
|
|
32
38
|
* ```ts
|
|
33
39
|
* const http = createOAuthAxios(tokens);
|
|
34
|
-
* const config = new card.Configuration({
|
|
40
|
+
* const config = new card.Configuration({ basePath });
|
|
35
41
|
* const api = new card.CardApi(config, undefined, http);
|
|
36
42
|
* ```
|
|
37
43
|
*/
|
|
38
44
|
function createOAuthAxios(manager, instance) {
|
|
39
45
|
const http = instance !== null && instance !== void 0 ? instance : axios_1.default.create();
|
|
46
|
+
// Proactive: attach a fresh bearer token to every outgoing request.
|
|
47
|
+
http.interceptors.request.use((config) => __awaiter(this, void 0, void 0, function* () {
|
|
48
|
+
config.headers.set('Authorization', BEARER_PREFIX + (yield manager.getToken()));
|
|
49
|
+
return config;
|
|
50
|
+
}));
|
|
40
51
|
http.interceptors.response.use(undefined, (error) => __awaiter(this, void 0, void 0, function* () {
|
|
41
52
|
var _a, _b, _c;
|
|
42
53
|
const response = error.response;
|
package/dist/oauth/index.js
CHANGED
|
@@ -16,10 +16,13 @@ exports.createOAuthAxios = exports.clientCredentialsFetcher = exports.clientCred
|
|
|
16
16
|
* clientSecret: 'my-secret',
|
|
17
17
|
* scopes: ['cards:read'],
|
|
18
18
|
* });
|
|
19
|
-
* const http = oauth.createOAuthAxios(tokens);
|
|
20
|
-
* const config = new card.Configuration({
|
|
19
|
+
* const http = oauth.createOAuthAxios(tokens); // attaches the token + retries on 401
|
|
20
|
+
* const config = new card.Configuration({ basePath: 'https://api.example.com' });
|
|
21
21
|
* const api = new card.CardApi(config, undefined, http);
|
|
22
22
|
*
|
|
23
|
+
* The same `http` instance authenticates every API module, including ones whose spec declares no
|
|
24
|
+
* security scheme (e.g. exchange-rate) — no `accessToken` on the `Configuration` is required.
|
|
25
|
+
*
|
|
23
26
|
* Server-side only — a client secret must never ship to a browser.
|
|
24
27
|
*/
|
|
25
28
|
var tokenManager_1 = require("./tokenManager");
|
package/package.json
CHANGED
package/src/oauth/axios.ts
CHANGED
|
@@ -19,19 +19,31 @@ function stripBearer(header: string): string {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* Returns an {@link AxiosInstance} with
|
|
23
|
-
*
|
|
24
|
-
*
|
|
22
|
+
* Returns an {@link AxiosInstance} with OAuth bearer-token handling built in:
|
|
23
|
+
*
|
|
24
|
+
* - **Proactive:** a request interceptor attaches a fresh bearer token (from the
|
|
25
|
+
* {@link TokenManager}) to *every* request. This authenticates API modules whose spec declares no
|
|
26
|
+
* security scheme (e.g. exchange-rate), so no `accessToken` on the `Configuration` is required.
|
|
27
|
+
* - **Reactive:** a response interceptor, on a `401`, forces a token refresh and retries the request
|
|
28
|
+
* exactly once with the new bearer token.
|
|
29
|
+
*
|
|
30
|
+
* Pass it as the third argument of a generated API class:
|
|
25
31
|
*
|
|
26
32
|
* ```ts
|
|
27
33
|
* const http = createOAuthAxios(tokens);
|
|
28
|
-
* const config = new card.Configuration({
|
|
34
|
+
* const config = new card.Configuration({ basePath });
|
|
29
35
|
* const api = new card.CardApi(config, undefined, http);
|
|
30
36
|
* ```
|
|
31
37
|
*/
|
|
32
38
|
export function createOAuthAxios(manager: TokenManager, instance?: AxiosInstance): AxiosInstance {
|
|
33
39
|
const http = instance ?? axios.create();
|
|
34
40
|
|
|
41
|
+
// Proactive: attach a fresh bearer token to every outgoing request.
|
|
42
|
+
http.interceptors.request.use(async (config) => {
|
|
43
|
+
config.headers.set('Authorization', BEARER_PREFIX + (await manager.getToken()));
|
|
44
|
+
return config;
|
|
45
|
+
});
|
|
46
|
+
|
|
35
47
|
http.interceptors.response.use(undefined, async (error: AxiosError) => {
|
|
36
48
|
const response = error.response;
|
|
37
49
|
const original = error.config as RetriableConfig | undefined;
|
package/src/oauth/index.ts
CHANGED
|
@@ -13,10 +13,13 @@
|
|
|
13
13
|
* clientSecret: 'my-secret',
|
|
14
14
|
* scopes: ['cards:read'],
|
|
15
15
|
* });
|
|
16
|
-
* const http = oauth.createOAuthAxios(tokens);
|
|
17
|
-
* const config = new card.Configuration({
|
|
16
|
+
* const http = oauth.createOAuthAxios(tokens); // attaches the token + retries on 401
|
|
17
|
+
* const config = new card.Configuration({ basePath: 'https://api.example.com' });
|
|
18
18
|
* const api = new card.CardApi(config, undefined, http);
|
|
19
19
|
*
|
|
20
|
+
* The same `http` instance authenticates every API module, including ones whose spec declares no
|
|
21
|
+
* security scheme (e.g. exchange-rate) — no `accessToken` on the `Configuration` is required.
|
|
22
|
+
*
|
|
20
23
|
* Server-side only — a client secret must never ship to a browser.
|
|
21
24
|
*/
|
|
22
25
|
export { AccessToken, TokenFetcher, TokenManager } from './tokenManager';
|
package/test/oauth.test.ts
CHANGED
|
@@ -139,6 +139,25 @@ describe('clientCredentialsFetcher', () => {
|
|
|
139
139
|
});
|
|
140
140
|
|
|
141
141
|
describe('createOAuthAxios', () => {
|
|
142
|
+
it('proactively attaches a bearer token to a request that has no Authorization header', async () => {
|
|
143
|
+
const { fetch, calls } = countingFetcher();
|
|
144
|
+
const mgr = new TokenManager(fetch, 60, makeClock().now);
|
|
145
|
+
|
|
146
|
+
const seenAuth: (string | undefined)[] = [];
|
|
147
|
+
const adapter: AxiosAdapter = async (config) => {
|
|
148
|
+
seenAuth.push(config.headers?.Authorization as string | undefined);
|
|
149
|
+
return { data: { ok: true }, status: 200, statusText: 'OK', headers: {}, config };
|
|
150
|
+
};
|
|
151
|
+
const http = createOAuthAxios(mgr, axios.create({ adapter }));
|
|
152
|
+
|
|
153
|
+
// No Authorization header supplied — the SDK must attach one (as for a no-security-scheme spec).
|
|
154
|
+
const response = await http.request({ url: 'http://localhost/v1/ecb/currencies', method: 'get' });
|
|
155
|
+
|
|
156
|
+
expect(response.status).toBe(200);
|
|
157
|
+
expect(seenAuth).toEqual(['Bearer token-1']);
|
|
158
|
+
expect(calls.n).toBe(1);
|
|
159
|
+
});
|
|
160
|
+
|
|
142
161
|
it('retries the request with a refreshed token when the first call rejects with 401', async () => {
|
|
143
162
|
const { fetch } = countingFetcher();
|
|
144
163
|
const mgr = new TokenManager(fetch, 60, makeClock().now);
|