Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.

...

Painel
Deck of Cards
historyfalse
iddeck principal
Card
labelMobile

Para a construção do nosso aplicativo utilizamos o framework de desenvolvimento Ionic na versão 5. Ele é considerado um framework do tipo híbrido, onde temos uma solução web e nativa trabalhando em conjunto. A sua principal característica é a utilização de uma Webview (uma espécie de container) para a renderização dos elementos na tela. Dentre os seus principais benefícios, estão o desenvolvimento mais rápido (utiliza recursos amplamente utilizados no mercado HTML, CSS e Javascript) e trabalhar com multiplataforma (Android e iOS) com apenas um único projeto.


No projeto do Meu RH utilizamos o Ionic como um projeto full Angular, porém ele permite a integração também com outros frameworks como React, Vue, Stencil, etc. A parte de comunicação para consumir os recursos do celular é feita pelo Cordova, que conta com diversos plug-ins dentre eles a Geolocalização, biometria, câmera, arquivos do celular e outros. O Ionic também conta com uma ampla biblioteca de componentes que podem ser reaproveitados e combinados para criar novas funcionalidades. O projeto está localizado no repositório MeuRH no AzureDevops. 


A estruturação do nosso app contempla hoje a apenas as páginas relacionadas a login (Login, Esqueceu a Senha, Alterar a senha no primeiro login), a parte de configurações (Configuração de ambiente, Visualização/Compartilhamento de QR-Code, menus de ajuda) e as telas de erros exibidas. Todas as outras funcionalidades do Meu RH são renderizadas pelo projeto de Portais através de um browser que é aberto dentro do aplicativo. Como utilizamos a biblioteca do PO-UI no projeto de Portais e ela é totalmente responsiva, ela adquiri a forma de um aplicativo mobile.

Porém ao abrir o browser, ficamos com duas webviews diferentes (A própria do Ionic e a outra do browser). Quem acessa os recursos do celular é a própria Webview do Ionic ou o Cordova e por isso o browser onde o portal acessa não tem acesso direto a esses recursos. Porém, sabemos que dentro do aplicativo consumimos esses recursos da mesma forma (Ex: Batida por geolocalização). Para isso funcionar, criamos uma espécie de fila de eventos entre as duas webviews, sendo que sempre quando o portal precisa de algum recurso do celular ele posta uma mensagem na fila de eventos (onde a webview do ionic está sempre escutando), o Ionic solicita o recurso/ação e devolve uma mensagem de resposta para a webview do portal:



Foi criado um contrato de mensagem nos dois projetos para que os dois lados possam saber o que está sendo solicitado e o que deve ser retornado:

Projeto de portais solicitando geolocalização:

Projeto do app recebendo a solicitação e verificando qual o evento recebido:


Utiliza o plugin do Cordova para recuperar a geolocalização e emite a resposta na fila de eventos para o portal:

Projeto de portais recebendo a resposta do Ionic. Seta a informação de geolocalização e exibe a localização no mapa renderizado na tela:



Em relação a comunicação com o backend, o formato se assemelha a versão de Portal do Meu RH, inclusive a parte que ele renderiza o portal pelo browser utiliza todo o mecanismo do projeto de Portais. Porém, algumas API's estão também do lado do Ionic, por exemplo a API de autenticação. Dessa forma, temos um serviço genérico que é capaz de identificar qual o ERP e a partir disso definir qual a url base para realizar as requisições para o backend. A diferença é que agora todas as requisições provenientes do Ionic exigem o mecanismo de CORS (melhor detalhado na sessão de CORS). Dentre as três linhas de produto temos dois tipos de mecanismos, para RM e Protheus utilizamos um Bearer Token e em Datasul utilizamos Basic Authentication (Cookies). Em ambos os mecanismos os objetos de autenticação são compartilhados entre as duas webviews, visto que são necessários nos dois lados:



Card
labelDatasul

Para utilizar a versão atual do aplicativo é necessário que o CORS esteja corretamente configurado, conforme as documentações abaixo:

   - Configuração do CORS no JBOSS

   - Configuração do CORS no TOMCAT

A autenticação no DATASUL ocorre via cookie.


Expandir
titleJBOSS

É realizado uma requisição POST em /dts/portal-hcm/rest/auth/login. É enviado os dados do usuário via request payload:

A resposta deverá possuir http status 200 e o seguinte corpo:

Caso as credenciais estejam incorretas será retornado http status 500 com o seguinte corpo:

Caso o login tenha acontecido com sucesso é transmitido as credenciais do usuário via mensagem entre a webview do mobile e webview do portal.

Expandir
titleTOMCAT

É realizado uma requisição GET em /api/rh/v1/login/auth/[USUARIO]. A autenticação ocorre via basic auth definido pelo frame.

A resposta deverá possuir http status 200 e o seguinte corpo:

     

Caso as credenciais estejam incorretas será retornado http status 401 com o corpo vazio.

Caso o retorno seja status 503:

É necessário verificar se não há problemas no contexto rest do ambiente. Para isso envie a requisição protocolo://IP:PORTA/api/btb/v1/companies no postman, o retorno deve ser parecido com:

Se o retorno for 503, o item deve ser analisado pela equipe de framework.


Login com SSO-FILTER ativo (passando pela página de login do frame): É preenchido automaticamente as credenciais do usuário na página de login do frame. Caso aconteça algum erro de autenticação nessa página a página será exibida para o usuário (ocasionando o que os usuários acreditam ser o bug de login em 2 telas).


Login com SSO-FILTER desativado: Caso o login tenha acontecido com sucesso é transmitido as credenciais do usuário via mensagem entre a webview do mobile e webview do portal.

Card
labelProtheus

É necessário que o CORS esteja corretamente configurado e utiliza bearer token.

Card
labelRM

Desde 09/2021 estamos utilizando nosso aplicativo com o framework Ionic na versão 5. Em relação a versão anterior, tivemos algumas mudanças e as principais delas foram a utilização do mecanismo de CORS, a autenticação por bearer token e a nova forma de comunicação entre o aplicativo e o servidor de aplicação.

CORS

Para atender o correto funcionamento do mecanismo de CORS e mantendo a infraestrutura que os clientes já possuíam, estamos utilizando agora o modelo de API's do host disponibilizadas pelo nosso time de framework. Além disso, caso o servidor web utilizado seja IIS, realizar a instalação do módulo adicional de CORS https://www.iis.net/downloads/microsoft/iis-cors-module. Maiores informações sobre o mecanismo de CORS estão na seção relacionada. Para o correto funcionamento do CORS em RM, são necessários 3 cabeçalhos na resposta das requisições de OPTIONS:

Bearer token

Outra novidade na versão do Ionic 5 é a utilização do bearer token para autenticação do usuário ao invés do processo de basic authentication. A bearer authentication (também chamada de autenticação por token) é um esquema de autenticação HTTP que envolve tokens de segurança chamados bearer tokens. O nome "Bearer token" pode ser entendido como "dar acesso ao portador deste token". O bearer token é uma string criptografada, gerada pelo servidor em resposta a uma solicitação de login. O client deve enviar este token no cabeçalho de autorização ao fazer solicitações para recursos protegidos. Utilizamos a API Autorização / Autenticação Basic e Bearer Token que retorna um token contendo as informações do usuário e outras claims que são relevantes para ele.

Como funciona a comunicação entre o IIS e o servidor de aplicação?

Na versão anterior do aplicativo, utilizavamos a camada de API's do FrameHTML para consumir os serviços necessários. Na nova versão, consumimos as API's que estão na camada do host para recuperar as informações necessárias.


