> For the complete documentation index, see [llms.txt](https://guias.mosaico.gov.pt/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://guias.mosaico.gov.pt/adesao-ao-fornecedor-de-evidencias-localizador-de-evidencia/comunicacao-com-o-localizador-de-evidencia/redirecionamento-para-o-localizador-de-evidencia.md).

# Redirecionamento para o localizador de evidência

Após receber os dados e o pedido da pessoa, o portal de serviços tem de comunicar e enviar o pedido para o localizador de evidência. Com base nos requisitos técnicos OOTS (Once-only Technical System), além dos campos a enviar:

* O pedido é enviado por parâmetros de URL
* O localizador de evidência não requer autenticação da pessoa do pedido
* A informação enviada não é sensível, mas pode ser manipulada nos parâmetros do URL
* A gestão de chaves de encriptação com os portais com os quais o localizador irá comunicar pode ser uma tarefa complexa, e a sua necessidade será revista após a fase de testes do OOTS Projectathon
* É possível que haja alterações no caso de ser necessário um método mais seguro

Com base nesta informação, uma vez que não requer autenticação (e de forma a não expor com facilidade os campos do pedido que podem ser adulterados no endereço URL da página), foi pensada a seguinte solução de ofuscação:

1. **Criação de uma mask key (chave de ofuscação) única associada ao portal de serviços:**

   * Esta chave é composta por uma string de 255 caracteres alfanuméricos
   * A chave é gerada pela equipa responsável pelo localizador de evidência durante o processo de integração, e é fornecida ao portal de serviços através de um canal seguro (a ser determinado)
   * A chave é secreta no sentido em que nunca deve ser exposta ao público
   * A chave é única para cada portal de serviços

2. **O portal de serviços codifica e mascara parte do conteúdo do pedido de evidência com o auxílio da chave de codificação:**

   * A codificação é realizada através de uma cifra de substituição XOR de forma a não ser demasiado simples como um único encoding em base64, nem demasiado complexa como o recurso a criptografia
   * O pedido de evidência é assumindo como partindo de um JSON string e depois convertido a base64, seguido da codificação por uma cifra de substituição com a chave de ofuscação
   * O resultado deverá ser um conjunto de caracteres alfanuméricos representados na constante MASK\_CHARS
   * É um método simples de encriptação simétrica e ofuscação, e robusto a ataques de força bruta, cuja segurança está dependente do sigilo da chave

3. **O pedido codificado deverá ser depois encoded para URL e enviado para a página do localizador de evidência como parâmetro URL (ev-request) em conjunto com o código identificador do portal de serviços (portal-id).** <br>

4. **O localizador de evidência vai obter a chave de codificação específica ao portal de serviços associado ao pedido, através do identificador do portal, e descodificar o pedido para obter o JSON string do pedido original.**

Para aplicar os passos 3 e 4, o portal de serviços deverá implementar o seguinte código (para efeitos práticos e de apresentação, apresentamos o código na linguagem Java e os passos mais importantes em sequência):

5. **Obter a mask key** **fornecida ao portal de serviços no processo de integração e que estará associada ao portal que pretende integrar. Para este exemplo teremos, a título exemplificativo, a chave “42oszYRtoj3BgXu9”. Mas será fornecida mais tarde uma chave com 255 caracteres alfanuméricos no processo de integração.**
6. **Implementar os seguintes métodos auxiliares de codificação associados à chave de codificação:**

<pre class="language-java"><code class="lang-java">/** Caracteres que serão codificados **/
private static final String MASK_CHARS = 
 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZàáâãçéêíóôõú0123456789{}"/':-,”;
 
/** Conversão a Base64 **/
/** Importante converter o input a bytes para não haver problemas com nonASCII characters **/
<strong>public static String encodeToBase64(String input) {
</strong> byte[] encodedBytes = Base64.getEncoder().encode(input.getBytes());
 return new String(encodedBytes);
}

/** Codificação do pedido com base na Mask Key **/
public static String mask(String base64Input, String maskKey) {
 StringBuilder maskedText = new StringBuilder();
 String repeatedMaskKey = repeatMaskKey(base64Input, maskKey);
 
 for (int i = 0; i &#x3C; base64Input.length(); i++) {
  char currentChar = base64Input.charAt(i);
  char maskChar = repeatedMaskKey.charAt(i);
  int alphabetIndex = MASK_CHARS.indexOf(currentChar);
  
  if (alphabetIndex != -1) {
    int newIndex = (alphabetIndex + maskChar - 'a') % MASK_CHARS.length();
  
    if (newIndex &#x3C; 0) {
      newIndex += MASK_CHARS.length();
    }
    
    maskedText.append(MASK_CHARS.charAt(newIndex));
  } else {
    maskedText.append(currentChar);
  }
}
 
 return maskedText.toString();
}

/** Mask Key é repetida para acompanhar a totalidade do input **/
private static String repeatMaskKey(String input, String maskKey) {
  StringBuilder repeatedMaskKey = new StringBuilder();
  int textLength = input.length();

  for (int i = 0; i &#x3C; textLength; i++) {
    char maskChar = maskKey.charAt(i % maskKey.length());
    repeatedMaskKey.append(maskChar);
  }

  return repeatedMaskKey.toString();
}

/** Encoding para URL de modo a poder ser enviado como parâmetro **/
public static String encodeURLParameter(String text) {
  try {
    return URLEncoder.encode(text, StandardCharsets.UTF_8.toString());
  } catch (Exception e) {
    e.printStackTrace();
  }

  return "";
}
</code></pre>

A partir do JSON string do pedido, aplicar a seguinte sequência de codificações até obter o parâmetro a ser enviado. A demonstração abaixo inclui um exemplo de um pedido JSON num formato já desatualizado, contudo pode ser aplicado a qualquer tipo de input, desde que se trate de um JSON com a estrutura de dados correta e tenha um encoding UTF-8.

<pre class="language-java"><code class="lang-java"><strong>String jsonInput =
</strong>"{\"requirementId\":\"12345678\",\"redirectUrl\":\"https://eportugal.gov.pt\",\
"personData\":{\"levelOfAssurance\":\"high\",\"id\":\"PT/NL/123456789\",\"famil
yName\":\"Smith\",\"givenName\":\"Jack\",\"dateOfBirth\":\"1990-01-01\"}}";

String maskKey = "42oszYRtoj3BgXu9";
String base64JsonInput = encodeToBase64(jsonInput);
// Resultado:
eyJyZXF1aXJlbWVudElkIjoiMTIzNDU2NzgiLCJyZWRpcmVjdFVybCI6Imh0dHBzOi8vZXBvcnR1Z2F
sLmdvdi5wdCIsInBlcnNvbkRhdGEiOnsibGV2ZWxPZkFzc3VyYW5jZSI6ImhpZ2giLCJpZCI6IlBUL0
5MLzEyMzQ1Njc4OSIsImZhbWlseU5hbWUiOiJTbWl0aCIsImdpdmVuTmFtZSI6IkphY2siLCJkYXRlT
2ZCaXJ0aCI6IjE5OTAtMDEtMDEifX0=

String maskedInput = mask(base64JsonInput, maskKey);
// Resultado:
DVXQgPqco67YhN:YC1zC7b,B026"Tu'o"WuA{uuR/5:2id:NC29QAuthWvFvjyV3/FeNgP
mOqw:w5TZW{JrNCaQPrL65OeVPBK1NAcCArP2VUeMMA39cgOi8/t3"iU:2fbbBgKthWvF25TAM{ZXHg
uthWuZpRRh-
{WSQ}rBc1sAzUJ2W7J/zAO'Ls3lUhN'M/FX}AO'boL65OdxTCJ9MaeqM/16BObJLfhGA{uuD"6:YZTb
6zcXazuthWs2AUKUX}0SL}vpBt6g=

