lhisp-oauth-client 1.0.10 → 1.0.13
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.
|
@@ -16,18 +16,18 @@ const axios_1 = __importDefault(require("axios"));
|
|
|
16
16
|
const lhisp_oauth_client_1 = require("../src/lhisp-oauth-client");
|
|
17
17
|
const lhisp_oauth_client_t_1 = require("../src/lhisp-oauth-client.t");
|
|
18
18
|
// Mock jest and set the type
|
|
19
|
-
jest.mock(
|
|
19
|
+
jest.mock("axios");
|
|
20
20
|
const mockedAxios = axios_1.default;
|
|
21
21
|
const apiUrl = "https://myapi.com";
|
|
22
22
|
const authUrl = "https://auth.myapi.com/oauth/token";
|
|
23
23
|
const clientId = "testClientdId";
|
|
24
24
|
const clientSecret = "testClientSecret";
|
|
25
25
|
const baseClientParams = { apiUrl, authUrl, clientId, clientSecret };
|
|
26
|
-
const basicAuth = `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString(
|
|
27
|
-
const contentTypeApplicationJson =
|
|
28
|
-
const contentTypeApplicationXFormUrlEncoded =
|
|
29
|
-
const defaultGrantValue =
|
|
30
|
-
const defaultGrantType = `
|
|
26
|
+
const basicAuth = `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString("base64")}`;
|
|
27
|
+
const contentTypeApplicationJson = lhisp_oauth_client_t_1.ContentType.APPLICATION_JSON;
|
|
28
|
+
const contentTypeApplicationXFormUrlEncoded = lhisp_oauth_client_t_1.ContentType.APPLICATION_X_WWW_FORM_URLENCODED;
|
|
29
|
+
const defaultGrantValue = "client_credentials";
|
|
30
|
+
const defaultGrantType = `grant_type=${defaultGrantValue}`;
|
|
31
31
|
describe("Get Access Token", () => {
|
|
32
32
|
beforeEach(() => {
|
|
33
33
|
mockedAxios.request.mockReset();
|
|
@@ -39,53 +39,53 @@ describe("Get Access Token", () => {
|
|
|
39
39
|
validateDefaultGetAccessToken();
|
|
40
40
|
}));
|
|
41
41
|
it("Shoud Get with Custom Auth Header", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
42
|
-
const cli = getOauthClient(Object.assign(Object.assign({}, baseClientParams), { authHeaderName:
|
|
42
|
+
const cli = getOauthClient(Object.assign(Object.assign({}, baseClientParams), { authHeaderName: "CustomAuthorizationHeader" }));
|
|
43
43
|
yield accessTokenValidator(cli);
|
|
44
44
|
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
|
|
45
45
|
url: authUrl,
|
|
46
46
|
method: "POST",
|
|
47
47
|
headers: {
|
|
48
48
|
CustomAuthorizationHeader: basicAuth,
|
|
49
|
-
|
|
49
|
+
"Content-Type": contentTypeApplicationXFormUrlEncoded,
|
|
50
50
|
},
|
|
51
51
|
data: defaultGrantType,
|
|
52
52
|
}));
|
|
53
53
|
}));
|
|
54
54
|
it("Shoud Get with Custom Grant Type", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
55
|
-
const cli = getOauthClient(Object.assign(Object.assign({}, baseClientParams), { grantType:
|
|
55
|
+
const cli = getOauthClient(Object.assign(Object.assign({}, baseClientParams), { grantType: "PermissaoCustom" }));
|
|
56
56
|
yield accessTokenValidator(cli);
|
|
57
57
|
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
|
|
58
58
|
url: authUrl,
|
|
59
59
|
method: "POST",
|
|
60
60
|
headers: {
|
|
61
61
|
Authorization: basicAuth,
|
|
62
|
-
|
|
62
|
+
"Content-Type": contentTypeApplicationXFormUrlEncoded,
|
|
63
63
|
},
|
|
64
|
-
data:
|
|
64
|
+
data: "grant_type=PermissaoCustom",
|
|
65
65
|
}));
|
|
66
66
|
}));
|
|
67
67
|
it("Shoud Get with Custom Auth Scope", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
68
|
-
const cli = getOauthClient(Object.assign(Object.assign({}, baseClientParams), { authScope:
|
|
68
|
+
const cli = getOauthClient(Object.assign(Object.assign({}, baseClientParams), { authScope: "EscopoCustom" }));
|
|
69
69
|
yield accessTokenValidator(cli);
|
|
70
70
|
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
|
|
71
71
|
url: authUrl,
|
|
72
72
|
method: "POST",
|
|
73
73
|
headers: {
|
|
74
74
|
Authorization: basicAuth,
|
|
75
|
-
|
|
75
|
+
"Content-Type": contentTypeApplicationXFormUrlEncoded,
|
|
76
76
|
},
|
|
77
|
-
data: `
|
|
77
|
+
data: `grant_type=${defaultGrantValue}&scope=EscopoCustom`,
|
|
78
78
|
}));
|
|
79
79
|
}));
|
|
80
80
|
it("Shoud Get with Credentials on Request body", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
81
|
-
const cli = getOauthClient(Object.assign(Object.assign({}, baseClientParams), { sendAuthCredentialsOnRequestBody: true }));
|
|
81
|
+
const cli = getOauthClient(Object.assign(Object.assign({}, baseClientParams), { authContentType: contentTypeApplicationJson, sendAuthCredentialsOnRequestBody: true }));
|
|
82
82
|
yield accessTokenValidator(cli);
|
|
83
83
|
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
|
|
84
84
|
url: authUrl,
|
|
85
85
|
method: "POST",
|
|
86
86
|
headers: {
|
|
87
87
|
Authorization: basicAuth,
|
|
88
|
-
|
|
88
|
+
"Content-Type": contentTypeApplicationJson,
|
|
89
89
|
},
|
|
90
90
|
data: `{"grant_type":"${defaultGrantValue}","client_id":"${clientId}","client_secret":"${clientSecret}"}`,
|
|
91
91
|
}));
|
|
@@ -95,60 +95,60 @@ describe("Request", () => {
|
|
|
95
95
|
beforeEach(() => {
|
|
96
96
|
mockedAxios.request.mockReset();
|
|
97
97
|
mockedAxios.request.mockResolvedValueOnce({ data: mockedAccessToken });
|
|
98
|
-
mockedAxios.request.mockResolvedValueOnce({ data: {
|
|
98
|
+
mockedAxios.request.mockResolvedValueOnce({ data: { status: "ok" } });
|
|
99
99
|
});
|
|
100
100
|
it("Get without Params", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
101
101
|
const cli = getOauthClient();
|
|
102
|
-
const resp = yield cli.get({ path:
|
|
102
|
+
const resp = yield cli.get({ path: "/my-test-url" });
|
|
103
103
|
validateDefaultGetAccessToken();
|
|
104
104
|
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
|
|
105
105
|
url: `${apiUrl}/my-test-url`,
|
|
106
106
|
method: "GET",
|
|
107
107
|
headers: {
|
|
108
108
|
Authorization: `Bearer SomeAccessToken`,
|
|
109
|
-
|
|
109
|
+
"Content-Type": contentTypeApplicationJson,
|
|
110
110
|
},
|
|
111
|
-
data: undefined
|
|
111
|
+
data: undefined,
|
|
112
112
|
}));
|
|
113
|
-
expect(resp).toStrictEqual({
|
|
113
|
+
expect(resp).toStrictEqual({ status: "ok" });
|
|
114
114
|
}));
|
|
115
115
|
it("Get with Params", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
116
116
|
const cli = getOauthClient();
|
|
117
|
-
const resp = yield cli.get({ path:
|
|
117
|
+
const resp = yield cli.get({ path: "/my-test-url", params: { id: 1 } });
|
|
118
118
|
validateDefaultGetAccessToken();
|
|
119
119
|
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
|
|
120
120
|
url: `${apiUrl}/my-test-url`,
|
|
121
121
|
method: "GET",
|
|
122
122
|
headers: {
|
|
123
123
|
Authorization: `Bearer SomeAccessToken`,
|
|
124
|
-
|
|
124
|
+
"Content-Type": contentTypeApplicationJson,
|
|
125
125
|
},
|
|
126
126
|
params: { id: 1 },
|
|
127
|
-
data: undefined
|
|
127
|
+
data: undefined,
|
|
128
128
|
}));
|
|
129
|
-
expect(resp).toStrictEqual({
|
|
129
|
+
expect(resp).toStrictEqual({ status: "ok" });
|
|
130
130
|
}));
|
|
131
131
|
it("Post", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
132
132
|
const cli = getOauthClient();
|
|
133
|
-
const resp = yield cli.post({ path:
|
|
133
|
+
const resp = yield cli.post({ path: "/my-test-url-post", data: { id: 1, user: "test" } });
|
|
134
134
|
validateDefaultGetAccessToken();
|
|
135
135
|
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
|
|
136
136
|
url: `${apiUrl}/my-test-url-post`,
|
|
137
137
|
method: "POST",
|
|
138
138
|
headers: {
|
|
139
139
|
Authorization: `Bearer SomeAccessToken`,
|
|
140
|
-
|
|
140
|
+
"Content-Type": contentTypeApplicationJson,
|
|
141
141
|
},
|
|
142
|
-
data: { id: 1, user:
|
|
142
|
+
data: { id: 1, user: "test" },
|
|
143
143
|
}));
|
|
144
|
-
expect(resp).toStrictEqual({
|
|
144
|
+
expect(resp).toStrictEqual({ status: "ok" });
|
|
145
145
|
}));
|
|
146
146
|
it("Post with different contentType", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
147
147
|
const cli = getOauthClient();
|
|
148
148
|
const resp = yield cli.post({
|
|
149
|
-
path:
|
|
150
|
-
data: { id: 1, user:
|
|
151
|
-
contentType: lhisp_oauth_client_t_1.ContentType.APPLICATION_X_WWW_FORM_URLENCODED
|
|
149
|
+
path: "/my-test-url-post",
|
|
150
|
+
data: { id: 1, user: "test" },
|
|
151
|
+
contentType: lhisp_oauth_client_t_1.ContentType.APPLICATION_X_WWW_FORM_URLENCODED,
|
|
152
152
|
});
|
|
153
153
|
validateDefaultGetAccessToken();
|
|
154
154
|
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
|
|
@@ -156,30 +156,30 @@ describe("Request", () => {
|
|
|
156
156
|
method: "POST",
|
|
157
157
|
headers: {
|
|
158
158
|
Authorization: `Bearer SomeAccessToken`,
|
|
159
|
-
|
|
159
|
+
"Content-Type": contentTypeApplicationXFormUrlEncoded,
|
|
160
160
|
},
|
|
161
|
-
data: { id: 1, user:
|
|
161
|
+
data: { id: 1, user: "test" },
|
|
162
162
|
}));
|
|
163
|
-
expect(resp).toStrictEqual({
|
|
163
|
+
expect(resp).toStrictEqual({ status: "ok" });
|
|
164
164
|
}));
|
|
165
165
|
it("Post with Different Token Header Name", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
166
166
|
const cli = getOauthClient(Object.assign(Object.assign({}, baseClientParams), { tokenHeaderName: "x-token" }));
|
|
167
167
|
const resp = yield cli.post({
|
|
168
|
-
path:
|
|
169
|
-
data: { id: 1, user:
|
|
170
|
-
contentType: lhisp_oauth_client_t_1.ContentType.APPLICATION_X_WWW_FORM_URLENCODED
|
|
168
|
+
path: "/my-test-url-post",
|
|
169
|
+
data: { id: 1, user: "test" },
|
|
170
|
+
contentType: lhisp_oauth_client_t_1.ContentType.APPLICATION_X_WWW_FORM_URLENCODED,
|
|
171
171
|
});
|
|
172
172
|
validateDefaultGetAccessToken();
|
|
173
173
|
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
|
|
174
174
|
url: `${apiUrl}/my-test-url-post`,
|
|
175
175
|
method: "POST",
|
|
176
176
|
headers: {
|
|
177
|
-
|
|
178
|
-
|
|
177
|
+
"x-token": `Bearer SomeAccessToken`,
|
|
178
|
+
"Content-Type": contentTypeApplicationXFormUrlEncoded,
|
|
179
179
|
},
|
|
180
|
-
data: { id: 1, user:
|
|
180
|
+
data: { id: 1, user: "test" },
|
|
181
181
|
}));
|
|
182
|
-
expect(resp).toStrictEqual({
|
|
182
|
+
expect(resp).toStrictEqual({ status: "ok" });
|
|
183
183
|
}));
|
|
184
184
|
});
|
|
185
185
|
function validateDefaultGetAccessToken() {
|
|
@@ -188,7 +188,7 @@ function validateDefaultGetAccessToken() {
|
|
|
188
188
|
method: "POST",
|
|
189
189
|
headers: {
|
|
190
190
|
Authorization: basicAuth,
|
|
191
|
-
|
|
191
|
+
"Content-Type": contentTypeApplicationXFormUrlEncoded,
|
|
192
192
|
},
|
|
193
193
|
data: defaultGrantType,
|
|
194
194
|
}));
|
|
@@ -202,7 +202,6 @@ function accessTokenValidator(cli) {
|
|
|
202
202
|
expect(accessToken.access_token).toBe(mockedAccessToken.access_token);
|
|
203
203
|
expect(accessToken.expires_in).toBe(mockedAccessToken.expires_in);
|
|
204
204
|
expect(accessToken.scope).toBe(mockedAccessToken.scope);
|
|
205
|
-
expect(accessToken.created_at).toBeGreaterThanOrEqual(now);
|
|
206
205
|
});
|
|
207
206
|
}
|
|
208
207
|
function getOauthClient(opt = baseClientParams) {
|
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
1
|
+
export * from "./lhisp-oauth-client";
|
|
2
|
+
export * from "./lhisp-oauth-client.t";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import https from "https";
|
|
3
3
|
import { AccessToken, ContentType, ExecutarRequestParams, LhispOauthClientConstructorParams } from "./lhisp-oauth-client.t";
|
|
4
|
-
export declare class LhispOauthClient {
|
|
4
|
+
export declare class LhispOauthClient<iAccessToken extends AccessToken = AccessToken> {
|
|
5
5
|
protected authUrl: string;
|
|
6
6
|
protected apiUrl: string;
|
|
7
7
|
protected clientId: string;
|
|
@@ -15,8 +15,10 @@ export declare class LhispOauthClient {
|
|
|
15
15
|
protected headers?: Headers;
|
|
16
16
|
protected grantType?: string;
|
|
17
17
|
protected agent: https.Agent;
|
|
18
|
-
protected accessToken?:
|
|
19
|
-
protected refreshToken?:
|
|
18
|
+
protected accessToken?: iAccessToken;
|
|
19
|
+
protected refreshToken?: iAccessToken;
|
|
20
|
+
protected tokenCreatedAt: number;
|
|
21
|
+
protected tokenExpiresIn: number;
|
|
20
22
|
protected sendAuthCredentialsOnRequestBody?: boolean;
|
|
21
23
|
constructor(params: LhispOauthClientConstructorParams);
|
|
22
24
|
getAuthHeaderValue(): string;
|
|
@@ -24,9 +26,9 @@ export declare class LhispOauthClient {
|
|
|
24
26
|
data: any;
|
|
25
27
|
contentType: string;
|
|
26
28
|
}): string | undefined;
|
|
27
|
-
isTokenValid(
|
|
28
|
-
getAccessToken(): Promise<
|
|
29
|
-
buildAccessToken(data:
|
|
29
|
+
isTokenValid(): boolean;
|
|
30
|
+
getAccessToken(): Promise<iAccessToken>;
|
|
31
|
+
buildAccessToken(data: any): iAccessToken;
|
|
30
32
|
getAuthToken(): string;
|
|
31
33
|
executarRequest<ResponseType>({ method, path, data, params, contentType, }: ExecutarRequestParams): Promise<ResponseType>;
|
|
32
34
|
get<ResponseType>({ path, contentType, params }: ExecutarRequestParams): Promise<ResponseType>;
|
|
@@ -20,6 +20,8 @@ const lhisp_oauth_client_t_1 = require("./lhisp-oauth-client.t");
|
|
|
20
20
|
const lhisp_logger_1 = __importDefault(require("lhisp-logger"));
|
|
21
21
|
class LhispOauthClient {
|
|
22
22
|
constructor(params) {
|
|
23
|
+
this.tokenCreatedAt = 0;
|
|
24
|
+
this.tokenExpiresIn = 0;
|
|
23
25
|
if (params.certificado) {
|
|
24
26
|
this.agent = new https_1.default.Agent({
|
|
25
27
|
pfx: params.certificado,
|
|
@@ -60,18 +62,19 @@ class LhispOauthClient {
|
|
|
60
62
|
throw new Error(`Content Type Inválido: [${contentType}]`);
|
|
61
63
|
}
|
|
62
64
|
}
|
|
63
|
-
isTokenValid(
|
|
64
|
-
if (!
|
|
65
|
+
isTokenValid() {
|
|
66
|
+
if (!this.accessToken)
|
|
65
67
|
return false;
|
|
66
|
-
if (!
|
|
68
|
+
if (!this.tokenCreatedAt)
|
|
67
69
|
return false;
|
|
68
|
-
const timeDiff = (Date.now() -
|
|
69
|
-
return timeDiff <
|
|
70
|
+
const timeDiff = (Date.now() - this.tokenCreatedAt) / 1000;
|
|
71
|
+
return timeDiff < this.tokenExpiresIn - 10;
|
|
70
72
|
}
|
|
71
73
|
getAccessToken() {
|
|
74
|
+
var _a;
|
|
72
75
|
return __awaiter(this, void 0, void 0, function* () {
|
|
73
76
|
try {
|
|
74
|
-
if (this.accessToken && this.isTokenValid(
|
|
77
|
+
if (this.accessToken && this.isTokenValid()) {
|
|
75
78
|
return this.accessToken;
|
|
76
79
|
}
|
|
77
80
|
// TODO: Implementar Refresh Token.
|
|
@@ -99,8 +102,11 @@ class LhispOauthClient {
|
|
|
99
102
|
data: authRequestOpt.data,
|
|
100
103
|
contentType: this.authContentType,
|
|
101
104
|
});
|
|
102
|
-
const
|
|
103
|
-
|
|
105
|
+
const resp = yield axios_1.default.request(authRequestOpt);
|
|
106
|
+
this.accessToken = this.buildAccessToken(resp.data);
|
|
107
|
+
this.tokenCreatedAt = new Date().getTime();
|
|
108
|
+
this.tokenExpiresIn = ((_a = this.accessToken) === null || _a === void 0 ? void 0 : _a.expires_in) || this.tokenCreatedAt + 60000;
|
|
109
|
+
return this.accessToken;
|
|
104
110
|
}
|
|
105
111
|
catch (error) {
|
|
106
112
|
lhisp_logger_1.default.error({ message: "LhispOauthClient.getAccessToken", error });
|
|
@@ -109,25 +115,19 @@ class LhispOauthClient {
|
|
|
109
115
|
});
|
|
110
116
|
}
|
|
111
117
|
buildAccessToken(data) {
|
|
112
|
-
|
|
113
|
-
return this.accessToken;
|
|
118
|
+
return data;
|
|
114
119
|
}
|
|
115
120
|
getAuthToken() {
|
|
116
121
|
var _a, _b;
|
|
117
122
|
return `${(_a = this.accessToken) === null || _a === void 0 ? void 0 : _a.token_type} ${(_b = this.accessToken) === null || _b === void 0 ? void 0 : _b.access_token}`;
|
|
118
123
|
}
|
|
119
124
|
executarRequest({ method, path, data, params, contentType = lhisp_oauth_client_t_1.ContentType.APPLICATION_JSON, }) {
|
|
120
|
-
var _a;
|
|
121
125
|
return __awaiter(this, void 0, void 0, function* () {
|
|
122
126
|
try {
|
|
123
127
|
yield this.getAccessToken();
|
|
124
|
-
if (!((_a = this.accessToken) === null || _a === void 0 ? void 0 : _a.token_type)) {
|
|
125
|
-
console.log("## LHOAUTH2 NO TOKEN ?:", this.accessToken);
|
|
126
|
-
}
|
|
127
128
|
let headers = {
|
|
128
129
|
"Content-Type": contentType,
|
|
129
130
|
[this.tokenHeaderName]: this.getAuthToken(),
|
|
130
|
-
// ...this.headers
|
|
131
131
|
};
|
|
132
132
|
const response = yield axios_1.default.request({
|
|
133
133
|
method,
|
|
@@ -140,7 +140,15 @@ class LhispOauthClient {
|
|
|
140
140
|
return response.data;
|
|
141
141
|
}
|
|
142
142
|
catch (error) {
|
|
143
|
-
lhisp_logger_1.default.error({
|
|
143
|
+
lhisp_logger_1.default.error({
|
|
144
|
+
message: "LhispOauthClient.executarRequest",
|
|
145
|
+
method,
|
|
146
|
+
url: `${this.apiUrl}${path}`,
|
|
147
|
+
data,
|
|
148
|
+
params,
|
|
149
|
+
contentType,
|
|
150
|
+
error,
|
|
151
|
+
});
|
|
144
152
|
throw error;
|
|
145
153
|
}
|
|
146
154
|
});
|
|
@@ -6,7 +6,7 @@ var ContentType;
|
|
|
6
6
|
ContentType["APPLICATION_JSON"] = "application/json";
|
|
7
7
|
ContentType["APPLICATION_X_WWW_FORM_URLENCODED"] = "application/x-www-form-urlencoded";
|
|
8
8
|
})(ContentType || (exports.ContentType = ContentType = {}));
|
|
9
|
-
exports.defaultGrantType =
|
|
9
|
+
exports.defaultGrantType = "client_credentials";
|
|
10
10
|
exports.defaultAuthContentType = ContentType.APPLICATION_X_WWW_FORM_URLENCODED;
|
|
11
|
-
exports.defaultAuthHeaderName =
|
|
12
|
-
exports.defaultTokenHeaderName =
|
|
11
|
+
exports.defaultAuthHeaderName = "Authorization";
|
|
12
|
+
exports.defaultTokenHeaderName = "Authorization";
|