Hotwire rails app: redirect to external service fails
I am integrating discourse single sign on with hotwire rails application, everything works fine till redirection, when it redirects I see there is CORS issue browser, ofcourse its turbo request so it attempts to fetch response from give URL so it throws CORS error, How we can do actual redirection here?.
def sso
secret = "572890bb92bbef8c4634c1bf"
sso = SingleSignOn.parse(request.query_string, secret)
sso.email = current_user.email # from devise
sso.name = current_user.name # this is a custom method on the User class
sso.username = current_user.username # from devise
sso.external_id = current_user.id # from devise
sso.sso_secret = secret
redirect_to sso.to_url("https://xxxxxxxx/session/sso_login")
end
Edit(1)
<main class="main-content">
<div class="d-flex justify-content-center">
<div>
<div class="mt-48 py-48 px-md-48 px-32 border-radius-lg log-in-card box-shadow-05">
<h4 class="font-size-24 text-black font-weight-400 mb-0">Member Login</h4>
<%= form_for(resource, as: resource_name, url: session_path(resource_name), html: {class: 'mt-48'}) do |f| %>
<div class="form-group mb-0">
<%= f.label :email, class: "font-weight-500 font-size-14 text-black" %>
<%= f.email_field :email, autofocus: true, autocomplete: "email", class: 'form-control-lg form-control' %>
</div>
<div class="form-group position-relative mt-32">
<%= f.label :password, class: "font-weight-500 font-size-14 text-black" %>
<%= f.password_field :password, autocomplete: "current-password", class: 'form-control-lg form-control' %>
<div class="position-absolute eye-icon"><i class="far fa-eye-slash font-size-14 text-black"></i></div>
</div>
<div class="d-flex flex-column align-items-center mt-32">
<%= f.submit "Login", class: 'btn btn-brand-primary py-12 px-48 text-decoration-none' %>
<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
<%= link_to "Forget password?", new_password_path(resource_name), class: 'text-decoration-none text-brand-primary font-weight-600 font-size-14 mt-32' %>
<% end %>
</div>
<% end %>
</div>
<div class="d-flex justify-content-center mt-48">
<span class="text-black font-weight-500 font-size-14 text-decoration-none">Not a member?</span>
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
<%= link_to "Create Account", new_registration_path(resource_name), class: 'text-brand-primary font-weight-600 font-size-14 text-decoration-none ml-8' %>
<% end %>
</div>
<div class="d-flex flex-md-row flex-column align-items-center justify-content-center mt-48 mb-96 pb-md-64">
<span class="text-black font-weight-500 font-size-14 text-decoration-none">Didn't receive confirmation
instructions?</span>
<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
<%= link_to "Request again", new_user_confirmation_path(resource_name), class: 'text-brand-primary font-weight-600 font-size-14 text-decoration-none ml-8'%>
<% end %>
</div>
</div>
</div>
</main>
2 ответа
я использовал
data-turbo="false"
в форме входа он отправит HTML-запрос на бэкэнд, поэтому, когда я перенаправляю, он перенаправляет всю страницу. Спасибо
https://turbo.hotwire.dev/handbook/drive#disables-turbo-drive-on-specific-links-or-forms
Если вы не хотите отключать турбо для определенного действия. Я создал JS-скрипт, который перезагрузил страницу.
просмотры/shared/_reload_script.html.erb
<script>
window.location = "<%= redirect_url %>";
</script>
в конкретном контроллере я добавил рендеринг, когда мне нужно было перенаправить
example_controller.rb
render turbo_stream: turbo_stream.append(
:reload,
partial: 'shared/reload_script',
locals: { redirect_url: 'https://example.com' }
)
и в действии представления или application.html.erb я помещаю DIV с идентификатором перезагрузки
<div id="reload"></div>
Это нормальное решение, если удаление турбопотока потребует много усилий. Я не уверен, есть ли у этого подхода какие-то особые недостатки, но для меня пока он работает нормально.
Чтобы метод читался лучше, я также создал метод вapplication_controller.rb
и переместите рендер туда
application_controller.rb
def turbo_stream_redirect_to(redirect_url)
render turbo_stream: turbo_stream.append(
:reload,
partial: 'shared/reload_script',
locals: { redirect_url: }
)
end
Итак, в вашем действии нужно вызвать следующее:
turbo_stream_redirect_to 'https://example.com'
ПРИМЕЧАНИЕ. Я бы не рекомендовал этот подход, если у пользователей есть возможность изменить URL-адрес. но пока вы (разработчики) единственный, кто решает, что URL-адрес в порядке