String urlEncodedInput = encodeURLParameter(maskedInput);
// Resultado:
DVXQgPqco67YhN%3AYC1zC7b%2CB026%22Tu%27o%22WuA%7BuuR%2F5%3A2id%3ANC29Q
AuthWvFvjyV3%2FFeNgPmOqw%3Aw5TZW%7BJrNCaQPrL65OeVPBK1NAcCArP2VUeMMA39cgOi8%2Ft3
%22iU%3A2fbbBgKthWvF25TAM%7BZXHguthWuZpRRh-
%7BWSQ%7DrBc1sAzUJ2W7J%2FzAO%27Ls3lUhN%27M%2FFX%7DAO%27boL65OdxTCJ9MaeqM%2F16BO
bJLfhGA%7BuuD%226%3AYZTb6zcXazuthWs2AUKUX%7D0SL%7DvpBt6g%3DUma vez obtida a JSON string codificada do pedido, enviar para a página do localizador de evidências como um parâmetro URL de acordo com a especificações abaixo.
</code></pre>

Uma vez obtida a JSON string codificada do pedido, enviar para a página do localizador de evidências como um parâmetro URL de acordo com a especificações abaixo.

**Parâmetros URL**

| Parâmetro  | Descrição                                                                                          | Observações                                                                                                         |
| ---------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| ev-request | O JSON string do pedido após codificação em base64, codificação com chave única, e codificação URL | Conteúdo do pedido “EvidenceRequest” pode ser consultado abaixo                                                     |
| portal-id  | Código de identificação do portal de serviços                                                      | O código é fornecido pelo localizador de evidência para identificar o portal de serviços localmente                 |
| request-id | Código de identificação gerado pelo portal de serviços                                             | Utilizado para identificar todas as invocações de serviço relacionadas com o processo global de pedido de evidência |

