feat: update version to 1.0.38 and add README documentation
This commit is contained in:
parent
0f99277068
commit
4cfa8fa6e4
3 changed files with 329 additions and 3 deletions
326
README.md
Normal file
326
README.md
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
# lhisp-oauth-client
|
||||
|
||||
Bilingual README (Português / English) for the **lhisp-oauth-client** library.
|
||||
|
||||
- [Português (PT-BR)](#português-pt-br)
|
||||
- [English](#english)
|
||||
|
||||
---
|
||||
|
||||
## Português (PT-BR)
|
||||
|
||||
Cliente HTTP simples para consumir uma API protegida por **OAuth2 (Client Credentials)**, cuidando automaticamente de:
|
||||
|
||||
- Obter o `access_token` no endpoint de autenticação
|
||||
- Cache do token até expirar (com margem de ~10s)
|
||||
- Enviar o token nas requisições subsequentes para a API
|
||||
- Suporte opcional a **certificado cliente (PFX)** via `https.Agent`
|
||||
|
||||
> Observação: refresh token **ainda não está implementado** (há um `TODO` no código). Quando o token expira, um novo token é solicitado.
|
||||
|
||||
### Instalação
|
||||
|
||||
```bash
|
||||
npm i lhisp-oauth-client
|
||||
# ou
|
||||
yarn add lhisp-oauth-client
|
||||
```
|
||||
|
||||
### Uso rápido
|
||||
|
||||
```ts
|
||||
import { LhispOauthClient } from "lhisp-oauth-client";
|
||||
|
||||
const client = new LhispOauthClient({
|
||||
apiUrl: "https://api.exemplo.com",
|
||||
authUrl: "https://auth.exemplo.com/oauth/token",
|
||||
clientId: "SEU_CLIENT_ID",
|
||||
clientSecret: "SEU_CLIENT_SECRET",
|
||||
});
|
||||
|
||||
type StatusResponse = { status: string };
|
||||
|
||||
async function main() {
|
||||
const resp = await client.get<StatusResponse>({
|
||||
path: "/status",
|
||||
params: { verbose: true },
|
||||
});
|
||||
|
||||
console.log(resp.status);
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
### API (principais métodos)
|
||||
|
||||
- `getAccessToken(): Promise<AccessToken>`
|
||||
- Obtém e cacheia o token.
|
||||
- `getAuthToken(): string`
|
||||
- Retorna o header final de autorização (por padrão `"<token_type> <access_token>"`).
|
||||
- `executarRequest<ResponseType>(params): Promise<ResponseType>`
|
||||
- Método base que injeta token e executa request via Axios.
|
||||
- Atalhos HTTP:
|
||||
- `get`, `post`, `put`, `patch`, `delete`
|
||||
|
||||
### Parâmetros do construtor
|
||||
|
||||
`new LhispOauthClient(params)` aceita:
|
||||
|
||||
- `apiUrl` (string, obrigatório): URL base da API (ex.: `https://api.exemplo.com`)
|
||||
- `authUrl` (string, obrigatório): endpoint OAuth2 para obter token
|
||||
- `clientId` (string, obrigatório)
|
||||
- `clientSecret` (string, obrigatório)
|
||||
|
||||
Opcionalmente:
|
||||
|
||||
- `certificado` (string | Buffer): certificado cliente PFX
|
||||
- Se for string, o código assume **base64** e faz `Buffer.from(certificado, "base64")`
|
||||
- `senhaCertificado` (string): senha do PFX
|
||||
- `authScope` (string): adiciona `scope` no request de token
|
||||
- `grantType` (string): padrão `client_credentials`
|
||||
- `authContentType` (`ContentType`): padrão `application/x-www-form-urlencoded`
|
||||
- `authData` (Record<string,string>): campos extras enviados ao endpoint de token
|
||||
- `headers` (object): headers aplicados nas requisições para a API
|
||||
- `authHeaders` (object): headers extras somente na obtenção do token
|
||||
- `authHeaderName` (string): nome do header usado para credenciais Basic (padrão `Authorization`)
|
||||
- `tokenHeaderName` (string): nome do header onde o token é enviado (padrão `Authorization`)
|
||||
- `sendAuthCredentialsOnRequestBody` (boolean): envia `client_id` e `client_secret` também no body
|
||||
- `formatAccessToken` ((token?) => string): personaliza o valor enviado no header do token
|
||||
- `timeout` (number): timeout das requisições (ms). Padrão `60000`
|
||||
- `logger` (Logger): logger compatível (com `.child()` + métodos `info/warn/error/debug`)
|
||||
|
||||
### Content-Type
|
||||
|
||||
Você pode escolher o `Content-Type` das requisições para API via `contentType`:
|
||||
|
||||
```ts
|
||||
import { ContentType } from "lhisp-oauth-client";
|
||||
|
||||
await client.post({
|
||||
path: "/clientes",
|
||||
contentType: ContentType.APPLICATION_JSON,
|
||||
data: { name: "Maria" },
|
||||
});
|
||||
```
|
||||
|
||||
> Nota: o `contentType` de **autenticação** (request do token) é controlado por `authContentType`.
|
||||
|
||||
### Exemplo: credenciais no body (alguns servidores exigem)
|
||||
|
||||
```ts
|
||||
import { LhispOauthClient, ContentType } from "lhisp-oauth-client";
|
||||
|
||||
const client = new LhispOauthClient({
|
||||
apiUrl: "https://api.exemplo.com",
|
||||
authUrl: "https://auth.exemplo.com/oauth/token",
|
||||
clientId: "SEU_CLIENT_ID",
|
||||
clientSecret: "SEU_CLIENT_SECRET",
|
||||
authContentType: ContentType.APPLICATION_JSON,
|
||||
sendAuthCredentialsOnRequestBody: true,
|
||||
});
|
||||
|
||||
await client.get({ path: "/status" });
|
||||
```
|
||||
|
||||
### Exemplo: header de token customizado
|
||||
|
||||
```ts
|
||||
import { LhispOauthClient } from "lhisp-oauth-client";
|
||||
|
||||
const client = new LhispOauthClient({
|
||||
apiUrl: "https://api.exemplo.com",
|
||||
authUrl: "https://auth.exemplo.com/oauth/token",
|
||||
clientId: "SEU_CLIENT_ID",
|
||||
clientSecret: "SEU_CLIENT_SECRET",
|
||||
tokenHeaderName: "x-token",
|
||||
});
|
||||
|
||||
await client.get({ path: "/status" });
|
||||
```
|
||||
|
||||
### Exemplo: usando certificado (PFX)
|
||||
|
||||
```ts
|
||||
import fs from "node:fs";
|
||||
import { LhispOauthClient } from "lhisp-oauth-client";
|
||||
|
||||
const pfxBuffer = fs.readFileSync("./certificado.pfx");
|
||||
|
||||
const client = new LhispOauthClient({
|
||||
apiUrl: "https://api.exemplo.com",
|
||||
authUrl: "https://auth.exemplo.com/oauth/token",
|
||||
clientId: "SEU_CLIENT_ID",
|
||||
clientSecret: "SEU_CLIENT_SECRET",
|
||||
certificado: pfxBuffer,
|
||||
senhaCertificado: "SENHA_DO_PFX",
|
||||
});
|
||||
|
||||
await client.get({ path: "/status" });
|
||||
```
|
||||
|
||||
### Observações de segurança
|
||||
|
||||
- O `https.Agent` é criado com `rejectUnauthorized: false` (com ou sem certificado). Isso **desabilita validação do certificado** do servidor TLS.
|
||||
- Em produção, isso pode reduzir segurança. Se você precisar de validação TLS, será necessário ajustar a implementação.
|
||||
|
||||
---
|
||||
|
||||
## English
|
||||
|
||||
A lightweight HTTP client to consume an API protected by **OAuth2 (Client Credentials)**. It automatically:
|
||||
|
||||
- Fetches an `access_token` from the auth endpoint
|
||||
- Caches the token until it expires (with a ~10s safety margin)
|
||||
- Sends the token on subsequent API requests
|
||||
- Optionally supports **client certificate (PFX)** via `https.Agent`
|
||||
|
||||
> Note: refresh token is **not implemented yet** (there is a `TODO` in the code). When the token expires, a new token is requested.
|
||||
|
||||
### Install
|
||||
|
||||
```bash
|
||||
npm i lhisp-oauth-client
|
||||
# or
|
||||
yarn add lhisp-oauth-client
|
||||
```
|
||||
|
||||
### Quick start
|
||||
|
||||
```ts
|
||||
import { LhispOauthClient } from "lhisp-oauth-client";
|
||||
|
||||
const client = new LhispOauthClient({
|
||||
apiUrl: "https://api.example.com",
|
||||
authUrl: "https://auth.example.com/oauth/token",
|
||||
clientId: "YOUR_CLIENT_ID",
|
||||
clientSecret: "YOUR_CLIENT_SECRET",
|
||||
});
|
||||
|
||||
type StatusResponse = { status: string };
|
||||
|
||||
async function main() {
|
||||
const resp = await client.get<StatusResponse>({
|
||||
path: "/status",
|
||||
params: { verbose: true },
|
||||
});
|
||||
|
||||
console.log(resp.status);
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
### API (main methods)
|
||||
|
||||
- `getAccessToken(): Promise<AccessToken>`
|
||||
- Fetches and caches the token.
|
||||
- `getAuthToken(): string`
|
||||
- Returns the final auth header value (by default `"<token_type> <access_token>"`).
|
||||
- `executarRequest<ResponseType>(params): Promise<ResponseType>`
|
||||
- Base method that injects the token and performs the request via Axios.
|
||||
- HTTP helpers:
|
||||
- `get`, `post`, `put`, `patch`, `delete`
|
||||
|
||||
### Constructor parameters
|
||||
|
||||
`new LhispOauthClient(params)` accepts:
|
||||
|
||||
Required:
|
||||
|
||||
- `apiUrl` (string): API base URL (e.g. `https://api.example.com`)
|
||||
- `authUrl` (string): OAuth2 token endpoint
|
||||
- `clientId` (string)
|
||||
- `clientSecret` (string)
|
||||
|
||||
Optional:
|
||||
|
||||
- `certificado` (string | Buffer): PFX client certificate
|
||||
- If string, it is treated as **base64** and converted using `Buffer.from(certificado, "base64")`
|
||||
- `senhaCertificado` (string): PFX password
|
||||
- `authScope` (string): adds `scope` to the token request
|
||||
- `grantType` (string): default `client_credentials`
|
||||
- `authContentType` (`ContentType`): default `application/x-www-form-urlencoded`
|
||||
- `authData` (Record<string,string>): extra fields sent to the token endpoint
|
||||
- `headers` (object): headers applied to API calls
|
||||
- `authHeaders` (object): extra headers only for token retrieval
|
||||
- `authHeaderName` (string): Basic credentials header name (default `Authorization`)
|
||||
- `tokenHeaderName` (string): token header name (default `Authorization`)
|
||||
- `sendAuthCredentialsOnRequestBody` (boolean): also sends `client_id` and `client_secret` in the request body
|
||||
- `formatAccessToken` ((token?) => string): customize token header value
|
||||
- `timeout` (number): request timeout in ms (default `60000`)
|
||||
- `logger` (Logger): compatible logger (must support `.child()` and `info/warn/error/debug`)
|
||||
|
||||
### Content-Type
|
||||
|
||||
You can set the API request `Content-Type` using `contentType`:
|
||||
|
||||
```ts
|
||||
import { ContentType } from "lhisp-oauth-client";
|
||||
|
||||
await client.post({
|
||||
path: "/customers",
|
||||
contentType: ContentType.APPLICATION_JSON,
|
||||
data: { name: "Alice" },
|
||||
});
|
||||
```
|
||||
|
||||
> Note: the **auth/token** request content type is controlled by `authContentType`.
|
||||
|
||||
### Example: credentials in request body
|
||||
|
||||
```ts
|
||||
import { LhispOauthClient, ContentType } from "lhisp-oauth-client";
|
||||
|
||||
const client = new LhispOauthClient({
|
||||
apiUrl: "https://api.example.com",
|
||||
authUrl: "https://auth.example.com/oauth/token",
|
||||
clientId: "YOUR_CLIENT_ID",
|
||||
clientSecret: "YOUR_CLIENT_SECRET",
|
||||
authContentType: ContentType.APPLICATION_JSON,
|
||||
sendAuthCredentialsOnRequestBody: true,
|
||||
});
|
||||
|
||||
await client.get({ path: "/status" });
|
||||
```
|
||||
|
||||
### Example: custom token header
|
||||
|
||||
```ts
|
||||
import { LhispOauthClient } from "lhisp-oauth-client";
|
||||
|
||||
const client = new LhispOauthClient({
|
||||
apiUrl: "https://api.example.com",
|
||||
authUrl: "https://auth.example.com/oauth/token",
|
||||
clientId: "YOUR_CLIENT_ID",
|
||||
clientSecret: "YOUR_CLIENT_SECRET",
|
||||
tokenHeaderName: "x-token",
|
||||
});
|
||||
|
||||
await client.get({ path: "/status" });
|
||||
```
|
||||
|
||||
### Example: using a PFX certificate
|
||||
|
||||
```ts
|
||||
import fs from "node:fs";
|
||||
import { LhispOauthClient } from "lhisp-oauth-client";
|
||||
|
||||
const pfxBuffer = fs.readFileSync("./certificate.pfx");
|
||||
|
||||
const client = new LhispOauthClient({
|
||||
apiUrl: "https://api.example.com",
|
||||
authUrl: "https://auth.example.com/oauth/token",
|
||||
clientId: "YOUR_CLIENT_ID",
|
||||
clientSecret: "YOUR_CLIENT_SECRET",
|
||||
certificado: pfxBuffer,
|
||||
senhaCertificado: "PFX_PASSWORD",
|
||||
});
|
||||
|
||||
await client.get({ path: "/status" });
|
||||
```
|
||||
|
||||
### Security notes
|
||||
|
||||
- The internal `https.Agent` is created with `rejectUnauthorized: false` (with or without PFX). This **disables TLS server certificate validation**.
|
||||
- In production, this may reduce security. If you need strict TLS validation, the implementation must be adjusted.
|
||||
Loading…
Add table
Add a link
Reference in a new issue