O endereço de acesso as API's do host é diferente da camada de API's do FrameHTML e não poderíamos realizar alterações de infraestrutura nesse aspecto, pois obrigaria o cliente a gerar novamente o QR Code de ambiente. Dessa forma, estamos utilizando a camada de FrameHTML como uma espécie de client para o host, sendo que todas as requisições ainda são encaminhadas para a camada de FrameHTML e de lá são redirecionadas para o host. Para realizar a comunicação entre a camada FrameHTML e a camada do host são utilizadas as portas de API configuradas dentro dos serviços de host. Para isso, é importante se atentar que caso os servidores de aplicação e de portal sejam separados, não pode haver qualquer tipo de bloqueio sobre as portas de API do host e o servidor de portal deve ser capaz de se comunicar através delas. Para realizar a diferenciação, agora temos 3 controllers que fazem todo o processo.

O primeiro deles é o controller padrão na camada FrameHTML e que atende o Portal quando utilizamos a autenticação via Cookie. Note que chamamos o server rest diretamente através do método "RetornaListaPermissoesUsuario" nesse caso:

Ainda na camada FrameHTML, temos o segundo controller. Esse é responsável por atender as requisições de Portal (quando utilizamos autenticação via Token) e o aplicativo com Ionic na versão 5. Ele é responsável por direcionar a requisição para o host através do método "RedirectRequestToNewApiModel". Note que o prefixo dele tem a palavra "new", justamente para segmentar quando deve vir para esse controller ou para o padrão:

O terceiro controller está na camada do host. Ele é bem similar ao primeiro, porém ja conta com todos os benefícios de estar na camada host. Além disso, ele está atendendo ao redirecionamento realizado pelo segundo controller:

Para validar o funcionamento do aplicativo na nova versão, foram desenvolvidos dois scripts dentro da ferramenta Postman, que tem como objetivo simular as principais requisições realizadas pelo aplicativo. Um desses scripts simula de fato o comportamento do app, validando o login, CORS e o consumo de serviços em geral (Pode ser executado de qualquer máquina). Já o outro script tem como objetivo consumir algumas das api's que estão dentro do host (Precisa ser executado de dentro da máquina onde exista o serviço de host). O passo-a-passo para executar os scripts estão no documento https://docs.google.com/document/d/1Jr7It3jhl2aUJBpy9T4c7QtxTU51J9SlGLy8JDsQ8PA/edit?usp=sharing. Caso algum teste que seja executado pelo Postman falhe, significa que algum tipo de problema está impedindo o funcionamento correto do aplicativo. Por padrão, todas as API's (exceto a de healthcheck) não retornam informações detalhadas de erro por motivos de segurança. Caso seja necessário obter mais informações para algum tipo de erro nas API's em geral, basta adicionar a tag <add key="ShowCompleteLogErrorMyHr" value="true" /> dentro do Web.config na pasta FrameHTML:

 

Pelas especificações de infraestrutura dos clientes, já temos algumas ações mapeadas que podem resolver os problemas de configuração de ambiente. O primeiro passo é seguir os passos descritos no KCS e realizar todas as configurações descritas. Dentre os casos mapeados, temos:

Aviso
OBS: Em todos os cenários mapeados, é necessário seguir os passos do KCS. Além disso, a reserva das portas deve ser feita em todos os servidores que possuam serviços ativos de host.


Portal e biblioteca instalados no mesmo servidor

Seguir apenas o KCS

Portal e biblioteca instalados em servidores distintos

A primeira verificação que deve ser feita é se o servidor de portal consegue "atingir" o servidor de aplicação e como ele faz isso (Através de IP, hostname, DNS, etc). Além disso, é necessário que a comunicação entre o servidor de portal e o de aplicação seja realizada através das portas API configuradas no serviços de host. Caso exista algum mecanismo de segurança entre a comunicação dos dois servidores (firewall, antivírus, proxy, etc) é necessário criar regras para liberar as portas API, caso contrário o aplicativo não irá funcionar. Por padrão o servidor de portal tentará se comunicar com o servidor de aplicação através do hostname. Se não for adequado para a configuração do cliente a utilização do hostname, será necessário adicionar a tag Host dentro dos arquivos RM.Host.Service.exe.config:

