> ## Documentation Index
> Fetch the complete documentation index at: https://docs.benup.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Autenticação Personalizada

> Abordagens diferentes para auth-strategies diferentes

Em um cenário com multiplos benefícios e diversas integrações, lidamos com diversos sistemas e, consequentemente, com diferentes formas de autenticação. Algumas APIs utilizam **JWT**, outras **OAuth**, algumas exigem **token fixo no header**, e ainda existem aquelas que utilizam métodos totalmente personalizados.

Com tantas abordagens, não é viável criar um ambiente multi-benefícios com estratégias de autenticações fixas. Por isso, o **benSDK** permite que cada benefício implementado defina sua própria *auth strategy*, oferecendo flexibilidade para se adaptar a qualquer modelo de autenticação.

### Estrutura básica

No arquivo `benefit-definition.ts` existe um campo opcional:

```ts theme={null}
auth?: {
    handler: (credentials: any, ctx: AuthHandlerCtx) => Promise<AuthHandlerResult>;
};
```

O campo `auth` lida com as responsabilidades de autenticação. Esse `handler` é justamente, onde se define uma função que irá lidar com essa responsabilidade. Um ponto interessante é que a cada mudança de estado na **state-machine** esse handler será chamado.
Por isso, o `ctx` fornece algumas funções auxiliares que podem ser úteis para cachear e reutilizar tokens entre chamadas:

```ts theme={null}
    get: (params: GetTokenParameters) => Promise<string | null>;
    set: (params: SetTokenParameters) => Promise<boolean>;
```

Essas funções servem para armazenar e recuperar tokens.

Elas são especialmente úteis em cenários em que o handler é invocado com frequência, por exemplo, a cada tranasição de estado, mas o token tem um TTL maior que esse intervalo. Sendo tudo isso configurável via chamadas ao `set`.

***

### Retorno esperado

O handler deve retornar um objeto simples do tipo:

```ts theme={null}
export type AuthHandlerResult = {
    outcome: 'FAILED';
    reason?: string;
    retry?: boolean;
} | {
    outcome: 'SUCCEEDED';
    instance?: AxiosInstance;
};
```

Com esse retorno é possível informar se a autenticação foi bem-sucedida ou falhou, em caso de falha se deve ocorrer re-tentativas (até 7 vezes, com backoff exponencial).
Quando a autenticação é bem-sucedida, o handler deve retornar uma instância configurada do axios através de `axios.create`.

***

### Exemplo prático

Abaixo um exemplo completo de implementação de uma *auth strategy* personalizada, usando cache de token com `ctx.tokenHelper`:

```ts theme={null}
auth: {
  handler: async (credentials: any, ctx: AuthHandlerCtx) => {
    const token = await ctx.tokenHelper.get({
      accountID: credentials.accountID,
      companyID: credentials.companyID,
      benefitID: credentials.benefitID
    });

    if (token) {
      return {
        outcome: 'SUCCEEDED',
        instance: axios.create({
          baseURL: 'https://api.example.com',
          headers: { Authorization: `Bearer ${token}` }
        })
      };
    }

    const res = await axios.post('https://api.example.com/auth/token', {
      login: credentials.login,
      password: credentials.password
    });

    if (res.status !== 200) {
      return {
        retry: true, // Retentará até 7 vezes, com backoff exponencial
        outcome: 'FAILED',
        reason: 'Failed to get token'
      };
    }

    await ctx.tokenHelper.set({
      accountID: credentials.accountID,
      companyID: credentials.companyID,
      benefitID: credentials.benefitID,
      valueToBeStored: res.data.token,
      storeForSeconds: 60 * 60 * 24 * 30
    });

    return {
      outcome: 'SUCCEEDED',
      instance: axios.create({
        baseURL: 'https://api.example.com',
        headers: { Authorization: `Bearer ${res.data.token}` }
      })
    };
  }
}
```

1. Tenta reutilizar um token já armazenado.
2. Caso não exista, requisita um novo token.
3. Armazena o token para futuras chamadas.
4. Retorna uma instância axios autenticada e pronta para uso.
