Initial commit
This commit is contained in:
parent
ec65720e99
commit
53c3fbffe6
8 changed files with 2604 additions and 0 deletions
2
src/index.js
Normal file
2
src/index.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
export * from './lhisp-oauth-client';
|
||||
export * from './lhisp-oauth-client.t';
|
46
src/lhisp-oauth-client.t.ts
Normal file
46
src/lhisp-oauth-client.t.ts
Normal file
|
@ -0,0 +1,46 @@
|
|||
import { AxiosRequestConfig } from "axios";
|
||||
|
||||
export interface Headers {
|
||||
[name: string]: any;
|
||||
}
|
||||
|
||||
export interface LhispOauthClientConstructorParams {
|
||||
authUrl: string;
|
||||
apiUrl: string;
|
||||
clientId: string;
|
||||
clientSecret: string;
|
||||
certificado?: string;
|
||||
senhaCertificado?: string;
|
||||
authScope?: string;
|
||||
authHeaderName?: string;
|
||||
headers?: Headers;
|
||||
grantType?: GrantType;
|
||||
authContentType?: ContentType;
|
||||
sendAuthCredentialsOnRequestBody?: boolean;
|
||||
debug?: boolean;
|
||||
}
|
||||
|
||||
export interface ExecutarRequestParams extends AxiosRequestConfig {
|
||||
path: string;
|
||||
contentType: ContentType,
|
||||
}
|
||||
|
||||
export interface AccessToken {
|
||||
token_type: string;
|
||||
access_token: string;
|
||||
expires_in: number;
|
||||
created_at: number;
|
||||
}
|
||||
|
||||
export enum GrantType {
|
||||
CLIENT_CREDENTIALS='client_credentials',
|
||||
}
|
||||
|
||||
export enum ContentType {
|
||||
APPLICATION_JSON='application/json',
|
||||
APPLICATION_X_WWW_FORM_URLENCODED='application/x-www-form-urlencoded',
|
||||
}
|
||||
|
||||
export const defaultGrantType = GrantType.CLIENT_CREDENTIALS;
|
||||
export const defaultAuthContentType = ContentType.APPLICATION_JSON;
|
||||
export const defaultAuthHeaderName = 'Authorization';
|
158
src/lhisp-oauth-client.ts
Normal file
158
src/lhisp-oauth-client.ts
Normal file
|
@ -0,0 +1,158 @@
|
|||
import qs from 'querystring';
|
||||
import https from 'https';
|
||||
import axios, { AxiosRequestConfig } from 'axios';
|
||||
import {
|
||||
AccessToken, ContentType, defaultAuthContentType,
|
||||
defaultAuthHeaderName,
|
||||
ExecutarRequestParams,
|
||||
GrantType, LhispOauthClientConstructorParams,
|
||||
} from "./lhisp-oauth-client.t";
|
||||
|
||||
export default class LhispOauthClient {
|
||||
protected authUrl: string;
|
||||
protected apiUrl: string;
|
||||
protected clientId: string;
|
||||
protected clientSecret: string;
|
||||
protected authHeaderName: string;
|
||||
protected authContentType: ContentType;
|
||||
protected certificado?: string;
|
||||
protected senhaCertificado?: string;
|
||||
protected authScope?: string;
|
||||
protected headers?: Headers;
|
||||
protected grantType?: GrantType;
|
||||
protected agent: https.Agent;
|
||||
protected accessToken?: AccessToken;
|
||||
protected refreshToken?: AccessToken;
|
||||
protected sendAuthCredentialsOnRequestBody?: boolean;
|
||||
|
||||
constructor(params: LhispOauthClientConstructorParams) {
|
||||
if (params.certificado) {
|
||||
this.agent = new https.Agent({
|
||||
pfx: params.certificado,
|
||||
passphrase: params.senhaCertificado,
|
||||
rejectUnauthorized: false,
|
||||
});
|
||||
} else {
|
||||
this.agent = new https.Agent({
|
||||
rejectUnauthorized: false
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
this.certificado = params.certificado;
|
||||
this.headers = (params.headers ? params.headers : {}) as any as Headers;
|
||||
this.apiUrl = params.apiUrl;
|
||||
this.authUrl = params.authUrl;
|
||||
this.authScope = params.authScope;
|
||||
this.grantType = params.grantType;
|
||||
this.authContentType = params.authContentType || defaultAuthContentType;
|
||||
this.clientId = params.clientId;
|
||||
this.clientSecret = params.clientSecret;
|
||||
this.authHeaderName = params.authHeaderName || defaultAuthHeaderName;
|
||||
this.sendAuthCredentialsOnRequestBody = params.sendAuthCredentialsOnRequestBody;
|
||||
}
|
||||
|
||||
getAuthHeaderValue(): string {
|
||||
return `Basic ${Buffer.from(`${this.clientId}:${this.clientSecret}`).toString("base64")}`;
|
||||
}
|
||||
|
||||
parseData({ data, contentType = ContentType.APPLICATION_JSON }: { data: any, contentType: string }) {
|
||||
switch (contentType) {
|
||||
case ContentType.APPLICATION_JSON: return JSON.stringify(data);
|
||||
case ContentType.APPLICATION_X_WWW_FORM_URLENCODED: return qs.stringify(data);
|
||||
default:
|
||||
throw new Error(`Content Type Inválido: [${contentType}]`);
|
||||
}
|
||||
}
|
||||
|
||||
isTokenValid(token: AccessToken){
|
||||
if(!token) return false;
|
||||
const now = Date.now()
|
||||
const timeDiff = (now - token.created_at) / 1000;
|
||||
return timeDiff < token.expires_in - 10;
|
||||
}
|
||||
|
||||
async getAccessToken() : Promise<AccessToken> {
|
||||
if(this.accessToken && this.isTokenValid(this.accessToken)) {
|
||||
return this.accessToken;
|
||||
}
|
||||
|
||||
// TODO: Implementar Refresh Token.
|
||||
|
||||
let authRequestOpt: AxiosRequestConfig = {
|
||||
method: 'POST',
|
||||
url: this.authUrl,
|
||||
httpsAgent: this.agent,
|
||||
headers: {
|
||||
[this.authHeaderName]: this.getAuthHeaderValue(),
|
||||
'Content-Type': this.authContentType,
|
||||
},
|
||||
}
|
||||
|
||||
if(this.sendAuthCredentialsOnRequestBody) {
|
||||
let data: any = {};
|
||||
if(this.grantType) data.grant_type = this.grantType;
|
||||
if(this.authScope) data.scope = this.authScope;
|
||||
if(this.clientId) data.client_id = this.clientId;
|
||||
if(this.clientSecret) data.client_secret = this.clientSecret;
|
||||
|
||||
authRequestOpt.data = this.parseData({ data, contentType: this.authContentType });
|
||||
}
|
||||
|
||||
const response = await axios(authRequestOpt);
|
||||
return this.buildAccessToken(response.data);
|
||||
}
|
||||
|
||||
buildAccessToken(data: Omit<AccessToken,'created_at'>): AccessToken{
|
||||
this.accessToken = {
|
||||
...data,
|
||||
created_at: Date.now()
|
||||
};
|
||||
|
||||
return this.accessToken;
|
||||
}
|
||||
|
||||
getRequestAuthToken(){
|
||||
return `${this.accessToken?.token_type} ${this.accessToken?.access_token}`;
|
||||
}
|
||||
|
||||
async executarRequest({ method, path, data, params, contentType = ContentType.APPLICATION_JSON } : ExecutarRequestParams) {
|
||||
await this.getAccessToken();
|
||||
if (!this.accessToken?.token_type) {
|
||||
console.log("## LHOAUTH2 NO TOKEN ?:", this.accessToken);
|
||||
}
|
||||
|
||||
let headers = {
|
||||
'Content-Type': contentType,
|
||||
[this.authRequestHeader]: this.getRequestAuthToken(),
|
||||
...this.headers
|
||||
};
|
||||
|
||||
const response = await axios({
|
||||
method,
|
||||
url: `${this.apiUrl}${path}`,
|
||||
httpsAgent: this.agent,
|
||||
headers,
|
||||
data,
|
||||
params
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
async get({ path, contentType = 'application/json', params }) {
|
||||
return this.executarRequest({ method: 'GET', path, contentType, params });
|
||||
}
|
||||
|
||||
async put({ path, data, contentType = 'application/json' }) {
|
||||
return this.executarRequest({ method: 'PUT', path, data, contentType });
|
||||
}
|
||||
|
||||
async post({ path, data, contentType = 'application/json' }) {
|
||||
return this.executarRequest({ method: 'POST', path, data, contentType });
|
||||
}
|
||||
|
||||
async delete({ path, contentType = 'application/json' }) {
|
||||
return this.executarRequest({ method: 'DELETE', path, contentType });
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue