Steam OAuth e Telegram OAuth com Casdoor: Adicionando Logins Sociais Não-Padrão Através de OIDC
Não existe "Steam OAuth": o Steam autentica usuários com OpenID 2.0 e fornece um SteamID de 64 bits, nada além disso. O Login Widget clássico do Telegram também não é OAuth: ele entrega à sua página um conjunto de campos de usuário mais um hash HMAC-SHA256 que você verifica com o token do seu bot. O Telegram agora também executa um provedor real de OpenID Connect em oauth.telegram.org. Se você colocar o Casdoor entre sua aplicação e esses provedores, o Casdoor faz as verificações específicas do protocolo e sua aplicação só conversa com o Casdoor usando OpenID Connect, da mesma forma que faria com Google ou GitHub.
Os provedores em um relance
| Provedor | Protocolo | O que identifica o usuário | Email disponível? | Tipo de provedor do Casdoor |
|---|---|---|---|---|
| Steam | OpenID 2.0 em https://steamcommunity.com/openid/login, mais a API Web do Steam para o perfil | SteamID64, obtido do ID reivindicado https://steamcommunity.com/openid/id/<steamid> | Não | Steam |
| Telegram (Login Widget) | Dados do widget assinados, HMAC-SHA256 com chave derivada do SHA-256 do token do bot | id do usuário do Telegram | Não | Telegram |
| Telegram (OpenID Connect) | Fluxo de código de autorização OIDC com PKCE em https://oauth.telegram.org | Claim sub do token de ID | Sem claim de email; telefone com o escopo phone | Custom |
| X (Twitter) | Código de autorização OAuth 2.0 com PKCE | ID de usuário do X de /2/users/me | Não com os escopos padrão do Casdoor | Twitter |
| Código de autorização OAuth 2.0 | ID de usuário escopado pela aplicação | Apenas se o perfil tiver um email primário válido | Facebook |
O restante deste post passa pelo que cada protocolo realmente retorna e o que o Casdoor faz com isso.
Steam: OpenID 2.0, sem OAuth
As páginas de desenvolvedores do Steam descrevem o Steam como um provedor OpenID: seu site envia o usuário para o Steam, e o Steam devolve um ID reivindicado no formato https://steamcommunity.com/openid/id/<steamid>. O número no final é o SteamID de 64 bits do usuário. Não há código de autorização, token de acesso, escopos nem email: nem a resposta do OpenID nem o perfil da API Web contêm um.
É por isso que buscas por "steam oauth" não levam a lugar útil: o protocolo é OpenID 2.0, predecessor do OpenID Connect, então uma biblioteca cliente de OAuth 2.0 ou OIDC não pode falar diretamente com o Steam.
O que o Casdoor faz para um login via Steam:
- A página de login do Casdoor constrói uma solicitação
checkid_setupde OpenID 2.0 parahttps://steamcommunity.com/openid/login, comopenid.realmdefinido como a origem do Casdoor eopenid.return_todefinido como a página/callbackdo Casdoor. - Quando o Steam redireciona de volta, o Casdoor posta os campos assinados de volta para o Steam com
openid.mode=check_authentication. Somente se o Steam responderis_valid:trueele continua. Ele também verifica seopenid.claimed_idcorresponde ao padrãosteamcommunity.com/openid/id/<digits>e extrai o SteamID dele. - Com a chave da API Web do Steam que você insere como Client secret do provedor, o Casdoor chama
ISteamUser/GetPlayerSummariespara obter o nome de persona e o avatar.
O usuário resultante do Casdoor tem o SteamID64 como nome de usuário, o nome da persona do Steam como nome de exibição e o avatar do Steam. O campo de e-mail permanece vazio. O Casdoor remove intencionalmente o texto de placeholder que a biblioteca subjacente coloca lá. Se sua aplicação precisar de um endereço de e-mail, colete-o após o cadastro.
A configuração leva dois minutos: registre uma chave de API Web para o domínio do seu Casdoor na página de chaves da Steam, crie um provedor do tipo Steam e cole a chave como segredo do cliente. O guia do provedor Steam tem os passos.
Telegram: o Widget de Login e sua verificação HMAC
O login clássico do Telegram é um widget JavaScript. Você cria um bot com @BotFather, vincula seu domínio a ele com /setdomain e incorpora o widget. Quando o usuário confirma no Telegram, o widget redireciona para a URL em data-auth-url ou chama uma função JavaScript, passando id, first_name, last_name, username, photo_url, auth_date e hash.
Nada nesse payload é um token. Qualquer pessoa pode digitar esses campos em uma URL, então o servidor deve verificar o hash. A verificação documentada pelo Telegram funciona assim:
data_check_string = all received fields except hash,
as key=value, sorted by key, joined with "\n"
secret_key = SHA256(bot_token)
valid = hex(HMAC_SHA256(data_check_string, secret_key)) == hash
O Telegram também recomenda verificar auth_date para que dados antigos não possam ser reproduzidos, mas deixa a janela de tempo por sua conta.
No Casdoor, o tipo de provedor Telegram usa o nome de usuário do bot (sem @) como Client ID e o token do bot como Client secret. Quando um usuário clica no botão do Telegram, o Casdoor abre sua própria página /telegram-login, que carrega telegram-widget.js de telegram.org com o nome de usuário do seu bot e aponta data-auth-url de volta para o /callback do Casdoor. O callback coleta os campos e o backend do Casdoor então:
- reconstrói a string de verificação de dados a partir de todos os campos exceto
hash, ordena-a e compara o HMAC-SHA256 contrahashusandoSHA256(bot token)como chave; - rejeita os dados se
auth_datetiver mais de 24 horas; - usa o
idnumérico do Telegram como identidade, ousernamecomo nome de usuário, o primeiro e último nome como nome de exibição, ephoto_urlcomo avatar.
Os nomes de usuário do Telegram são opcionais. Quando um usuário não possui um, o Casdoor gera telegram_<id>, que permanece o mesmo em cada login. O widget nunca envia um endereço de e-mail ou número de telefone, portanto, um usuário apenas do Telegram no Casdoor não possui nenhum dos dois. Veja o guia do provedor Telegram para os passos do BotFather.
O Telegram agora oferece OpenID Connect também
A página "Log In With Telegram" do Telegram agora documenta um fluxo padrão OpenID Connect, e a documentação antiga do widget iframe foi movida para uma página de arquivo. Os fatos da documentação do Telegram:
- Documento de descoberta:
https://oauth.telegram.org/.well-known/openid-configuration. Endpoint de autorizaçãohttps://oauth.telegram.org/auth, endpoint de tokenhttps://oauth.telegram.org/token, chaves emhttps://oauth.telegram.org/.well-known/jwks.json. - No @BotFather você abre as configurações do Login Widget do seu bot, registra as URLs permitidas (origens e URIs de redirecionamento exatas) e obtém um client ID e um client secret.
- Fluxo de código de autorização, PKCE com
S256recomendado. A requisição de token usa autenticação HTTP Basic com o client ID e secret. - Scopes:
openidé obrigatório;profileadiciona o nome,preferred_usernameepicture;phoneadicionaphone_numbercom o consentimento do usuário. Não há claim de e-mail. - Não existe um endpoint UserInfo. Todos os dados do usuário estão no token de ID, cujo
isséhttps://oauth.telegram.orge cujoaudé o ID do seu bot.
Você pode conectar esse fluxo com um provedor OAuth personalizado do Casdoor. Defina o Auth URL e o Token URL para os endpoints acima, defina o Scope para openid profile (adicione phone se necessário), ative Enable PKCE e deixe o UserInfo URL vazio. Registre o https://<your-casdoor-host>/callback do Casdoor como uma URL permitida no BotFather. Sem um URL UserInfo, o Casdoor extrai o usuário do token de ID na resposta do token: ele exige sub, rejeita um token expirado e verifica se aud contém o client ID. Sem um mapeamento de usuário, sub se torna o ID do usuário, preferred_username o nome de usuário, name o nome de exibição e picture o avatar, e phone_number preenche o telefone. A página de login do Casdoor reconhece um provedor personalizado cuja URL de autenticação aponta para oauth.telegram.org e mantém o state OAuth curto para ele.
Note que um usuário do Telegram autenticado através do widget e a mesma pessoa autenticada através de OIDC não são automaticamente o mesmo usuário do Casdoor. A identidade do widget é o id numérico, enquanto a identidade OIDC é sub, e os próprios exemplos do Telegram mostram valores diferentes para os dois. Escolha um método por aplicação.
X (Twitter) e Facebook
Esses dois são OAuth 2.0 comuns, mas cada um tem um detalhe que vale a pena conhecer.
X requer um desafio PKCE em sua URL de autorização OAuth 2.0. O tipo Twitter do Casdoor gera um novo code verifier para cada login, envia o desafio S256 e passa o verifier na troca de token, então não há nada para configurar além do client ID e secret. O Casdoor solicita os scopes users.read tweet.read e lê o usuário de /2/users/me, que fornece o ID do usuário, o handle e o nome de exibição. Ele não solicita um campo de e-mail, então planeje usuários do X sem endereço de e-mail. O guia do provedor Twitter cobre as configurações do app.
Facebook retorna um ID de usuário com escopo de aplicativo: a mesma pessoa tem um ID diferente em cada aplicativo do Facebook, então mudar para um novo aplicativo do Facebook significa que seus usuários não corresponderão aos registros antigos, a menos que você os vincule por e-mail. O Casdoor solicita email,public_profile e lê id, name, picture e email da Graph API. O Facebook omite email quando o perfil não possui um endereço válido. Veja o guia do provedor Facebook.
Como sua aplicação vê tudo isso: OIDC puro
Sua aplicação nunca se comunica diretamente com Steam, Telegram, X ou Facebook. Ela é um cliente OIDC do Casdoor, configurado uma única vez com o emissor do Casdoor, https://<your-casdoor-host>/.well-known/openid-configuration. Você adiciona os provedores sociais à aplicação do Casdoor na aba Providers, e seus botões aparecem na página de login do Casdoor.
Após qualquer um desses logins, o Casdoor encontra ou cria um usuário do Casdoor e finaliza o fluxo normal de código de autorização com sua aplicação. O token de ID que sua aplicação recebe é assinado pelo Casdoor, e seu sub é o ID do usuário do Casdoor, não o SteamID nem o ID do Telegram. Portanto, sua aplicação não precisa de bibliotecas OpenID 2.0, código HMAC, particularidades PKCE por provedor, nem tratamento especial para usuários sem e-mail. O ID original do provedor é armazenado no usuário do Casdoor, por exemplo, nos campos steam ou telegram, caso você precise dele.
Algumas coisas para planejar:
- Vinculação de contas. O Casdoor vincula um login social a um usuário existente por e-mail verificado, telefone verificado ou nome de usuário, na ordem definida pela regra de vínculo da aplicação. Steam e Telegram baseado em widget não fornecem e-mail nem telefone, então eles criam um usuário separado, a menos que o usuário vincule o provedor a partir de uma conta já autenticada. Veja como o Casdoor vincula contas.
- Campos extras de perfil. Provedores que passam dados brutos, como o tipo Steam baseado em Goth e provedores personalizados, podem preencher mais campos do usuário através do mapeamento de usuário.
- O lado do cliente. Qualquer biblioteca padrão funciona contra o Casdoor. Conectar um cliente OIDC padrão lista os endpoints, e o post SSO Spring Boot com OIDC mostra uma aplicação completa.
Referências
- Steam Web API e OpenID: steamcommunity.com/dev
- Steamworks, Autenticação de Usuário e Propriedade: partner.steamgames.com/doc/features/auth
- Telegram, Log In With Telegram (OpenID Connect): core.telegram.org/bots/telegram-login
- Telegram, Widget de Login (legado): core.telegram.org/widgets/login-legacy
- X, Fluxo de Código de Autorização OAuth 2.0 com PKCE: docs.x.com
- Meta, Referência de Usuário da Graph API: developers.facebook.com/docs/graph-api/reference/user
- Fonte do Casdoor:
idp/telegram.go,idp/goth.go,idp/custom.go