diff options
Diffstat (limited to 'bin')
| -rwxr-xr-x | bin/idp | 104 |
1 files changed, 43 insertions, 61 deletions
@@ -28,8 +28,12 @@ $port = ENV.fetch("PORT", 8282).to_i $host = ENV.fetch("HOST", "localhost:#{$port}") module HTTPHelpers - def logged_in?(request) - request.session[:user_id] + def current_user?(request) + current_user(request) + end + + def current_user(request) + ::Authn::User.find(request.session[:user_id]) end def default_headers @@ -47,7 +51,7 @@ module HTTPHelpers end def http_redirect_to(location) - [302, { 'Location' => location }, []] + [302, { 'Location' => "http://idp.example.com:8080#{location}" }, []] end end @@ -67,6 +71,12 @@ module Authn end end + def find(id) + all.find do |user| + user[:id] == id + end + end + def find_by_username(username) all.find do |user| user[:username] == username @@ -136,7 +146,8 @@ module Authn when '/sessions' if (user = User.find_by_credentials(request.params)) request.session[:user_id] = user[:id] - return http_redirect_to('/') + path = request.params["redirect_back"] ? request.params["redirect_back"] : "/" + return http_redirect_to(path) else return http_redirect_to("/sessions/new") end @@ -159,6 +170,7 @@ module Authn <body> <form id="login-form" action="/sessions" method="post"> <input type="input" placeholder="Username" id="username" name="username" value="" /> + <input type="hidden" name="redirect_back" value="<%= request.params["redirect_back"] %>" /> <input type="password" placeholder="Password" id="password" name="password" value="" /> <input type="submit" id="login-button" value="Login" /> </form> @@ -194,26 +206,33 @@ module Authn end def call(env) - path = env['PATH_INFO'] - case env['REQUEST_METHOD'] - when 'GET' - case path - when "/metadata.xml" + request = Rack::Request.new(env) + case request.request_method + when Rack::GET + case request.path + when "/saml/continue" + if current_user?(request) + saml_params = request.session[:saml_params] + return saml_post_back(request, current_user(request), saml_params) + else + return http_redirect_to("/sessions/new?redirect_back=/saml/continue") + end + when "/saml/metadata.xml" return http_ok( { 'Content-Type' => "application/samlmetadata+xml" }, saml_metadata.to_xml(pretty: true) ) end - when 'POST' - case path - when "/new" - return login_page(Rack::Request.new(env)) - when "/login" - request = Rack::Request.new(env) - if (user = User.find_by_credentials(request.params)) - return saml_post_back(request, user) + when Rack::POST + case request.path + when "/saml/new" + saml_params = saml_params_from(request) + + if current_user?(request) + return saml_post_back(request, current_user(request), saml_params) else - return login_page(request) + request.session[:saml_params] = saml_params + return http_redirect_to("/sessions/new?redirect_back=/saml/continue") end end end @@ -225,45 +244,14 @@ module Authn attr_reader :saml_metadata - def login_page(request) - saml_params = saml_params_from(request) + def saml_post_back(request, user, saml_params) saml_request = binding_for(request).deserialize(saml_params) - raise saml_request.errors unless saml_request.valid? - - template = <<~ERB - <!DOCTYPE html> - <html> - <head><title></title></head> - <body> - <h2>Recieved SAML Request</h2> - <textarea readonly="readonly" disabled="disabled" cols=225 rows=6><%=- saml_request.to_xml(pretty: true) -%></textarea> - - <form id="login-form" action="/saml/login" method="post"> - <input type="input" placeholder="Username" id="username" name="username" value="" /> - <input type="password" placeholder="Password" id="password" name="password" value="" /> - <%- saml_params.each do |(key, value)| -%> - <input type="hidden" name="<%= key %>" value="<%= value %>" /> - <%- end -%> - <input type="submit" id="login-button" value="Login" /> - </form> - </body> - </html> - ERB - erb = ERB.new(template, trim_mode: '-') - html = erb.result(binding) - [200, { 'Content-Type' => "text/html" }, [html]] - end - - def saml_post_back(request, user) - params = saml_params_from(request) - saml_request = binding_for(request).deserialize(params) - request.session[:user_id] = user[:id] @builder = nil url, saml_params = saml_request.response_for( user, binding: :http_post, - relay_state: params[:RelayState] + relay_state: saml_params[:RelayState] ) { |builder| @builder = builder } template = <<~ERB <!DOCTYPE html> @@ -303,12 +291,7 @@ module Authn end def binding_for(request) - location = "#{$scheme}://#{$host}/saml/new" - if request.post? - Saml::Kit::Bindings::HttpPost.new(location: location) - else - Saml::Kit::Bindings::HttpRedirect.new(location: location) - end + Saml::Kit::Bindings::HttpPost.new(location: "#{$scheme}://#{$host}/saml/new") end end end @@ -395,7 +378,7 @@ module Authz when Rack::GET case request.path_info when "/authorize" # RFC-6749 - if logged_in?(request) + if current_user?(request) return get_authorize(request) else http_redirect_to("/saml/") @@ -481,7 +464,7 @@ class IdentityProvider when Rack::GET case request.path when '/' - if logged_in?(request) + if current_user?(request) return get_dashboard(request) else return http_redirect_to("/sessions/new") @@ -507,8 +490,7 @@ class IdentityProvider <html> <head><title></title></head> <body> - <h1>Dashboard</h1> - <pre><%= request.session[:access_token] %></pre> + <h1> Hello, <%= current_user(request)[:username] %></h1> <form action="/sessions/delete" method="post"> <input type="submit" value="logout" /> |