Exemplo de URL de redirecionamento:

{% hint style="info" %}
**http\://\[domínio AutGov]/evidence-request?ev-request=**&#x44;TCy7uuR%2F63wgO3PAb9MCuthWL71jy%7D0BWCN%7BVyRZvp8jy6YC39Bz uQEr678ixYYgc8NBeGQr5J%7D5NdPAK5R%7BrqE0M%7BySd2p%7BuR%22vxM1MaxStcqgGua%7BOqD%22sbY5N6m%7DPC%22atLQrYTOeV2Ah1DgzGR%2F16BOt3i%7D%3AWK1alzWwZYie7ZAFWg7zd3WLYTO t3Wgc%2FDAwUF46%7D%22jO3LAJ1D7b%2CzWvF25TAM%7BXCy7ulzWvJXOaIK7IP%22 %7BSQ5ZI2%7DSq%7Bn%22Gqe%2FKtLQrYTOtUMgJTLzOig7v365J2s7ZX%7DAO'boL65I %2CUK7ZOAgU'd%2F5lj4NdP7GCy7caA%22%7DQVRrIK7ZOy7eCArPbk5b3TBK5G7b%2 CzWs2AUKUX%7D0SL%7DvpBQrYTlJQ'7ZOABeGDo67Y4U%7DhBJKA%2FalBoQ%3Aviy 6s%7BVfDByURrQb04NQYghfc%7BfmbWrUfOtUMBJ9PCOGSrPb%7D1yF0g%3AWg7u ucqvkB4T%3AQ%7BJ9b%2FeQAp5b%22UdFOgbbazOKI%2F66BXLZf%2FGyf%22vJBZJM TOt32gcTbgPyb%2F67j4NdPBVWg7xd3WLYTOyM'7ZOy7ulzWvVUhdwM%2FFOA-MPBZJMTOtUK7ZOAAeqM%2F16BOt3cBJfNgamO%2FrZ%225N7ZAJ5zBf%2Fz%2F5%3A w4TZmzbfM7yCIqPV8hNYZfh9QCy'Fo5%7DUjx'M1FOy7umkQrYT3JQ'7ZOAgfGLpN3X5y 3PBi0A%2FalB8wbUOx%7DP711HAOpLWMazO%2CQ'7ZOAAyUC%226%3A8ib%7DPBhz FAeqbp%226VU%2CUM%22-uA%7Bs%2CzWL79hU7m%3AhfCgKthWL6vSu'0%7B4b%22atLQrYTOeVZBi5VzPCg7v365J2s7ZX8AVubpH65I%2CUK7JTCAO'N95l2jvRPCJ9K% 7DKthWL7l1t2W1FOy7eqDp5J71NhTC1LDCeGL0r6BOt2M%7BXCy7uuPp%22%7D%22gN 3TA3zaDMKOquZ%7D5ObTgcqA%2FambqwbYIec%3&#x44;**\&portal-id=**&#x50;MC-TES&#x54;**\&request-id=**&#x62;f08b6db-3edd-47c3-b48b-b9ae5f3eae92
{% endhint %}

