commit
f1b651f5a2
8 changed files with 282 additions and 2647 deletions
|
@ -1,9 +1,9 @@
|
||||||
import axios from 'axios';
|
import axios from "axios";
|
||||||
import { LhispOauthClient } from "../src/lhisp-oauth-client";
|
import { LhispOauthClient } from "../src/lhisp-oauth-client";
|
||||||
import { ContentType, LhispOauthClientConstructorParams } from '../src/lhisp-oauth-client.t';
|
import { ContentType, LhispOauthClientConstructorParams, defaultAuthContentType } from "../src/lhisp-oauth-client.t";
|
||||||
|
|
||||||
// Mock jest and set the type
|
// Mock jest and set the type
|
||||||
jest.mock('axios');
|
jest.mock("axios");
|
||||||
const mockedAxios = axios as jest.Mocked<typeof axios>;
|
const mockedAxios = axios as jest.Mocked<typeof axios>;
|
||||||
|
|
||||||
const apiUrl = "https://myapi.com";
|
const apiUrl = "https://myapi.com";
|
||||||
|
@ -11,223 +11,243 @@ const authUrl = "https://auth.myapi.com/oauth/token";
|
||||||
const clientId = "testClientdId";
|
const clientId = "testClientdId";
|
||||||
const clientSecret = "testClientSecret";
|
const clientSecret = "testClientSecret";
|
||||||
const baseClientParams = { apiUrl, authUrl, clientId, clientSecret };
|
const baseClientParams = { apiUrl, authUrl, clientId, clientSecret };
|
||||||
const basicAuth = `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`;
|
const basicAuth = `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString("base64")}`;
|
||||||
const contentTypeApplicationJson = "application/json";
|
const contentTypeApplicationJson = ContentType.APPLICATION_JSON;
|
||||||
const contentTypeApplicationXFormUrlEncoded = "application/x-www-form-urlencoded";
|
const contentTypeApplicationXFormUrlEncoded = ContentType.APPLICATION_X_WWW_FORM_URLENCODED;
|
||||||
const defaultGrantValue='client_credentials';
|
const defaultGrantValue = "client_credentials";
|
||||||
const defaultGrantType=`{"grant_type":"${defaultGrantValue}"}`;
|
const defaultGrantType = `grant_type=${defaultGrantValue}`;
|
||||||
|
|
||||||
describe("Get Access Token", ()=>{
|
describe("Get Access Token", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mockedAxios.request.mockReset();
|
mockedAxios.request.mockReset();
|
||||||
mockedAxios.request.mockResolvedValueOnce({ data: mockedAccessToken });
|
mockedAxios.request.mockResolvedValueOnce({ data: mockedAccessToken });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Shoud Get with Standard Config", async () => {
|
||||||
|
const cli = getOauthClient();
|
||||||
|
await accessTokenValidator(cli);
|
||||||
|
validateDefaultGetAccessToken();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Shoud Get with Custom Auth Header", async () => {
|
||||||
|
const cli = getOauthClient({
|
||||||
|
...baseClientParams,
|
||||||
|
authHeaderName: "CustomAuthorizationHeader",
|
||||||
});
|
});
|
||||||
|
await accessTokenValidator(cli);
|
||||||
it("Shoud Get with Standard Config", async ()=>{
|
expect(mockedAxios.request).toBeCalledWith(
|
||||||
const cli = getOauthClient();
|
expect.objectContaining({
|
||||||
await accessTokenValidator(cli);
|
|
||||||
validateDefaultGetAccessToken();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Shoud Get with Custom Auth Header", async ()=>{
|
|
||||||
const cli = getOauthClient({
|
|
||||||
...baseClientParams,
|
|
||||||
authHeaderName: 'CustomAuthorizationHeader',
|
|
||||||
});
|
|
||||||
await accessTokenValidator(cli);
|
|
||||||
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
|
|
||||||
url: authUrl,
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
CustomAuthorizationHeader: basicAuth,
|
|
||||||
'Content-Type': contentTypeApplicationJson,
|
|
||||||
},
|
|
||||||
data: defaultGrantType,
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Shoud Get with Custom Grant Type", async ()=>{
|
|
||||||
const cli = getOauthClient({
|
|
||||||
...baseClientParams,
|
|
||||||
grantType: 'PermissaoCustom',
|
|
||||||
});
|
|
||||||
await accessTokenValidator(cli);
|
|
||||||
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
|
|
||||||
url: authUrl,
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: basicAuth,
|
|
||||||
'Content-Type': contentTypeApplicationJson,
|
|
||||||
},
|
|
||||||
data: '{"grant_type":"PermissaoCustom"}',
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Shoud Get with Custom Auth Scope", async ()=>{
|
|
||||||
const cli = getOauthClient({
|
|
||||||
...baseClientParams,
|
|
||||||
authScope: 'EscopoCustom',
|
|
||||||
});
|
|
||||||
await accessTokenValidator(cli);
|
|
||||||
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
|
|
||||||
url: authUrl,
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: basicAuth,
|
|
||||||
'Content-Type': contentTypeApplicationJson,
|
|
||||||
},
|
|
||||||
data: `{"grant_type":"${defaultGrantValue}","scope":"EscopoCustom"}`,
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Shoud Get with Credentials on Request body", async ()=>{
|
|
||||||
const cli = getOauthClient({
|
|
||||||
...baseClientParams,
|
|
||||||
sendAuthCredentialsOnRequestBody: true,
|
|
||||||
});
|
|
||||||
await accessTokenValidator(cli);
|
|
||||||
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
|
|
||||||
url: authUrl,
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: basicAuth,
|
|
||||||
'Content-Type': contentTypeApplicationJson,
|
|
||||||
},
|
|
||||||
data: `{"grant_type":"${defaultGrantValue}","client_id":"${clientId}","client_secret":"${clientSecret}"}`,
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Request", ()=>{
|
|
||||||
beforeEach(() => {
|
|
||||||
mockedAxios.request.mockReset();
|
|
||||||
mockedAxios.request.mockResolvedValueOnce({ data: mockedAccessToken });
|
|
||||||
mockedAxios.request.mockResolvedValueOnce({ data: {"status": "ok"} });
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Get without Params", async ()=>{
|
|
||||||
const cli = getOauthClient();
|
|
||||||
const resp = await cli.get({ path: '/my-test-url' });
|
|
||||||
validateDefaultGetAccessToken();
|
|
||||||
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
|
|
||||||
url: `${apiUrl}/my-test-url`,
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer SomeAccessToken`,
|
|
||||||
'Content-Type': contentTypeApplicationJson,
|
|
||||||
},
|
|
||||||
data: undefined
|
|
||||||
}));
|
|
||||||
expect(resp).toStrictEqual({"status": "ok"});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Get with Params", async ()=>{
|
|
||||||
const cli = getOauthClient();
|
|
||||||
const resp = await cli.get({ path: '/my-test-url', params: { id: 1 } });
|
|
||||||
validateDefaultGetAccessToken();
|
|
||||||
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
|
|
||||||
url: `${apiUrl}/my-test-url`,
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer SomeAccessToken`,
|
|
||||||
'Content-Type': contentTypeApplicationJson,
|
|
||||||
},
|
|
||||||
params: { id: 1 },
|
|
||||||
data: undefined
|
|
||||||
}));
|
|
||||||
expect(resp).toStrictEqual({"status": "ok"});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Post", async ()=>{
|
|
||||||
const cli = getOauthClient();
|
|
||||||
const resp = await cli.post({ path: '/my-test-url-post', data: { id: 1, user: 'test' } });
|
|
||||||
validateDefaultGetAccessToken();
|
|
||||||
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
|
|
||||||
url: `${apiUrl}/my-test-url-post`,
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer SomeAccessToken`,
|
|
||||||
'Content-Type': contentTypeApplicationJson,
|
|
||||||
},
|
|
||||||
data: { id: 1, user: 'test' }
|
|
||||||
}));
|
|
||||||
expect(resp).toStrictEqual({"status": "ok"});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Post with different contentType", async ()=>{
|
|
||||||
const cli = getOauthClient();
|
|
||||||
const resp = await cli.post({
|
|
||||||
path: '/my-test-url-post',
|
|
||||||
data: { id: 1, user: 'test' },
|
|
||||||
contentType: ContentType.APPLICATION_X_WWW_FORM_URLENCODED
|
|
||||||
});
|
|
||||||
validateDefaultGetAccessToken();
|
|
||||||
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
|
|
||||||
url: `${apiUrl}/my-test-url-post`,
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer SomeAccessToken`,
|
|
||||||
'Content-Type': contentTypeApplicationXFormUrlEncoded,
|
|
||||||
},
|
|
||||||
data: { id: 1, user: 'test' }
|
|
||||||
}));
|
|
||||||
expect(resp).toStrictEqual({"status": "ok"});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Post with Different Token Header Name", async ()=>{
|
|
||||||
const cli = getOauthClient({
|
|
||||||
...baseClientParams,
|
|
||||||
tokenHeaderName: "x-token",
|
|
||||||
});
|
|
||||||
const resp = await cli.post({
|
|
||||||
path: '/my-test-url-post',
|
|
||||||
data: { id: 1, user: 'test' },
|
|
||||||
contentType: ContentType.APPLICATION_X_WWW_FORM_URLENCODED
|
|
||||||
});
|
|
||||||
validateDefaultGetAccessToken();
|
|
||||||
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
|
|
||||||
url: `${apiUrl}/my-test-url-post`,
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
'x-token': `Bearer SomeAccessToken`,
|
|
||||||
'Content-Type': contentTypeApplicationXFormUrlEncoded,
|
|
||||||
},
|
|
||||||
data: { id: 1, user: 'test' }
|
|
||||||
}));
|
|
||||||
expect(resp).toStrictEqual({"status": "ok"});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function validateDefaultGetAccessToken(){
|
|
||||||
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
|
|
||||||
url: authUrl,
|
url: authUrl,
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: basicAuth,
|
CustomAuthorizationHeader: basicAuth,
|
||||||
'Content-Type': contentTypeApplicationJson,
|
"Content-Type": contentTypeApplicationXFormUrlEncoded,
|
||||||
},
|
},
|
||||||
data: defaultGrantType,
|
data: defaultGrantType,
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Shoud Get with Custom Grant Type", async () => {
|
||||||
|
const cli = getOauthClient({
|
||||||
|
...baseClientParams,
|
||||||
|
grantType: "PermissaoCustom",
|
||||||
|
});
|
||||||
|
await accessTokenValidator(cli);
|
||||||
|
expect(mockedAxios.request).toBeCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
url: authUrl,
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
Authorization: basicAuth,
|
||||||
|
"Content-Type": contentTypeApplicationXFormUrlEncoded,
|
||||||
|
},
|
||||||
|
data: "grant_type=PermissaoCustom",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Shoud Get with Custom Auth Scope", async () => {
|
||||||
|
const cli = getOauthClient({
|
||||||
|
...baseClientParams,
|
||||||
|
authScope: "EscopoCustom",
|
||||||
|
});
|
||||||
|
await accessTokenValidator(cli);
|
||||||
|
expect(mockedAxios.request).toBeCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
url: authUrl,
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
Authorization: basicAuth,
|
||||||
|
"Content-Type": contentTypeApplicationXFormUrlEncoded,
|
||||||
|
},
|
||||||
|
data: `grant_type=${defaultGrantValue}&scope=EscopoCustom`,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Shoud Get with Credentials on Request body", async () => {
|
||||||
|
const cli = getOauthClient({
|
||||||
|
...baseClientParams,
|
||||||
|
authContentType: contentTypeApplicationJson,
|
||||||
|
sendAuthCredentialsOnRequestBody: true,
|
||||||
|
});
|
||||||
|
await accessTokenValidator(cli);
|
||||||
|
expect(mockedAxios.request).toBeCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
url: authUrl,
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
Authorization: basicAuth,
|
||||||
|
"Content-Type": contentTypeApplicationJson,
|
||||||
|
},
|
||||||
|
data: `{"grant_type":"${defaultGrantValue}","client_id":"${clientId}","client_secret":"${clientSecret}"}`,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Request", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mockedAxios.request.mockReset();
|
||||||
|
mockedAxios.request.mockResolvedValueOnce({ data: mockedAccessToken });
|
||||||
|
mockedAxios.request.mockResolvedValueOnce({ data: { status: "ok" } });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Get without Params", async () => {
|
||||||
|
const cli = getOauthClient();
|
||||||
|
const resp = await cli.get({ path: "/my-test-url" });
|
||||||
|
validateDefaultGetAccessToken();
|
||||||
|
expect(mockedAxios.request).toBeCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
url: `${apiUrl}/my-test-url`,
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer SomeAccessToken`,
|
||||||
|
"Content-Type": contentTypeApplicationJson,
|
||||||
|
},
|
||||||
|
data: undefined,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
expect(resp).toStrictEqual({ status: "ok" });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Get with Params", async () => {
|
||||||
|
const cli = getOauthClient();
|
||||||
|
const resp = await cli.get({ path: "/my-test-url", params: { id: 1 } });
|
||||||
|
validateDefaultGetAccessToken();
|
||||||
|
expect(mockedAxios.request).toBeCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
url: `${apiUrl}/my-test-url`,
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer SomeAccessToken`,
|
||||||
|
"Content-Type": contentTypeApplicationJson,
|
||||||
|
},
|
||||||
|
params: { id: 1 },
|
||||||
|
data: undefined,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
expect(resp).toStrictEqual({ status: "ok" });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Post", async () => {
|
||||||
|
const cli = getOauthClient();
|
||||||
|
const resp = await cli.post({ path: "/my-test-url-post", data: { id: 1, user: "test" } });
|
||||||
|
validateDefaultGetAccessToken();
|
||||||
|
expect(mockedAxios.request).toBeCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
url: `${apiUrl}/my-test-url-post`,
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer SomeAccessToken`,
|
||||||
|
"Content-Type": contentTypeApplicationJson,
|
||||||
|
},
|
||||||
|
data: { id: 1, user: "test" },
|
||||||
|
})
|
||||||
|
);
|
||||||
|
expect(resp).toStrictEqual({ status: "ok" });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Post with different contentType", async () => {
|
||||||
|
const cli = getOauthClient();
|
||||||
|
const resp = await cli.post({
|
||||||
|
path: "/my-test-url-post",
|
||||||
|
data: { id: 1, user: "test" },
|
||||||
|
contentType: ContentType.APPLICATION_X_WWW_FORM_URLENCODED,
|
||||||
|
});
|
||||||
|
validateDefaultGetAccessToken();
|
||||||
|
expect(mockedAxios.request).toBeCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
url: `${apiUrl}/my-test-url-post`,
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer SomeAccessToken`,
|
||||||
|
"Content-Type": contentTypeApplicationXFormUrlEncoded,
|
||||||
|
},
|
||||||
|
data: { id: 1, user: "test" },
|
||||||
|
})
|
||||||
|
);
|
||||||
|
expect(resp).toStrictEqual({ status: "ok" });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Post with Different Token Header Name", async () => {
|
||||||
|
const cli = getOauthClient({
|
||||||
|
...baseClientParams,
|
||||||
|
tokenHeaderName: "x-token",
|
||||||
|
});
|
||||||
|
const resp = await cli.post({
|
||||||
|
path: "/my-test-url-post",
|
||||||
|
data: { id: 1, user: "test" },
|
||||||
|
contentType: ContentType.APPLICATION_X_WWW_FORM_URLENCODED,
|
||||||
|
});
|
||||||
|
validateDefaultGetAccessToken();
|
||||||
|
expect(mockedAxios.request).toBeCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
url: `${apiUrl}/my-test-url-post`,
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"x-token": `Bearer SomeAccessToken`,
|
||||||
|
"Content-Type": contentTypeApplicationXFormUrlEncoded,
|
||||||
|
},
|
||||||
|
data: { id: 1, user: "test" },
|
||||||
|
})
|
||||||
|
);
|
||||||
|
expect(resp).toStrictEqual({ status: "ok" });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function validateDefaultGetAccessToken() {
|
||||||
|
expect(mockedAxios.request).toBeCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
url: authUrl,
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
Authorization: basicAuth,
|
||||||
|
"Content-Type": contentTypeApplicationXFormUrlEncoded,
|
||||||
|
},
|
||||||
|
data: defaultGrantType,
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function accessTokenValidator(cli: LhispOauthClient){
|
async function accessTokenValidator(cli: LhispOauthClient) {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const accessToken = await cli.getAccessToken();
|
const accessToken = await cli.getAccessToken();
|
||||||
expect(accessToken).toBeDefined();
|
expect(accessToken).toBeDefined();
|
||||||
expect(accessToken.token_type).toBe(mockedAccessToken.token_type);
|
expect(accessToken.token_type).toBe(mockedAccessToken.token_type);
|
||||||
expect(accessToken.access_token).toBe(mockedAccessToken.access_token);
|
expect(accessToken.access_token).toBe(mockedAccessToken.access_token);
|
||||||
expect(accessToken.expires_in).toBe(mockedAccessToken.expires_in);
|
expect(accessToken.expires_in).toBe(mockedAccessToken.expires_in);
|
||||||
expect(accessToken.scope).toBe(mockedAccessToken.scope);
|
expect(accessToken.scope).toBe(mockedAccessToken.scope);
|
||||||
expect(accessToken.created_at).toBeGreaterThanOrEqual(now);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getOauthClient(opt:LhispOauthClientConstructorParams=baseClientParams){
|
function getOauthClient(opt: LhispOauthClientConstructorParams = baseClientParams) {
|
||||||
return new LhispOauthClient(opt);
|
return new LhispOauthClient(opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
const mockedAccessToken = {
|
const mockedAccessToken = {
|
||||||
token_type: "Bearer",
|
token_type: "Bearer",
|
||||||
access_token: "SomeAccessToken",
|
access_token: "SomeAccessToken",
|
||||||
expires_in: 600,
|
expires_in: 600,
|
||||||
scope: "cobrancas.boletos-requisicao cobrancas.boletos-info",
|
scope: "cobrancas.boletos-requisicao cobrancas.boletos-info",
|
||||||
}
|
};
|
||||||
|
|
|
@ -6,8 +6,9 @@ definitions:
|
||||||
caches:
|
caches:
|
||||||
- node
|
- node
|
||||||
script:
|
script:
|
||||||
- yarn install
|
- npm install
|
||||||
- yarn build
|
- npm run test
|
||||||
|
- npm run build
|
||||||
artifacts:
|
artifacts:
|
||||||
- dist/**
|
- dist/**
|
||||||
pipelines:
|
pipelines:
|
||||||
|
|
4
package-lock.json
generated
4
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "lhisp-oauth-client",
|
"name": "lhisp-oauth-client",
|
||||||
"version": "1.0.11",
|
"version": "1.0.13",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "lhisp-oauth-client",
|
"name": "lhisp-oauth-client",
|
||||||
"version": "1.0.11",
|
"version": "1.0.13",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.4.0",
|
"axios": "^1.4.0",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "lhisp-oauth-client",
|
"name": "lhisp-oauth-client",
|
||||||
"version": "1.0.11",
|
"version": "1.0.13",
|
||||||
"main": "src/index",
|
"main": "src/index",
|
||||||
"types": "src/index.d.ts",
|
"types": "src/index.d.ts",
|
||||||
"repository": "git@bitbucket.org:leandro_costa/lhisp-oauth-client.git",
|
"repository": "git@bitbucket.org:leandro_costa/lhisp-oauth-client.git",
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
export * from './lhisp-oauth-client';
|
export * from "./lhisp-oauth-client";
|
||||||
export * from './lhisp-oauth-client.t';
|
export * from "./lhisp-oauth-client.t";
|
||||||
|
|
|
@ -1,45 +1,44 @@
|
||||||
import { AxiosRequestConfig } from "axios";
|
import { AxiosRequestConfig } from "axios";
|
||||||
|
|
||||||
export interface Headers {
|
export interface Headers {
|
||||||
[name: string]: any;
|
[name: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LhispOauthClientConstructorParams {
|
export interface LhispOauthClientConstructorParams {
|
||||||
authUrl: string;
|
authUrl: string;
|
||||||
apiUrl: string;
|
apiUrl: string;
|
||||||
clientId: string;
|
clientId: string;
|
||||||
clientSecret: string;
|
clientSecret: string;
|
||||||
certificado?: string;
|
certificado?: string;
|
||||||
senhaCertificado?: string;
|
senhaCertificado?: string;
|
||||||
authScope?: string;
|
authScope?: string;
|
||||||
authHeaderName?: string;
|
authHeaderName?: string;
|
||||||
tokenHeaderName?: string;
|
tokenHeaderName?: string;
|
||||||
headers?: Headers;
|
headers?: Headers;
|
||||||
grantType?: string;
|
grantType?: string;
|
||||||
authContentType?: ContentType;
|
authContentType?: ContentType;
|
||||||
sendAuthCredentialsOnRequestBody?: boolean;
|
sendAuthCredentialsOnRequestBody?: boolean;
|
||||||
debug?: boolean;
|
debug?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExecutarRequestParams extends AxiosRequestConfig {
|
export interface ExecutarRequestParams extends AxiosRequestConfig {
|
||||||
path: string;
|
path: string;
|
||||||
contentType?: ContentType,
|
contentType?: ContentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AccessToken {
|
export interface AccessToken {
|
||||||
token_type: string;
|
token_type: string;
|
||||||
access_token: string;
|
access_token: string;
|
||||||
expires_in: number;
|
expires_in: number;
|
||||||
scope?: string;
|
scope?: string;
|
||||||
created_at?: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ContentType {
|
export enum ContentType {
|
||||||
APPLICATION_JSON='application/json',
|
APPLICATION_JSON = "application/json",
|
||||||
APPLICATION_X_WWW_FORM_URLENCODED='application/x-www-form-urlencoded',
|
APPLICATION_X_WWW_FORM_URLENCODED = "application/x-www-form-urlencoded",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaultGrantType = 'client_credentials';
|
export const defaultGrantType = "client_credentials";
|
||||||
export const defaultAuthContentType = ContentType.APPLICATION_X_WWW_FORM_URLENCODED;
|
export const defaultAuthContentType = ContentType.APPLICATION_X_WWW_FORM_URLENCODED;
|
||||||
export const defaultAuthHeaderName = 'Authorization';
|
export const defaultAuthHeaderName = "Authorization";
|
||||||
export const defaultTokenHeaderName = 'Authorization';
|
export const defaultTokenHeaderName = "Authorization";
|
||||||
|
|
|
@ -13,7 +13,7 @@ import {
|
||||||
} from "./lhisp-oauth-client.t";
|
} from "./lhisp-oauth-client.t";
|
||||||
import logger from "lhisp-logger";
|
import logger from "lhisp-logger";
|
||||||
|
|
||||||
export class LhispOauthClient {
|
export class LhispOauthClient<iAccessToken extends AccessToken = AccessToken> {
|
||||||
protected authUrl: string;
|
protected authUrl: string;
|
||||||
protected apiUrl: string;
|
protected apiUrl: string;
|
||||||
protected clientId: string;
|
protected clientId: string;
|
||||||
|
@ -27,8 +27,10 @@ export class LhispOauthClient {
|
||||||
protected headers?: Headers;
|
protected headers?: Headers;
|
||||||
protected grantType?: string;
|
protected grantType?: string;
|
||||||
protected agent: https.Agent;
|
protected agent: https.Agent;
|
||||||
protected accessToken?: AccessToken;
|
protected accessToken?: iAccessToken;
|
||||||
protected refreshToken?: AccessToken;
|
protected refreshToken?: iAccessToken;
|
||||||
|
protected tokenCreatedAt = 0;
|
||||||
|
protected tokenExpiresIn = 0;
|
||||||
protected sendAuthCredentialsOnRequestBody?: boolean;
|
protected sendAuthCredentialsOnRequestBody?: boolean;
|
||||||
|
|
||||||
constructor(params: LhispOauthClientConstructorParams) {
|
constructor(params: LhispOauthClientConstructorParams) {
|
||||||
|
@ -75,16 +77,16 @@ export class LhispOauthClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isTokenValid(token: AccessToken) {
|
isTokenValid() {
|
||||||
if (!token) return false;
|
if (!this.accessToken) return false;
|
||||||
if (!token.created_at) return false;
|
if (!this.tokenCreatedAt) return false;
|
||||||
const timeDiff = (Date.now() - token.created_at) / 1000;
|
const timeDiff = (Date.now() - this.tokenCreatedAt) / 1000;
|
||||||
return timeDiff < token.expires_in - 10;
|
return timeDiff < this.tokenExpiresIn - 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAccessToken(): Promise<AccessToken> {
|
async getAccessToken(): Promise<iAccessToken> {
|
||||||
try {
|
try {
|
||||||
if (this.accessToken && this.isTokenValid(this.accessToken)) {
|
if (this.accessToken && this.isTokenValid()) {
|
||||||
return this.accessToken;
|
return this.accessToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,21 +115,19 @@ export class LhispOauthClient {
|
||||||
data: authRequestOpt.data,
|
data: authRequestOpt.data,
|
||||||
contentType: this.authContentType,
|
contentType: this.authContentType,
|
||||||
});
|
});
|
||||||
const response = await axios.request(authRequestOpt);
|
const resp = await axios.request(authRequestOpt);
|
||||||
return this.buildAccessToken(response.data);
|
this.accessToken = this.buildAccessToken(resp.data);
|
||||||
|
this.tokenCreatedAt = new Date().getTime();
|
||||||
|
this.tokenExpiresIn = this.accessToken?.expires_in || this.tokenCreatedAt + 60000;
|
||||||
|
return this.accessToken;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error({ message: "LhispOauthClient.getAccessToken", error });
|
logger.error({ message: "LhispOauthClient.getAccessToken", error });
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buildAccessToken(data: Omit<AccessToken, "created_at">): AccessToken {
|
buildAccessToken(data: any) {
|
||||||
this.accessToken = {
|
return data as iAccessToken;
|
||||||
...data,
|
|
||||||
created_at: Date.now(),
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.accessToken;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getAuthToken() {
|
getAuthToken() {
|
||||||
|
@ -143,14 +143,10 @@ export class LhispOauthClient {
|
||||||
}: ExecutarRequestParams): Promise<ResponseType> {
|
}: ExecutarRequestParams): Promise<ResponseType> {
|
||||||
try {
|
try {
|
||||||
await this.getAccessToken();
|
await this.getAccessToken();
|
||||||
if (!this.accessToken?.token_type) {
|
|
||||||
console.log("## LHOAUTH2 NO TOKEN ?:", this.accessToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
let headers = {
|
let headers = {
|
||||||
"Content-Type": contentType,
|
"Content-Type": contentType,
|
||||||
[this.tokenHeaderName]: this.getAuthToken(),
|
[this.tokenHeaderName]: this.getAuthToken(),
|
||||||
// ...this.headers
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await axios.request<ResponseType>({
|
const response = await axios.request<ResponseType>({
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue