Ionic & Angular: Fazendo o CORS seu amigo

Se esse post chamou sua atenção, com certeza você já teve ou ainda tem problemas com o CORS. Meu objetivo aqui é mostrar a importância desse mecanismo de segurança e como fazer o seu uso de forma consciente e clara.

Antes de criticarmos ou falar que algo é ruim, é bom entendermos o motivo pelo qual aquilo existe.

Porque o CORS existe?

O CORS (do inglês cross-origin resource sharing) é um mecanismo que permite que os conteúdos de domínios diferentes sejam compartilhados. Ele existe para evitar que o conteúdo de um determinado domínio seja utilizado por outro sem a autorização do mesmo.

Exemplo: supondo que eu queira exibir os conteúdos do youtube em meu site, faço uma análise das requisições HTTP’s feitas pelo youtube, obtendo os parâmetros da chamada criaria uma UI para usar as informações do youtube, tirando assim proveiro dos dados deles. O CORS impediria que essa ação fosse executada na camada do navegador, ou seja é uma segurança para você!

Como funcionar o CORS?

O CORS vai analisar se o recurso que você tenta carregar está sob o mesmo domínio e porta. Com isso mesmo que você tenha sua API rodando no endereço “http://localhost:8080” e sua aplicação ionic/angular rodando em suas respectivas portas (8100/4200) ao chamar a API com toda certeza vai ter sua requisição bloqueada e vai receber a mensagem de CORS.

Quando você não está sob o mesmo domínio você vai notar na parte de redes que uma requisição http gera 2 outras chamadas. A primeira chamada usa o verbo http OPTIONS, ele é utilizado pelo navegador para perguntar ao  seu servidor/aplicação quais os tipos de requisição sua aplicação permite e é no OPTIONS que você deve informar suas configurações do CORS através de Headers.

Opções para o CORS

  1. Access-Control-Allow-Origin: Header utilizado para informar quais domínios você permite que use o seu conteúdo.
  2. Access-Control-Allow-Methods: Header utilizado para informar quais verbos http você permite a partir dos domínios liberados.
  3. Access-Control-Allow-Headers: Header utilizado para informar quais “Headers” os domínios liberados podem enviar para você.
  4. Access-Control-Max-Age: Header utilizado para informar quanto tempo é válido essas configurações de CORS.

O que não devo fazer?

[wp_ad_camp_3]

Bom acho que a primeira coisa que você deve se questionar é: Preciso realmente liberar o CORS em seu ambiente? Mesmo em aplicações ionic a liberação não é necessária. O mesmo para Angular, vendo que em produção o domínio será o mesmo (ou não rs).

Mas vamos lá, supondo que você chegou a conclusão que liberar o CORS é realmente necessário, não faça isso “Access-Control-Allow-Origin: *” ao fazer isso você está simplesmente tirando uma camada de segurança que foi criada para você. Caso você esteja rodando uma aplicação ionic (já compilada), não é necessário liberar o CORS mas caso queira liberar é necessário apenas  permitir o endereço http://localhost:8080/ que é o endereço que o ionic utiliza para carregar sua aplicação compilada ou seja a liberação correta (caso deseje fazer) é “Access-Control-Allow-Origin: http://localhost:8080“.

Outra coisa bem importante é o Access-Control-Max-Age geralmente nos tutoriais ninguém comenta sobre ele. Lembra aquela segunda requisição? A do tipo OPTIONS, então ela é feita quando expira o Access-Control-Max-Age então se você não falar para o navegador que essas definições só mudam de X em X tempos todo e qualquer request que você fizer o seu servidor vai receber duas requisições (cada browser tem seu tempo padrão). Em ambiente de desenvolvimento, geralmente desabilitamos os cache’s e com isso o Access-Control-Max-Age não vai fazer efeito. Mas em ambiente de produção é algo muito importante.

Como assim não preciso liberar o CORS para o ionic?

Sim é isso mesmo, não precisa! E já vou explicar o motivo. Quando você desenvolve seu aplicativo, você geralmente testa seu projeto seu navegador e ele implementa o Same-Origin-Policy por isso que você tem problemas com CORS e acaba fazendo tudo quanto é tipo de liberação. Porém quando o seu aplicativo é compilado para APK ou IPA o ionic de forma nativa consegue desabilitar o CORS da WebView (e eles já fazem isso).

Vale lembrar que para o iOS o ionic sempre usou o UIWebView só que agora eles migraram para o MKWebView e no iOS eles não conseguem desabilitar o CORS nessa webview em especifico =/. Então ou você faz um downgrade da webview, ou você libera o CORS para a origem “http://localhost:8080” ai é uma decisão pessoal, basta acessar a documentação com as melhorias propostas pela MKWebView e colocar na balança.

Para fazer o downgrade da WebView basta colocar o conteúdo abaixo em seu config.xml para a plataforma iOS:


<preference name="CordovaWebViewEngine" value="CDVUIWebViewEngine" />

E meu ambiente de desenvolvimento, como faço?