EvidenceRequest:

| Campo                 | Descrição                                                                                                       | Observações                                                                                                        |
| --------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| requirement           | Identificador do requerimento                                                                                   |                                                                                                                    |
| procedure             | Identificador do procedimento                                                                                   |                                                                                                                    |
| redirectUrl           | Endereço para redirecionar para o portal de serviços após o localizador enviar a evidência no final do processo | Endereço deve ser URL encoded. Endereço será também utilizado em caso de erro que não permita proceder no processo |
| + person              | Dados da pessoa (natural person)                                                                                |                                                                                                                    |
| ++ levelOfAssurance   | O nível mínimo de garantia eIDAS                                                                                | “High”, “Medium”, ou “Low”. Case sensitive                                                                         |
| ++ id                 | Identificador único eIDA                                                                                        | Opcional                                                                                                           |
| ++ familyName         | Apelido da pessoa                                                                                               |                                                                                                                    |
| ++ givenName          | Primeiro nome da pessoa                                                                                         |                                                                                                                    |
| ++ dateOfBirth        | Data de nascimento da pessoa                                                                                    | Formato yyyy-MM-dd                                                                                                 |
| requesterId           | Identificador do portal                                                                                         |                                                                                                                    |
| requesterType         | Identificador do tipo de portal                                                                                 |                                                                                                                    |
| + requesterNames      | Lista de nomes do portal em vários idiomas                                                                      | Lista                                                                                                              |
| ++ lang               | Idioma                                                                                                          | “EN”, “PT” …                                                                                                       |
| ++ name               | Nome do portal no idioma                                                                                        |                                                                                                                    |
| fullAddress           | Morada da entidade solicitadora (portal)                                                                        | Opcional                                                                                                           |
| locatorDesignator     | N.º da porta ou n.º do edifício da entidade solicitadora                                                        | Opcional                                                                                                           |
| postCode              | Código postal da entidade solicitadora                                                                          | Opcional                                                                                                           |
| postCityName          | Localidade da entidade solicitadora                                                                             | Opcional                                                                                                           |
| adminUnitLevel1       | Código do nível mais alto da morada (quase sempre o código do país)                                             | Opcional                                                                                                           |
| adminUnitLevel2       | Código do nível secundário da morada (costuma ser um código da cidade ou região)                                | Opcional                                                                                                           |
| possibilityForPreview | Indica se é um pedido de evidência com possibilidade de pré-visualização da evidência                           | Booleano                                                                                                           |

Exemplo de JSON do EvidenceRequest:

```json
{
 "requirement": "https://sr.oots.tech.europa.eu/requirements/f8a6a284-34e9-42c7-9733-63b5c4f4aa42",
 "procedure": "T1",
 "person": {
  "levelOfAssurance": "High",
   "id": "PT/NL/123456789",
   "familyName": "Smith",
   "givenName": "Jack",
   "dateOfBirth": "1990-01-01"
 },
 "redirectUrl": "https%3A%2F%2Fportaldeprocedimentos.pt",
 "requesterType": "urn:cef.eu:names:identifier:EAS:9946",
 "requesterId": "9988b2b6-a23b-41d7-b373-7160e2190b38",
 "requesterNames": [
  {
   "lang": "EN",
   "name": "Procedure Portal"
  },
  {
   "lang": "PT",
   "name": "Portal de Procedimentos"
  }
 ],
 "fullAddress": "Rua de Cima, 58",
 "locatorDesignator": "58",
 "postCode": "4050-456",
 "postCityName": "Porto",
 "adminUnitLevel1": "PT",
 "adminUnitLevel2": "",
 "possibilityForPreview": true
}
```
