Redirect to external site in a plugin?

I’m trying to call an external URL to log in to a remote site after users log in to Discourse. All I need to do is redirect to a URL on the remote site, which does the login there, and then redirects back to Discourse. When I do, the browser refuses to redirect because or CORS:

Access to XMLHttpRequest at 'https://SITE/api/sso/v2/sso/jwt?' (redirected from 'https://testing.literatehosting.com/session') from origin 'https://testing.literatehosting.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Developers on the app say that it’s because I’m doing the redirect wrong (e.g., with an ajax call?), but this looks the same as, say, what I see in commits mentioned here.

I’m (once again) stumped.

I can’t tell if I’m just stupid or whether they need to be sending Access-Control-Allow-Origin headers (and if that’s the case, then this can’t be working for any of their clients? which seems far-fetched).

Here’s my code:

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

EDIT: The developers shared a Rails app that uses redirect_to just as I am and they claim that it works. Is there something about Discourse that makes it do something different with a redirect_to because it’s. . . inside Ember, or something?

Sure there is something simple that I’m missing here. My latest incantation is to try

      url = thinkific_sso_url(payload)
      redirect_location = "<!DOCTYPE html><html><head><meta http-equiv=\"Refresh\" content = \"5; url='#{url}'\" /></head><body>This is my body</body></html>"
      Rails.logger.info "REDIRECTING... #{redirect_location}"

      render plain: redirect_location

If I save the text that is redirect_location to a file and open it in my browser, I get logged in to thinkific and I’m redirected to Discourse. Sadly, the same doesn’t work when I click login in my browser.

Can anyone throw me a bone?

I’m sorry to call you out, @sam, but I feel like there is something Discourse-specific and quick that you can help me with and I’ve been working on this for two weeks.

I’ve made my code work by inserting a proxy in the middle, but that doesn’t seem like a very good solution.

When I try to redirect_to an external site in an the SessionController that I am overriding, I get a CORS error. The same code from thinkific appears not to have that problem. Is there something special about doing a redirect from within site_url/session? Do I need to do the redirect from Javascript somehow? If so, could you point me in the general direction of how that might work?

1 Like

Honestly I am not sure what is going on here. redirect_to should work to an external url.

1 Like

Oh. Darn.

It does redirect, but it generates a CORS violation. It’s bizarre because what appears to be the exact same redirection doesn’t cause a CORS violation on their Rails sample code. I was hoping that something was special about doing it inside of Ember. Or something.

So much for my hope that it was something silly and obvious.

Thanks very much. I really appreciate it.

I’m fairly certain that because the login modal is done in AJAX (in base_url/session) the browser refuses to do a redirect_to without the other side sending CORS headers.

What I think that I need is some way to (and I have no idea how to describe this) get out of AJAX so that to the browser it looks like a normal redirect, not a redirect in AJAX.

Or, is there some way to get the login to be a non-ajax page?

hi @pfaffman

Any luck with this situation? I am having same issue using the Discourse SSO login from asp.net core web API.

The Angular app browser is throwing the ‘accept control header’ not present error once the request is redirected from API to angular app (after discourse sent the reply back successfully).

Angular web app ->asp.net API-> API calls discourse SSO->Discourse returns values to asp.net server API-> API server redirects call back to angular app URL->Browser throws error that discourse URL is not accessible due to ‘Access control origin header’ not present.

image

All CORS settings on discourse are set up correctly and on the asp net API web server.

It sounds similar to the problem you faced earlier. I am hoping that you can shed some light on how to solve it.

1 Like