Outras configurações

Existem algumas configurações que podem ser utilizadas independente de como o cliente organizou sua infraestrutura. Abaixo listamos algumas das que já foram mapeadas.

        WebService - ServicesHostName

Em casos onde tenha WebService configurado através da tag ServicesHostName no RM.Host.Service.exe.config, a comunicação será feita através do endereço do WebService utilizando as portas de API configuradas no serviço de host.

Aviso
OBS: Caso o cliente utilize a tag <add key="EnableWSSecurity" value="true" />, onde habilita a comunicação segura no host, as requisições entre o servidor de portal e o servidor de aplicação utilizaram o protocolo HTTPS. Nesses casos é obrigatória a configuração da tag ServicesHostName pois o domínio precisa ser certificado.

        SubDomainMask ou múltiplas pastas FrameHTML

Existem casos onde o cliente utiliza apenas um servidor de aplicação que atende a diversos servidores de portal. Ele pode utilizar a configuração de Multi Tenancy(Configurando o RM Multi Tenancy (Multi Alias)) ou replicar diversas pastas FrameHTML apontando para o servidor de aplicação. Nesses casos não se pode utilizar a tag DefaultDB dentro dos serviços de host e sim a tag ServiceAlias dentro do arquivo Web.config na pasta FrameHTML. Além disso, é necessário adicionar a tag <add key="ConsiderServiceAliasMyHr" value="true" /> dentro do arquivo Web.config (Caso existam réplicas da pasta FrameHTML, copiar para todos).

        Clientes que utilizam Proxy Reverso ou mecanismos de encaminhamento

Caso os cabeçalhos de CORS não estejam sendo repassados corretamente para o client (teste pode ser feito pelo script do Postman), mesmo criando regras de encaminhamento, é necessário fazer uma configuração adicional dentro do IIS. Após realizar a instalação do módulo adicional de CORS https://www.iis.net/downloads/microsoft/iis-cors-module, é necessário adicionar as linhas dentro do web.config dentro da pasta FrameHTML na seção system.webServer

Bloco de código
languagexml
titleConfiguração CORS IIS
<system.webServer>
    <cors enabled="true">
        <add origin="http://localhost" allowCredentials="true" maxAge="120">
            <allowHeaders allowAllRequestedHeaders="true">
                <add header="Content-Type" />
            </allowHeaders>
            <allowMethods>
                <add method="GET" />
                <add method="PUT" />
                <add method="POST" />
                <add method="OPTIONS" />
                <add method="DELETE" />
            </allowMethods>
            <exposeHeaders>
                <add header="Content-Type" />
            </exposeHeaders>
        </add>
        <add origin="ionic://localhost" allowCredentials="true" maxAge="120">
            <allowHeaders allowAllRequestedHeaders="true">
                <add header="Content-Type" />
            </allowHeaders>
            <allowMethods>
                <add method="GET" />
                <add method="PUT" />
                <add method="POST" />
                <add method="OPTIONS" />
                <add method="DELETE" />
            </allowMethods>
            <exposeHeaders>
                <add header="Content-Type" />
            </exposeHeaders>
        </add>
        <add origin="capacitor://localhost" allowCredentials="true" maxAge="120">
            <allowHeaders allowAllRequestedHeaders="true">
                <add header="Content-Type" />
            </allowHeaders>
            <allowMethods>
                <add method="GET" />
                <add method="PUT" />
                <add method="POST" />
                <add method="OPTIONS" />
                <add method="DELETE" />
            </allowMethods>
            <exposeHeaders>
                <add header="Content-Type" />
            </exposeHeaders>
        </add>
    </cors>
