¿Redirigir a un sitio externo en un plugin?

Estoy intentando llamar a una URL externa para iniciar sesión en un sitio remoto después de que los usuarios inicien sesión en Discourse. Todo lo que necesito hacer es redirigir a una URL en el sitio remoto, que realiza el inicio de sesión allí, y luego redirigir de vuelta a Discourse. Cuando lo hago, el navegador se niega a redirigir debido a CORS:

Acceso a XMLHttpRequest a 'https://SITE/api/sso/v2/sso/jwt?' (redirigido desde 'https://testing.literatehosting.com/session') desde el origen 'https://testing.literatehosting.com' ha sido bloqueado por la política CORS: La respuesta a la solicitud preflight no pasa la verificación de control de acceso: No hay un encabezado 'Access-Control-Allow-Origin' presente en el recurso solicitado.

Los desarrolladores de la aplicación dicen que es porque estoy haciendo la redirección incorrectamente (por ejemplo, con una llamada AJAX?), pero esto se ve igual que, por ejemplo, lo que veo en los commits mencionados aquí.

Estoy (una vez más) atascado.

No puedo decir si soy simplemente estúpido o si ellos necesitan enviar encabezados Access-Control-Allow-Origin (y si ese es el caso, entonces esto no puede estar funcionando para ninguno de sus clientes, lo cual parece muy improbable).

Aquí está mi código:

after_initialize do
  class ::SessionController
    def login(user)
      puts "\n\n\n\LOGIN happening!\n\n\n\n"
      session.delete(ACTIVATE_USER_KEY)
      log_on_user(user)

      if payload = cookies.delete(:sso_payload)
        sso_provider(payload)
      else
        if true # plugin is enabled and has api key and url
          sign_into_thinkific(user)
        else
          render_serialized(user, UserSerializer)
        end
      end
    end

    def sign_into_thinkific(user)
      # do stuff to generate payload

      redirect_to thinkific_sso_url(payload) # also tried redirect_to 
 generate_url(thinkific_sso_url(payload))

    end

    def generate_url(url, params = {})
      puts "\n\n\nGenerate URL: #{url}\n\n\n"
      uri = URI(url)
      uri.query = params.to_query
      uri.to_s
    end

    def thinkific_sso_url(payload)
      current_url="https://#{GlobalSetting.hostname}/"
      url = "https://#{SiteSetting.thinkific_site_url}/api/sso/v2/sso/jwt?jwt=#{payload}"
      url += "&return_to=#{URI.escape(current_url)}" 

      url
    end

  end
end

EDITO: Los desarrolladores compartieron una aplicación Rails que usa redirect_to exactamente como yo y afirman que funciona. ¿Hay algo sobre Discourse que haga que redirect_to se comporte de manera diferente porque está… dentro de Ember, o algo así?

Seguro que me estoy perdiendo algo sencillo. Mi último intento es probar:

      url = thinkific_sso_url(payload)
      redirect_location = "<!DOCTYPE html><html><head><meta http-equiv=\"Refresh\" content = \"5; url='#{url}'\" /></head><body>Este es mi cuerpo</body></html>"
      Rails.logger.info "REDIRIGIENDO... #{redirect_location}"

      render plain: redirect_location

Si guardo el texto de redirect_location en un archivo y lo abro en mi navegador, me inicio sesión en Thinkific y me redirige a Discourse. Lamentablemente, lo mismo no funciona cuando hago clic en «Iniciar sesión» en mi navegador.

¿Alguien me echa una mano?

Siento sacarte en público, @sam, pero creo que hay algo específico de Discourse y rápido con lo que podrías ayudarme, y llevo dos semanas trabajando en esto.

He logrado que mi código funcione insertando un proxy en medio, pero eso no parece una solución muy buena.

Cuando intento hacer un redirect_to a un sitio externo en el SessionController que estoy sobrescribiendo, obtengo un error de CORS. El mismo código de Thinkific parece no tener ese problema. ¿Hay algo especial al hacer una redirección desde dentro de site_url/session? ¿Necesito hacer la redirección desde JavaScript de alguna manera? Si es así, ¿podrías indicarme la dirección general de cómo podría funcionar eso?

Honestamente, no estoy seguro de qué está pasando aquí. redirect_to debería funcionar con una URL externa.

Oh. Mierda.

redirige, pero genera una violación de CORS. Es extraño porque lo que parece ser exactamente la misma redirección no causa una violación de CORS en su código de ejemplo de Rails. Esperaba que hubiera algo especial en hacerlo dentro de Ember. O algo así.

Así que mucho se acabó mi esperanza de que fuera algo tonto y obvio.

Muchas gracias. Lo aprecio mucho.

Estoy bastante seguro de que, como el modal de inicio de sesión se realiza mediante AJAX (en base_url/session), el navegador se niega a ejecutar un redirect_to a menos que el otro extremo envíe las cabeceras CORS.

Lo que creo que necesito es alguna forma de (y no tengo idea de cómo describir esto) salir del contexto de AJAX para que, para el navegador, parezca una redirección normal y no una redirección dentro de AJAX.

O, ¿hay alguna manera de que el inicio de sesión sea una página que no use AJAX?

Hola @pfaffman

¿Has tenido suerte con esta situación? Estoy teniendo el mismo problema al usar el inicio de sesión SSO de Discourse desde una API web de ASP.NET Core.

El navegador de la aplicación Angular lanza el error ‘encabezado de control de aceptación no presente’ una vez que la solicitud se redirige desde la API a la aplicación Angular (después de que Discourse haya enviado la respuesta correctamente).

Aplicación web Angular → API de ASP.NET → La API llama a SSO de Discourse → Discourse devuelve los valores al servidor API de ASP.NET → El servidor API redirige la llamada de vuelta a la URL de la aplicación Angular → El navegador lanza un error indicando que la URL de Discourse no es accesible debido a que falta el ‘encabezado de origen de control de acceso’.

image

Todos los ajustes de CORS en Discourse están configurados correctamente, al igual que en el servidor web de la API de ASP.NET.

Parece similar al problema que enfrentaste anteriormente. Espero que puedas aclarar cómo solucionarlo.