Neste artigo, vemos como habilitar o CORS (Cross-Origin Resource Sharing) com o cookie HTTPOnly para proteger nossos tokens de acesso.
Atualmente, servidores de back-end e clientes de front-end são implantados em diferentes domínios. Portanto, o servidor precisa habilitar o CORS para permitir que os clientes se comuniquem com o servidor nos navegadores.
Além disso, os servidores estão implementando autenticação sem estado para melhor escalabilidade. Os tokens são armazenados e mantidos no lado do cliente, mas não no lado do servidor, como na sessão. Por segurança, é melhor armazenar tokens em cookies HTTPOnly.
Por que as solicitações Cross-Origin são bloqueadas?
Vamos supor que nosso aplicativo de front-end implantado em https://tecnologico.online
. Um script carregado em https://tecnologico.online
só pode solicitar recursos de mesma origem.
Sempre que tentamos enviar uma solicitação de origem cruzada para outro domínio https://tecnologico.online
ou outra porta https://tecnologico.online:3000
ou outro esquema https://tecnologico.online
a solicitação de origem cruzada será bloqueada pelo navegador.
Mas por que a mesma solicitação bloqueada pelo navegador pode ser enviada de qualquer servidor de back-end usando a solicitação curl ou enviada usando ferramentas como o carteiro sem nenhum problema de CORS. Na verdade, é para segurança proteger os usuários de ataques como CSRF (Cross-Site Request Forgery).
Vamos dar um exemplo, suponha que algum usuário tenha feito login em sua própria conta do PayPal em seu navegador. Se pudermos enviar uma solicitação de origem cruzada para paypal.com
de um script carregado em outro domínio malicious.com
sem nenhum erro/bloqueio de CORS como enviamos a solicitação de mesma origem.
Atacantes podem facilmente enviar sua página maliciosa https://malicious.com/transfer-money-to-attacker-account-from-user-paypal-account
convertendo-o em URL curto para ocultar o URL real. Quando o usuário clica em um link malicioso, o script carregado no domínio malicious.com
enviará uma solicitação de origem cruzada ao PayPal para transferir o valor do usuário para a conta do PayPal do invasor. Todos os usuários que fizeram login em suas contas do PayPal e clicaram neste link malicioso perderão seu dinheiro. Qualquer pessoa pode facilmente roubar dinheiro sem o conhecimento de um usuário de conta do PayPal.
Pelo motivo acima, os navegadores bloqueiam todas as solicitações de origem cruzada.
O que é CORS (Compartilhamento de recursos entre origens)?
CORS é um mecanismo de segurança baseado em cabeçalho usado pelo servidor para instruir o navegador a enviar uma solicitação de origem cruzada de domínios confiáveis.
O servidor ativado com cabeçalhos CORS usados para evitar solicitações de origem cruzada bloqueadas por navegadores.
Como o CORS funciona?
Como o servidor já definiu seu domínio confiável em sua configuração CORS. Quando enviamos uma solicitação ao servidor, a resposta informará ao navegador se o domínio solicitado é confiável ou não em seu cabeçalho.
Existem dois tipos de solicitações CORS:
- Pedido simples
- Solicitação de simulação
Pedido Simples:
- O navegador envia a solicitação para um domínio de origem cruzada com origin(https://tecnologico.online).
- O servidor envia de volta a resposta correspondente com métodos permitidos e origem permitida.
- Após receber a solicitação, o navegador verificará o valor do cabeçalho de origem enviado (https://tecnologico.online ) e recebeu o valor access-control-allow-origin (https://tecnologico.online ) são iguais ou curinga
. Caso contrário, ele lançará um erro de CORS.
- CORS-Preflight Request Imagem que mostra o fluxo da solicitação de origem cruzada com a solicitação de simulação OPTIONS antes de enviar a solicitação real para verificação de cabeçalhos.
- Dependendo do parâmetro de solicitação personalizada da solicitação de origem cruzada, como métodos (PUT, DELETE) ou cabeçalhos personalizados ou tipo de conteúdo diferente, etc. O navegador decidirá enviar uma solicitação OPTIONS de comprovação para verificar se a solicitação real é segura para enviar ou não. Depois de receber a resposta (código de status: 204, que significa sem conteúdo), o navegador verificará o controle de acesso-permitir
parâmetros para a solicitação real. Se os parâmetros de solicitação forem permitidos pelo servidor. A solicitação de origem cruzada real enviada e recebida access-control-allow-origin: *
Se
, então a resposta é permitida para todas as origens. Mas não é seguro, a menos que você precise.
Como ativar o CORS?
Para ativar o CORS para qualquer domínio, ative os cabeçalhos CORS para permitir origem, métodos, cabeçalhos personalizados, credenciais etc.
- O navegador lê o cabeçalho CORS do servidor e permite solicitações reais do cliente somente após verificar os parâmetros da solicitação. Acesso-Controle-Permitir-Origem:
- Para especificar domínios exatos (https://tecnologico.online, https://tecnologico.online) ou curinga
- Acesso-Controle-Permitir-Métodos: Para permitir os métodos HTTP (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS) que só precisamos.
- Acesso-Controle-Permitir-Cabeçalhos: Para permitir apenas cabeçalhos específicos (autorização, csrf-token)
- Acesso-Controle-Permitir-Credenciais: Valor booleano usado para permitir credenciais de origem cruzada (cookies, cabeçalho de autorização).
- Controle de Acesso-Max-Idade: Diz ao navegador para armazenar em cache a resposta de simulação por algum tempo.
Acesso-Controle-Exposição-Cabeçalhos: Especifique os cabeçalhos que são acessíveis pelo script do lado do cliente. Para habilitar o CORS no servidor Apache e Nginx, siga este
tutorial
. Habilitando o CORS no ExpressJS Vamos dar um exemplo
const express = require('express');
const app = express()
app.get('/users', function (req, res, next) {
res.json({msg: 'user get'})
});
app.post('/users', function (req, res, next) {
res.json({msg: 'user create'})
});
app.put('/users', function (req, res, next) {
res.json({msg: 'User update'})
});
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
ExpressJS
aplicativo sem CORS: No exemplo acima, ativamos o endpoint da API dos usuários para os métodos POST, PUT, GET, mas não para o método DELETE.
npm install cors
Para facilitar a ativação do CORS no aplicativo ExpressJS, você pode instalar o
núcleos
app.use(cors({
origin: '*'
}));
Acesso-Controle-Permitir-Origem
app.use(cors({
origin: 'https://tecnologico.online'
}));
Ativando o CORS para todos os domínios Ativando o CORS para um único domínio Se você deseja permitir CORS para origem https://tecnologico.online
app.use(cors({
origin: (
'https://tecnologico.online',
'https://tecnologico.online'
)
}));
e
app.use(cors({
origin: (
'https://tecnologico.online',
'https://tecnologico.online'
),
methods: ('GET', 'PUT', 'POST')
}));
Acesso-Controle-Permitir-Métodos
Para habilitar CORS para todos os métodos, omita esta opção no módulo CORS no ExpressJS. Mas para habilitar métodos específicos (GET, POST, PUT).
app.use(cors({
origin: (
'https://tecnologico.online',
'https://tecnologico.online'
),
methods: ('GET', 'PUT', 'POST'),
allowedHeaders: ('Content-Type', 'Authorization', 'x-csrf-token')
}));
Acesso-Controle-Permitir-Cabeçalhos
Usado para permitir que cabeçalhos diferentes dos padrões sejam enviados com solicitações reais. Acesso-Controle-Permitir-Credenciais Omita isso se não quiser instruir o navegador a permitir credenciais mediante solicitação, mesmo emcomCredenciais
app.use(cors({
origin: (
'https://tecnologico.online',
'https://tecnologico.online'
),
methods: ('GET', 'PUT', 'POST'),
allowedHeaders: ('Content-Type', 'Authorization', 'x-csrf-token'),
credentials: true
}));
está definido como verdadeiro
.
app.use(cors({
origin: (
'https://tecnologico.online',
'https://tecnologico.online'
),
methods: ('GET', 'PUT', 'POST'),
allowedHeaders: ('Content-Type', 'Authorization', 'x-csrf-token'),
credentials: true,
maxAge: 600
}));
Acesso-Controle-Max-Idade
Para intimar o navegador a armazenar em cache as informações de resposta de simulação no cache por um segundo especificado. Omita isso se não quiser armazenar em cache a resposta.
app.use(cors({
origin: (
'https://tecnologico.online',
'https://tecnologico.online'
),
methods: ('GET', 'PUT', 'POST'),
allowedHeaders: ('Content-Type', 'Authorization', 'x-csrf-token'),
credentials: true,
maxAge: 600,
exposedHeaders: ('Content-Range', 'X-Content-Range')
}));
A resposta de simulação em cache ficará disponível por 10 minutos no navegador. Acesso-Controle-Exposição-Cabeçalhos Se colocarmos o curinga
app.use(cors({
origin: (
'https://tecnologico.online',
'https://tecnologico.online'
),
methods: ('GET', 'PUT', 'POST'),
allowedHeaders: ('Content-Type', 'Authorization', 'x-csrf-token'),
credentials: true,
maxAge: 600,
exposedHeaders: ('*', 'Authorization', )
}));
no
cabeçalhos expostos,
ele não exporá o cabeçalho de autorização. Portanto, temos que expor explicitamente como abaixo
O acima irá expor todos os cabeçalhos e o cabeçalho de autorização também.
- O que é um cookie HTTP? Um cookie é um pequeno pedaço de dados que o servidor enviará ao navegador do cliente. Em solicitações posteriores, o navegador enviará todos os cookies relacionados ao mesmo domínio em todas as solicitações.
- Cookie tem seu atributo, que pode ser definido para fazer com que um cookie funcione de maneira diferente conforme a nossa necessidade. Nome
- Nome do biscoito. valor:
- dados do cookie relativos ao cookie-name Domínio:
- os cookies serão enviados apenas para o domínio definido Caminho:
- cookies enviados somente após o caminho de prefixo de URL definido. Suponha que definimos nosso caminho de cookie como path=’admin/’. Cookies não enviados para o URL https://tecnologico.online/, mas enviados com o prefixo do URL https://tecnologico.online/admin/ Max-Age/Expires(número em segundos):
- Quando o cookie deve expirar. A vida útil do cookie torna o cookie inválido após o tempo especificado. HTTPOnly(Booleano):
- O servidor de back-end pode acessar esse cookie HTTPOnly, mas não o script do lado do cliente quando verdadeiro. Seguro (Booleano):
sameSite
Cookies enviados apenas por um domínio SSL/TLS quando verdadeiros. sameSite(string (Strict, Lax, None)): Usado para ativar/restringir cookies enviados em solicitações entre sites. Para saber mais detalhes sobre cookies
Vejo
MDN . Ele aceita três opções Strict, Lax, None. Valor seguro do cookie definido como true para a configuração do cookie sameSite=None. Por que HTTPOnly cookie para tokens? Armazenar o token de acesso enviado do servidor no armazenamento do lado do cliente, como armazenamento local , banco de dados indexado, e bolacha
(HTTPOnly não definido como verdadeiro) são mais vulneráveis a
ataque XSS
. Suponha que qualquer uma de suas páginas seja fraca para um ataque XSS. Os invasores podem fazer uso indevido de tokens de usuário armazenados no navegador.
Os cookies HTTPOnly são definidos/obtidos apenas pelo servidor/back-end, mas não no lado do cliente.
- Script do lado do cliente restrito para acessar esse cookie HTTPonly. Portanto, os cookies HTTPOnly não são vulneráveis a ataques XSS e são mais seguros. Porque só é acessível pelo servidor.
- Habilitar cookie HTTPOnly no back-end habilitado para CORS
- A ativação do Cookie no CORS requer a configuração abaixo no aplicativo/servidor.
- Defina o cabeçalho Access-Control-Allow-Credentials como verdadeiro.
Access-Control-Allow-Origin e Access-Control-Allow-Headers não devem ser curingas
const express = require('express');
const app = express();
const cors = require('cors');
app.use(cors({
origin: (
'https://tecnologico.online',
'https://tecnologico.online'
),
methods: ('GET', 'PUT', 'POST'),
allowedHeaders: ('Content-Type', 'Authorization', 'x-csrf-token'),
credentials: true,
maxAge: 600,
exposedHeaders: ('*', 'Authorization' )
}));
app.post('/login', function (req, res, next) {
res.cookie('access_token', access_token, {
expires: new Date(Date.now() + (3600 * 1000 * 24 * 180 * 1)), //second min hour days year
secure: true, // set to true if your using https or samesite is none
httpOnly: true, // backend only
sameSite: 'none' // set to none for cross-request
});
res.json({ msg: 'Login Successfully', access_token });
});
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
});
.
O atributo cookie sameSite deve ser Nenhum. Para ativar o valor sameSite como nenhum, defina o valor seguro como verdadeiro: Habilitar back-end com certificado SSL/TLS para funcionar no nome de domínio. Vejamos um exemplo de código que define um token de acesso no cookie HTTPOnly após verificar as credenciais de login.
Você pode configurar cookies CORS e HTTPOnly implementando as quatro etapas acima em seu idioma de back-end e servidor da web.
você pode seguir isso
tutorial
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://tecnologico.online/', true);
xhr.withCredentials = true;
xhr.send(null);
para apache e Nginx para ativar o CORS seguindo as etapas acima.
fetch('https://tecnologico.online/', {
credentials: 'include'
});
withCredentials for Cross-Origin request
$.ajax({
url: 'https://tecnologico.online/',
xhrFields: {
withCredentials: true
}
});
Credenciais (Cookie, Autorização) enviadas com a solicitação de mesma origem por padrão. Para origem cruzada, temos que especificar withCredentials como true.
axios.defaults.withCredentials = true
API XMLHttpRequest
API de busca
JQuery AjaxAxiosConclusão Espero que o artigo acima ajude você a entender como o CORS funciona e habilite o CORS para solicitações de origem cruzada no servidor. Por que armazenar cookies em HTTPOnly é seguro e como withCredentials é usado em clientes para solicitações de origem cruzada.