</<system.webServer>
Card
labelCORS

O que é CORS?

O CORS (Cross-origin Resource Sharing) é um mecanismo utilizado pelos navegadores para compartilhar recursos entre diferentes origens. O CORS é uma especificação do W3C e faz uso de headers do HTTP para informar aos navegadores se determinado recurso pode ser ou não acessado.

Cross-Origin Resource Sharing (CORS, Compartilhamento de recursos de origem  cruzada) - AWS SDK for JavaScript

Requisição

OPTIONS (

Preflight

)

É necessário sempre verificar se as requisições do tipo OPTIONS ( preflight ) estão sendo feitas e o retorno deve conter os cabeçalhos necessários de CORS. Por isso, é importante verificar que eles estão sendo retornados de maneira correta e que nenhum tipo de mecanismo de segurança (firewall, antivírus, proxy, etc) estejam barrando os headers.

Os principais headers de response de CORS são:

HeaderDescrição
Access-Control-Allow-OriginEspecifica a origem permitida, podendo ser http://localhost ou * para permitir qualquer uma
Access-Control-Allow-MethodsMétodos que são permitidos para acessar aquele recurso (GET, POST, PUT, DELETE, etc)
Access-Control-Allow-HeadersQuais headers são permitidos na requisição (Headers convencionais e simples já são permitidos)
Access-Control-Allow-CredentialsSe a requisição deve ser feita com credenciais (true ou false)
Access-Control-Expose-HeadersEspecifica quais headers o browser pode ter acesso
Access-Control-Max-AgeTempo de vida do resultado da requisição de OPTIONS


Os principais headers de request de CORS são:

HeaderDescrição
OriginEspecifica a origem do request
Access-Control-Request-MethodEspecifica qual o método será usado para requisição seguinte a OPTIONS
Access-Control-Request-HeadersEspecifica quais os headers diferentes dos convencionais que serão enviados na requisição


A requisição de OPTIONS preflight nem sempre é realizada, existem alguns casos que são consideradas como requisições simples. São elas:

Quando o método é:

  • GET
  • HEAD
  • POST

Possui E possuir apenas esses headers:

  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type
  • DPR
  • Downlink
  • Save-Data
  • Viewport-Width
  • Width

O E o header Content-Type é:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

Não utiliza ReadableStreamou E não utilizar ReadableStream ou event listeners em XMLHttpRequestUpload.


Porém, em outros casos a requisição OPTIONS de preflight é sempre realizada. São eles:

O método é:

  • PUT
  • DELETE
  • CONNECT
  • OPTIONS
  • TRACE
  • PATCH

Ou se tiver um header diferente de:

  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type
  • DPR
  • Downlink
  • Save-Data
  • Viewport-Width
  • Width

Ou se o header Conten-Type tiver um valor diferente dos listados abaixo:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

Ou se utilizar ReadableStreamou event utilizar ReadableStream ou event listeners in XMLHttpRequestUploadem XMLHttpRequestUpload.

IONIC e CORS

Na versão 5 do Ionic todas as requisições qualificadas nos critérios acima, utilizam o mecanismo de CORS. Para isso, os backends devem estar preparados para responder de maneira correta as requisições do tipo OPTIONS. No caso do Ionic temos duas origens diferentes para cada um dos tipos de plataforma, Android e iOS:

PlataformaOrigem
Androidhttp://localhost
iOSionic://localhost


Para testar se o servidor está com CORS configurado corretamente basta fazer uma requisição POST/PUT/DELETE (não pode GET) em alguma URL da API colocando o Header "Origin" com valor "http://localhost", como por exemplo:


A resposta do servidor deverá possuir em seu header "Access-Control-Allow-Origin" com "http://localhost".


Caso o servidor não responda isso o CORS não está configurado corretamente e ocorrerá erros no login do mobile.

Card
labelCertificado

Certificado SSL é um certificado digital que autentica a identidade de um site e possibilita uma conexão criptografada. O termo "SSL" significa "Secure Sockets Layer" (camada de soquete seguro), um protocolo de segurança que cria um link criptografado entre um servidor Web e um navegador Web.

Empresas e organizações precisam adicionar certificados SSL aos seus sites para proteger as transações on-line e manter a privacidade e a segurança das informações dos clientes.

Verifique o seu certificado

No nosso aplicativo, em ambas plataformas (Android e iOS) utilizamos um browser para renderizar o nosso aplicativo. Isso implica na validação dos certificados assim como em qualquer site que você acessa normalmente por um browser comum. Para verificar se um determinado certificado é válido, recomendamos a validação através de portais como https://www.ssllabs.com/ssltest/ ou https://www.sslshopper.com/ssl-checker.html

Por exemplo, o SSLLabs realiza a geração de um grade/score baseado em uma série de critérios como por exemplo inspeção do certificado e protocolos de criptografia, nos casos abaixo o certificado gratuito ficou grade B, pois nível de criptografia suportado é inferior ao disponível no mercado, nesse link podem ser identificado metodologia de validação: https://github.com/ssllabs/research/wiki/SSL-Server-Rating-Guide


                 



                    


E se o meu certificado estiver inválido?

A tentativa de utilização de certificados inválidos geram erro no processo de handshake na validação das requisições e geração da chave de sessão entre o cliente requisitante e o servidor, consequentemente todas as suas informações não irão trafegar de modo seguro e criptografado pela rede. No exemplo da imagem abaixo, podemos observar que apesar de ser um certificado valido e configurado no server com sua chave privada, o mesmo não está autorizado a ser utilizado de acordo com o SAN, sendo rejeito pelo browsers no momento de negociação da chave de acesso para a sessão de comunicação. Ou seja, não podemos utilizar esse certificado para ser configurado em um IP externo ou mesmo em qualquer outro subdomínio, sendo assim realize essa verificação e validação para um correto funcionamento do ambiente seguro.


Certificados SSL Mobile

As plataformas de dispositivos móveis (IOS, Android) possuem limitações com relação aos certificados digitais. Por padrão, apenas os certificados homologados por elas são reconhecidos como confiáveis. Em geral, as maiores certificadoras são reconhecidas em ambos sistemas operacionais, porém  em caso de dúvidas, procure na sua unidade certificadora para assegurar que seu certificado é homologado para ambas plataformas. Para evitar a aquisição de certificados não homologados e outros problemas relacionados a segurança, é importante consultar a documentação técnica de cada plataforma sobre a lista de certificados reconhecidos como confiáveis:

Plataforma

Como consultar

iOS

A lista de certificados confiáveis para o iOS está disponível em: Certificados confiáveis IOS. (Esse link é constantemente atualizado. Até a data da escrita dessa documentação a versão é a 14).

Além disso, a Apple também instituiu a chamada Política de Transparência de Certificados da Apple, que define algumas diretivas de certificados que são válidos https://support.apple.com/en-us/HT205280.

Para verificar se o seu certificado se enquadra nessa política de transparência, utilize a ferramenta https://sslmate.com/labs/ct_policy_analyzer/.

Android

É necessário verificar no aparelho em: Configurações > Segurança > Credenciais Confiáveis

Na Aba Sistema existe a lista de certificados confiáveis para aquela versão do Android.

Atenção: Cada versão do Android pode ter uma lista de certificados confiáveis diferente.


Alguns sinais são comuns e indicam que o certificado não é válido para utilização em mobile:

  • Consegue se logar em apenas uma das plataformas pelo aplicativo (Android ou iOS)
  • Carregamento com tempo excessivo na tela pós-login até resultar algum erro genérico na tela
  • Ao acessar a URL do portal pelo browser do celular, exibe uma mensagem relacionada a algum problema de segurança:

...