Commit cbac4110 authored by o's avatar o
Browse files

login flow without inline scripts

parent 86c8c262
......@@ -4,6 +4,7 @@ require 'jsobfu'
class LoginController < ApplicationController
CountIpFails = false
skip_before_action :verify_authenticity_token, only: [:nonce_js]
def save_login_token(res, user)
session[:login_token] = res['login_token']
......@@ -94,6 +95,37 @@ class LoginController < ApplicationController
flash[:notice] = nil
new_login_session
end
def nonce_js
# Add some obfuscated script to the page that will fill in the nonce
# field, compute the pow and submit it. The obfuscation makes it
# harder for an attacker to get the nonce without executing this
# javascript (thus running a browser) first.
# In the case this is a bogus request (ie. no active session with a nonce
# waiting) we return a random nonce. The nonce is set by load_pow.
nonce = session[:pow_nonce_disclose] || random_nonce
autosubmit_str =
if params[:submit]
"brf();document.forms[0].submit();"
else
""
end
script = <<EOF
window.addEventListener('load', function() {
try {
console.log('login');
if (!navigator.webdriver) {
document.getElementById('pow_nonce').value = '#{nonce}';
#{autosubmit_str}
}
} catch(e){ }
})
EOF
render :js => JSObfu.new(script).obfuscate.to_s
end
private
def new_login_session
......@@ -221,6 +253,10 @@ class LoginController < ApplicationController
load_custom_params
end
def random_nonce
SecureRandom.urlsafe_base64(20)
end
def load_pow(initial_page)
@pow_factor = session[:pow_factor] = security_level[:pow_factor]
if !initial_page && session[:ping_pong] == 1 && security_level[:enable_captcha]
......@@ -231,31 +267,7 @@ class LoginController < ApplicationController
@captcha = Base64.encode64(res[1])
session[:pow_nonce] = res[0]
else
nonce = session[:pow_nonce] = SecureRandom.urlsafe_base64(20)
# Add some obfuscated script to the page that will fill in the nonce
# field, compute the pow and submit it. The obfuscation makes it
# harder for an attacker to get the nonce without executing this
# javascript (thus running a browser) first.
autosubmit_str =
if !initial_page
"brf();document.forms[0].submit();"
else
""
end
script = <<EOF
window.addEventListener('load', function() {
function d() { eval("debugger"); setTimeout(d, 40);};
setTimeout(d, 10);
try {
console.log('login');
if (!navigator.webdriver) {
document.getElementById('pow_nonce').value = '#{nonce}';
#{autosubmit_str}
}
} catch(e){ }
})
EOF
@pow_nonce_script = JSObfu.new(script).obfuscate.to_s.html_safe
session[:pow_nonce_disclose] = session[:pow_nonce] = random_nonce
end
end
end
......@@ -2,6 +2,11 @@
<%= t :auth_wait %>
<% end %>
<% unless @captcha %>
<script src="/nonce.js?submit=1">
</script>
<% end %>
<%= form_tag(request.path, method: 'post', target: '_self') do %>
<p>
<div id="captcha_input" style="display:<%= if @captcha then 'block' else 'none' end %>"/>
......@@ -25,7 +30,3 @@
<%= hidden_field_tag("RelayState", params[:RelayState] || @saml_relay_state) %>
</p>
<% end %>
<script type="text/javascript">
<%= @pow_nonce_script %>
</script>
......@@ -6,6 +6,8 @@
<% end %>
<br/>
<%= javascript_include_tag "/nonce.js" %>
<noscript><%= t(:requires_javascript) %><br/><br/></noscript>
<%
webmail_locales = [
......@@ -61,10 +63,6 @@ webmail_locales_map = {
</p>
<% end %>
<script type="text/javascript">
<%= @pow_nonce_script %>
</script>
<% if @news_frame %>
<hr style="margin-top:30px"/>
<div class="news">
......
......@@ -11,5 +11,7 @@ Rails.application.routes.draw do
get '/login/:handoff/:handoff_instance', to: 'handoff_login#new'
post '/login/:handoff/:handoff_instance', to: 'handoff_login#login'
get '/nonce.js', to: 'login#nonce_js'
get '/logout', to: 'logout#new'
end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment