Olá , escrevi este módulo de autenticação SimpleSAMLphp para permitir o uso do Discourse como provedor de SSO em uma instalação do SimpleSAMLphp. Ou seja, você pode usar o Discourse como provedor de SSO para qualquer serviço que suporte autenticação SAML ou Shibboleth, o que é realmente ótimo.
Me diga o que você acha (se tiver interesse em comentar sobre o código, pode usar as Issues do GitHub).
Isso é ótimo! Se você quiser tornar o módulo mais visível, pode criar um tópico sobre ele na nossa categoria #plugin:extras. Essa categoria é um diretório de todas as extensões e integrações para o Discourse que não são plugins do Discourse.
Estou implementando este SSO em um site existente e gostaria apenas de verificar como as pessoas estão “apresentando” seu método de login aos usuários.
Por exemplo, digamos que meu site em www.example.com tenha um botão de Login na barra de navegação superior.
Esse botão de login deve levar as pessoas diretamente para a página de autenticação do meu Discourse? Ou é preferível exibir primeiro uma página ou modal com informações, algo como:
Estou apenas me perguntando se as pessoas ficarão confusas se não forem informadas sobre o que vai acontecer?
Alguém tem alguma experiência de usuário ou melhores práticas para compartilhar?
E obrigado também, aliás, ao @techAPJ pelo primeiro post muito detalhado neste tópico; consegui construir isso do zero no meu site ASP.NET seguindo seus passos
É possível incluir um parâmetro de estado que seja retornado inalterado, como é feito no OAuth? O middleware de autenticação do ASP.NET Core depende da geração de um ID de correlação para prevenir ataques CSRF, e atualmente não tenho uma maneira fácil de incluí-lo.
@jessicah Eu testei isso hoje e, sim, funciona perfeitamente.
' Criar uma URL de retorno
Dim strReturnURL As String = "https://www.example.com/authtestRETURNURL.aspx?myownparametershere=surewhynot"
' Gerar um nonce aleatório. Salve-o temporariamente para que você possa verificá-lo com o valor do nonce retornado
Dim strNonce As String = Guid.NewGuid().ToString("N")
' Criar um novo payload com o nonce e a URL de retorno (para onde o Discourse redirecionará o usuário após a verificação)
' O payload deve se parecer com: nonce=NONCE&return_sso_url=RETURN_URL
Dim strPayload As String = "nonce=" & strNonce & "&return_sso_url=" & strReturnURL
Então, na página que é chamada de volta, você encontrará isso dentro da sua string de consulta SSO decodificada:
Abordagens multi-site para uso do discourse-auth-proxy?
Existem exemplos ou recomendações para usar o Discourse como provedor de SSO para autenticação multi-site?
Parece que existem duas abordagens básicas para multi-site:
Usar múltiplas instâncias do discourse-auth-proxy, uma por site protegido.
Usar uma única instância do discourse-auth-proxy para que o payload contendo o return_sso_url mude com base na origem da solicitação de login.
Acho que qualquer uma dessas poderia funcionar, mas o problema com essas duas abordagens é que você ainda precisa fazer login em cada site diferente.
Há também o risco de que algo seja armazenado no Postgres e seja sobrescrito por cada login dos diferentes sites. Ou seja: site1.com, site2.com
(Não conheço os detalhes do esquema de autenticação do Discourse/PG, então não sei)
O que seria ideal é uma maneira de realizar o login uma única vez, o que faria com que você estivesse logado em todos os sites do grupo multi-site. Ou seja: site1.com, site2.com, site3.com
Aparentemente, o Stackoverflow faz isso usando uma combinação de armazenamento local (localStorage) e iframes como principais facilitadores. descrição técnica
Mas eu adoraria saber se alguém implementou alguma abordagem para login multi-site usando o Discourse como provedor de SSO.
Abordagem 1: múltiplas instâncias do discourse-auth-proxy
Abordagem 2: discourse-auth-proxy modificado alterando o return_sso_url no payload.
Abordagem 3: #1 ou #2 implementadas de forma que, ao fazer login uma vez, você não precise fazer login novamente ao migrar de site1.com para site2.com
Estou marcando você, @sam, já que você foi o autor original do programa Go discourse-auth-proxy.
O problema é que a URL de retorno será processada pela função urldecode no PHP (que é o fluxo principal de autenticação do MediaWiki), e o valor de wpLoginToken mudará inesperadamente de 123+\ para 123 \.
Parece que encontrei a causa:
Bem, o cliente e o servidor implementam codificação/decodificação, mas seguem especificações diferentes.
Não estou pedindo ao Discourse que altere nada, mas procurando conselhos para resolver isso.
Obrigado.
Edição:
Resolvi apenas codificando o sinal + duas vezes.
Em Configurações > Login, as duas configurações do provedor do DiscourseConnect não estão consecutivas e aparecem intercaladas com as configurações do DiscourseConnect:
Como as configurações do provedor e as não provedoras são para casos de uso opostos — usar o Discourse para gerenciar usuários de outra coisa versus usar outra coisa para gerenciar usuários do Discourse — exibir essas configurações misturadas pode levar a uma configuração incorreta. Seria menos confuso se as duas configurações do provedor estivessem consecutivas e totalmente antes ou totalmente depois das configurações não provedoras.
@techAPJ Isso pode ser usado com o AWS Cognito? Quero criar um aplicativo no AWS Amplify para minha comunidade Discourse e gostaria que o aplicativo fosse autenticado através do Discourse.
@mdoggydog Obrigado pela atualização recente da extensão MediaWiki DiscourseSsoConsumer. Estávamos quebrando a cabeça sobre o que fazer em relação aos usuários sendo desconectados de nossa wiki sem terem se desconectado do Discourse, e $wgPluggableAuth_EnableAutoLogin definitivamente não era o que queríamos, pois impede o acesso anônimo à wiki. A configuração $wgDiscourseSsoConsumer_AutoRelogin que você adicionou é exatamente o que precisávamos.
Estou tentando usar o exemplo de PHP da postagem original, mas a forma como eles estão armazenando as coisas não faz sentido. Eles estão apenas armazenando valores em um banco de dados SQL com as chaves login e nonce. Se eu quiser usar SQL para armazenar os nonces, como exatamente seria meu banco de dados SQL?
Algumas outras informações que podem ajudar são para que estou usando isso - espero vincular um usuário do Discourse a uma conta do Minecraft gerando um link SSO que está vinculado à sua UUID. Após fazer login com sucesso no Discourse, vou armazenar a UUID e o ID do Discourse deles em uma tabela.
Até agora, consegui fazer o exemplo de PHP funcionar, mas acho que não estou entendendo completamente como eu teria que modificá-lo para funcionar para o meu caso de uso. Idealmente, quero gerar o link através de uma solicitação GET e enviá-lo ao usuário, para que a UUID já esteja associada ao nonce.
Obrigado por esta postagem, pois eu estaria ainda mais perdido sem ela!
Editar: Para nonces, seria melhor armazenar nonces na tabela e procurar por eles? Eu sei que preciso corresponder ao nonce, mas, a menos que eu possa passar informações adicionais na URL de redirecionamento (o que não consegui fazer com sucesso), não tenho certeza de como referenciar o nonce corretamente.
Eu editei parte do valor do parâmetro sso que você forneceu. A menos que alguém conhecesse sua chave secreta, não seria capaz de decodificar o valor, mas ainda assim parecia mais seguro não fornecer o valor completo. Não estará relacionado ao erro 502 que você está recebendo.
Parece um erro de banco de dados. Porque eu tentei o mesmo plugin e configuração em outro site do Discourse, e está funcionando. Como posso corrigir este problema?
Parece que tentar autenticar no discourse-auth-proxy com nomes de usuário ou grupos não ASCII (chinês no meu caso) leva a um erro porque os cookies não podem conter esses caracteres. Esta é a minha correção: (aviso: eu não sou muito familiarizado com golang)
diff --git a/main.go b/main.go
index 1b1dc28..18f8c9e 100644
--- a/main.go
+++ b/main.go
@@ -154,7 +154,12 @@ func redirectIfNoCookie(handler http.Handler, r *http.Request, w http.ResponseWr
var username, groups string
if err == nil && cookie != nil {
- username, groups, err = parseCookie(cookie.Value, config.CookieSecret)
+ var value string
+ value, err = url.QueryUnescape(cookie.Value)
+ if err != nil {
+ return
+ }
+ username, groups, err = parseCookie(value, config.CookieSecret)
}
if err == nil {
@@ -224,7 +229,7 @@ func redirectIfNoCookie(handler http.Handler, r *http.Request, w http.ResponseWr
cookieData := strings.Join([]string{username, strings.Join(groups, "|")}, ",")
http.SetCookie(w, &http.Cookie{
Name: cookieName,
- Value: signCookie(cookieData, config.CookieSecret),
+ Value: url.QueryEscape(signCookie(cookieData, config.CookieSecret)),
Expires: expiration,
HttpOnly: true,
Path: "/",