Implementando Login Social
1. Introdução
O que é Login Social?
O login social (ou social sign-in) permite que os usuários acessem sua aplicação usando suas credenciais existentes de uma rede social ou provedor de identidade (por exemplo, Google, Facebook). Em vez de criar uma nova conta e senha para o seu site, eles podem conceder permissão para que o provedor compartilhe suas informações com sua aplicação.
Por que Usar?
- Melhora a Experiência do Usuário: Simplifica o processo de registro e login, reduzindo a fricção para novos usuários.
- Aumenta a Segurança: Aproveita as robustas medidas de segurança dos principais provedores de identidade. Você não precisa armazenar as senhas dos usuários.
- Informações de Perfil: Acessa facilmente dados básicos do perfil (nome, e-mail, foto) para personalizar a experiência do usuário, com o consentimento dele.
2. O Fluxo de Autorização do OAuth 2.0 (Authorization Code Flow)
O método mais comum e seguro para o login social é o OAuth 2.0 Authorization Code Flow. Ele garante que informações sensíveis, como o Client Secret, nunca sejam expostas no navegador do usuário.
Este é um diagrama do fluxo:
sequenceDiagram
participant User as Usuário
participant AppFrontend as Sua App (Frontend)
participant AppBackend as Sua App (Backend)
participant Google
Usuário->>+AppFrontend: Clica em "Login com Google"
AppFrontend->>+Usuário: Redireciona para a Página de Autenticação do Google
Usuário->>+Google: Faz login e concede permissão
Google->>-Usuário: Redireciona de volta para sua app com um Código de Autorização
Usuário->>+AppFrontend: Acessa sua URI de Redirecionamento (ex: /auth/google/callback?code=...)
AppFrontend->>+AppBackend: Envia o Código de Autorização para o backend
AppBackend->>+Google: Troca o Código, Client ID e Client Secret por um Access Token
Google-->>-AppBackend: Retorna o Access Token e o ID Token
AppBackend->>+Google: Usa o Access Token para solicitar informações do usuário
Google-->>-AppBackend: Retorna os dados do perfil do usuário (nome, e-mail, etc.)
AppBackend->>AppBackend: Procura ou cria o usuário no banco de dados
AppBackend-->>-AppFrontend: Estabelece uma sessão (ex: define um cookie JWT)
AppFrontend-->>-Usuário: Usuário agora está logado
3. Implementação Passo a Passo (Google)
Passo 1: Configure seu Projeto no Google Cloud Console
Antes de escrever qualquer código, você precisa registrar sua aplicação no Google e obter suas credenciais.
-
Crie um Projeto:
- Acesse o Google Cloud Console.
- Crie um novo projeto (ex: "Meu App Incrível").
-
Configure a Tela de Consentimento OAuth:
- Na barra lateral, navegue para APIs e Serviços -> Tela de consentimento OAuth.
- Escolha Externo e clique em Criar.
- Preencha as informações necessárias:
- Nome do app: O nome exibido para os usuários.
- E-mail de suporte ao usuário: Seu e-mail.
- Domínios autorizados: O domínio que hospeda sua aplicação (ex:
meuapp.com).
- Na página "Escopos", você pode deixar em branco por enquanto. Solicitaremos os escopos diretamente em nosso código.
- Adicione seu e-mail como um Usuário de teste enquanto seu aplicativo estiver em modo de "Teste".
-
Crie as Credenciais OAuth 2.0:
- Navegue para APIs e Serviços -> Credenciais.
- Clique em Criar Credenciais -> ID do cliente OAuth.
- Selecione Aplicativo da Web como o tipo de aplicativo.
- Adicione URIs de redirecionamento autorizados. Este é um passo crítico. Esta é a URL em sua aplicação para a qual o Google redirecionará o usuário após a autorização. Para desenvolvimento local, você pode adicionar
http://localhost:3000/auth/google/callback. - Clique em Criar.
Você receberá um Client ID e um Client Secret. Copie-os e guarde-os em um lugar seguro.
Aviso de Segurança: O
Client SecretNUNCA deve ser exposto no seu código de frontend ou enviado para o controle de versão. Use variáveis de ambiente no seu servidor de backend para armazená-lo.
Passo 2: Integração no Frontend
O frontend é responsável por iniciar o fluxo de login, redirecionando o usuário para o Google.
Este é um exemplo de um botão "Login com Google" em uma aplicação React.
// Example for a React App
function LoginButton() {
const handleLogin = () => {
const googleAuthUrl = 'https://accounts.google.com/o/oauth2/v2/auth';
const redirectUri = 'http://localhost:3000/auth/google/callback'; // Must match one in your Google Console settings
const scope = [
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile'
].join(' ');
const params = {
response_type: 'code',
client_id: 'YOUR_GOOGLE_CLIENT_ID', // Replace with your Client ID
redirect_uri: redirectUri,
scope: scope,
access_type: 'offline', // Optional: To get a refresh token
state: 'some_random_string_for_csrf_protection' // Important for security!
};
const url = `${googleAuthUrl}?${new URLSearchParams(params)}`;
window.location.href = url;
};
return <button onClick={handleLogin}>Login with Google</button>;
}
Passo 3: Integração no Backend
O backend lida com a troca do código de autorização por um token de acesso e busca os dados do usuário.
Este é um exemplo usando Node.js com Express.
-
Instale as dependências:
npm install express axios -
Crie o endpoint de callback: Esta é a
redirect_urique você configurou.
// Example for a Node.js/Express backend
const express = require('express');
const axios = require('axios');
const app = express();
const port = 3001; // Your backend server port
// Store your credentials securely!
const GOOGLE_CLIENT_ID = process.env.GOOGLE_CLIENT_ID;
const GOOGLE_CLIENT_SECRET = process.env.GOOGLE_CLIENT_SECRET;
const REDIRECT_URI = 'http://localhost:3000/auth/google/callback';
app.get('/auth/google/callback', async (req, res) => {
const { code } = req.query;
if (!code) {
return res.status(400).send('Authorization code not found.');
}
try {
// 1. Exchange authorization code for access token
const tokenResponse = await axios.post('https://oauth2.googleapis.com/token', null, {
params: {
code,
client_id: GOOGLE_CLIENT_ID,
client_secret: GOOGLE_CLIENT_SECRET,
redirect_uri: REDIRECT_URI,
grant_type: 'authorization_code',
},
});
const { access_token, id_token } = tokenResponse.data;
// 2. Use access token to get user info
const userResponse = await axios.get('https://www.googleapis.com/oauth2/v2/userinfo', {
headers: {
Authorization: `Bearer ${access_token}`,
},
});
const { email, name, picture } = userResponse.data;
// 3. Find or create user in your database
// let user = await User.findOne({ email });
// if (!user) {
// user = await User.create({ email, name, googleId: userResponse.data.id });
// }
// 4. Create a session (e.g., using JWT) and send it to the client
// const token = createJwt(user);
// res.cookie('auth_token', token).redirect('http://localhost:3000/dashboard');
res.json({
message: "Login successful!",
user: { email, name, picture },
tokens: { access_token, id_token }
});
} catch (error) {
console.error('Error during Google OAuth flow:', error.response?.data || error.message);
res.status(500).send('An error occurred during login.');
}
});
app.listen(port, () => {
console.log(`Backend server listening on port ${port}`);
});
4. Considerações de Segurança
- Parâmetro
state: Use um parâmetrostateúnico e imprevisível em sua requisição de autorização inicial. Armazene-o na sessão do usuário e verifique se ostateretornado pelo Google no callback corresponde ao que você enviou. Isso previne ataques de Cross-Site Request Forgery (CSRF). - Armazenamento de Tokens: No backend, armazene os refresh tokens de forma segura (por exemplo, criptografados em seu banco de dados). Os access tokens têm vida curta e podem ser armazenados em memória ou em um cache de acesso rápido.
- Manuseio de Tokens no Frontend: Não armazene tokens no
localStorage. Se precisar fazer chamadas de API autenticadas a partir do frontend, use um cookie seguro comHttpOnlypara armazenar um token de sessão (como um JWT) que seu backend fornece após um login bem-sucedido.
5. Conclusão
Implementar o login social com o OAuth 2.0 Authorization Code Flow é uma maneira segura e amigável de lidar com a autenticação. Ao delegar o processo de login a um provedor confiável como o Google, você simplifica o desenvolvimento e aumenta a segurança de sua aplicação. A chave é garantir que as credenciais sejam mantidas em segredo no backend e seguir as melhores práticas de segurança, como o uso do parâmetro state.