Então para você desabilitar a checagem do CORS em seu ambiente de desenvolvimento você pode fazer uso de uma extensão do google chrome mas eu não recomendo, tive muitos problemas com essa extensão. Ela liberou o CORS mas sempre me trouxe problema com encodings em outros sites que eu acessava.

Não quer usar a extensão?

Então vamos lá, o ionic e o angular tem um recurso bem interessante e muito pouco conhecido que tem exatamente essa função (impedir problemas com CORS) são os proxies.  É algo bem simples, mas eles são apenas para ambientes de desenvolvimento. Então não se esqueça de criar uma configuração para seu endpoint  🙂

O que é um proxy? Como ele funciona?

Um proxy basicamente é um serviço intermediário entre você e seu servidor de aplicação, ele recebe sua requisição e repassa ela para o servidor original.

Vamos criar o seguinte cenário: Tenho a url (http://localhost:8888/) rodando um backend, então vamos criar um mapeamento para informar que tudo que for chamado na uri /api seja passado para o backend.

Vamos supor que você esteja desenvolvendo em uma aplicação ionic, ao digitar o endereço http://localhost:8100/api/criar-usuario ele vai redirecionar internamente no processo do ionic serve a requisição para http://localhost:8888/criar-usuario então sua aplicação vai estar chamando uma URL que está no mesmo domínio e na mesma porta assim a Same-Origin-Policy não vai ser aplicada e você pode seguir seu desenvolvimento sem necessidade de liberar o CORS para desenvolver.

Configurando o proxy no ionic

[wp_ad_camp_2]

Para configurar o proxy no ionic basta abrir o arquivo ionic.config.json e criar uma nova propriedade chamada proxies e nela definir seus paths.

Exemplo:

{
	"name": "app-meuapp",
	"app_id": "",
	"type": "ionic-angular",
	"proxies": [{
		"path": "/api",
		"proxyUrl": "http://localhost:8888/"
	}],
	"integrations": {
		"cordova": {}
	}
}

Configurando o proxy no Angular

Para fazer a configuração de seu proxy no Angular o processo é semelhante. Para isso é necessário criar um arquivo JSON com as configurações os paths desejados. Então vamos criar o arquivo proxy.conf.json e vamos colocar o conteúdo abaixo. Após isso basta você inicializar seu projeto com o comando ng serve –proxy-config proxy.conf.json.

Observação: Recomendo que coloque esse comando na chave start do package.json assim você só vai precisar rodar o comando npm start

Conteúdo para o proxy.conf.json

{
  "/api": {
    "target": "http://localhost:8888",
    "secure": false
  }
}

Conclusão

[wp_ad_camp_1]

O CORS é um recurso de segurança muito importante e precisamos gerenciar ele de acordo com as necessidades do nosso projeto, fazendo o uso das técnicas mencionadas nesse post é possível trabalhar sem dor de cabeça e claro ter um desenvolvimento saudável e seguro.

Comments

  1. Bruno

    Olá, Higor!
    Muito bacana o post, consegui entender bem o problema.
    Acontece que optei por liberar o CORS para o http://localhost:8080 e ainda assim não funcionou.
    O curioso é que quando libero para todos os domínios, funciona corretamente.
    Sabe se a porta que o ionic usa mudou?
    Muito obrigado!

    1. Post
      Author
      Hiago Souza

      Bom dia Bruno tudo bem? A porta 8080 é quando o app está compilado, caso você esteja rodando o ionic no seu browser em modo de desenvolvimento a porta utilizada será a partir da porta 8100. Eu não vi como tá a nova versão do ionic, então se estiver utilizando ela pode ser que realmente tenha mudado algo por conta do capacitor. Mas vou ver isso para você, onde acontece o erro? No dispositivo ou no seu navegador (utilizando o ionic serve)?

      1. Bruno

        Hiago, perdão por errar seu nome. Acontece em ambos. Quando faço o proxy para a porta 8100, roda certinho no browser, mas quando mudo para a porta 8080 e mando rodar no android real, simplesmente não vai. Quando libero totalmente, todos conseguem acessar…

        1. Post
          Author
          Hiago Souza

          Sem problemas Bruno, acontece ;)!! A configuração de proxy é válida apenas para ambiente de desenvolvimento. Quando compila o App o proxy do node não é considerado, você pode inspecionar o webview do aplicativo rodando utilizando a url “chrome://inspect” (isso com o dispositivo plugado no computador). Veja qual erro aparece no console e me encaminhe aqui. As vezes a porta local onde o app roda foi modificada nas versões recentes do ionic.

  2. Vinicius Araujo

    Olá,
    Estou desenvolvendo um app que tratei o problema de cors com a configuração de proxy o que faz tudo funcionar direitinho no meu navegador. Fui testar no dispositivo real através do apk e não funciona. Rodei no inspect para ver o que estava ocorrendo e minha requisição traz 200 ok mas como body vazio. Coloquei para acessar a requisição direto da url da api que preciso pegar as informações e caiu no cors de novo (XMLHttpRequestProgressEvent). Pode me ajudar com isso?

    1. Post
      Author
      1. Vinicius Araujo

        Olá Hiago, infelizmente não tenho permissão de compartilhar a URL. Eu estou usando a versão 4.2.1. Em resumo, o problema que tenho é de que o apk não faz as requisições e debugando apareceu o problema de cors. No navegador roda direitinho com o proxy configurado, já no dispositivo não roda nem com proxy e nem sem proxy.

        1. Post
          Author
          Hiago Souza

          Vinicius, considere fazer a liberação de CORS nesse caso. O proxy é apenas em desenvolvimento, na versão 4 eu não sei se houve alguma mudança nisso, eles mudaram do Cordova para o Capacitor talvez o melhor seja você fazer a liberação do CORS no seu endpoint.

  3. André B.

    Hiago, boa noite.

    Estou com esse problema de cors quando gero o apk e jogo celular. já usei o inspect.

    1. Post
      Author
      1. André Bessa

        Hiago, bom dia!

        Consegui resolver, estou usando o Ionic v3. Meu problema estava no servidor ajustei o CORS lá e funcionou beleza.
        Muito obrigado!

  4. Rafael Moura

    Noa noite Hiago, estou com uma dúvida, não consegui resolve essa questão, tenho minha aplicação Laravel/Angular, tudo certo por lá, consigo integrar a fazer as requisições de boa, mas no ionic (v4), fiz de tudo e ele cai justamente nesse problema com o CORS, por ex, minha API é assim: http://127.0.0.1:8000/api/v1/login, detalhe, eu estou rodando no “lab” do Ionic na porta 8200 (abre automaticamente) e ele dá problema na 8100, olha o erro:

    Access to XMLHttpRequest at ‘http://127.0.0.1:8000/api/v1/login’ from origin ‘http://localhost:8100’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

    1. Post
      Author
      Hiago Souza

      Olá Rafael, no ionic 4 você já pode fazer uso dos proxies do angular se não me engano. Eu vou criar um novo post sobre o assunto e associo com esse beleza?

  5. Santos

    Olá Hiago por gentileza poderia me dar uma ajuda

    olha instalei osclass tudo correu certo porem noto que ao abrir a pagina principal sempre abre como pagina insegura a partir de qualquer outro click fica Pagina segura inspecionado o doc descobri que estes erros
    procurei então por todo código e pastas a fim de editar esse HTTP para HTTPS para resolver mas não encontro nada ai pesquisei e vi que se trata de algo parecido ou igual a este aqui deste post mas não sei com o resolver posso mostrar os erros

    1. Post
      Author
  6. Post
    Author
    Hiago Souza

    Santos, não precisa de liberar o Cors no seu caso. Basta você utilizar o mesmo protocolo para receber os arquivos. Você tá acessando o site via http e importando os recursos com https. Ao invés de colocar http:// ou https:// coloque apenas // que ele assume o mesmo protocolo utilizado para acessar a página. Vale lembrar que isso só funciona pra vc porque é o mesmo domínio e o Cors tá ocorrendo por conta de não estar acessando do mesmo protocolo http/https.

  7. Santos

    Ok ! entendi decupa…vasculhei todo script para encontrar o local onde apontou o erro e tentar editar mas nã achei em lugar algum
    poderia me dizer no caso em qual pasta devo editar isso? pois o caminho me leva na pasta de font e lá não tem nada que eu possa editar obrigado

    1. Post
      Author
  8. Miguel Rios

    Estimado Hiago Souza. Tengo un enrome problema y es por temas de CORS. Mi version de Ionic es 5 y estoy accediendo localmente a un servicio a una api estatal, pero me sale problemas de CORS. Y esta app va a ser una app publica. ¿Como puedo solucionar el problema? Ya intente ponerle un proxy y probarlo en un dispositivo pero no me ha funcionado y estoy desesperado.

    1. Post
      Author
      Hiago Souza

      Hola miguel

      ¿Cómo estás?
      ¿Puedes compartir la URL de esta API?

      Si no tiene acceso al código fuente, es necesario implementar un proxy en su BackEnd y esto hará la llamada por usted.

      (Aplicación) => (Su Proxy, el cors va aquí) => (API pública)

  9. Igor Assis

    Olá Iago. Excelente artigo! Eu tenho uma dificuldade e sinceramente estou com dificuldade em saber a direção certa que devo seguir. Gostaria de saber se vc pode me orientar. Estou tentando incorporar no meu app ionic v1 um iframe cuja origem eh o um site HTTPS. No Android funciona fino. No Ios o safari apresenta o seguinte erro : Blocked a frame with origin “https://www.meusite.com” from accessing a frame with origin “http://localhost:8100”. The frame requesting access has a protocol of “https”, the frame being accessed has a protocol of “http”. Protocols must match. Deveria criar um Proxy para esse HTTPS ou compreendi errado? Mto obrigado de antemão

    1. Post
      Author
      Hiago Souza

      Olá Igor, perdoe a demora. Tive que me ausentar do blog durante um periodo… Qual é o seu backend? O proxy com ionic é para resolver esse BO no ambiente de desenvolvimento, para a sua produção é necessário configurar o CORS no seu WebServer e caso possível na sua própria LP.

    1. Post
      Author
    1. Post
      Author

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *