Commit d1562ce
Changed files (1)
bin
bin/idp
@@ -28,6 +28,10 @@ $port = ENV.fetch("PORT", 8282).to_i
$host = ENV.fetch("HOST", "localhost:#{$port}")
module HTTPHelpers
+ def logged_in?(request)
+ request.session[:user_id]
+ end
+
def default_headers
{
'X-Powered-By' => 'IdP'
@@ -41,6 +45,10 @@ module HTTPHelpers
def http_ok(headers = {}, body = nil)
[200, default_headers.merge(headers), [body]]
end
+
+ def http_redirect_to(location)
+ [302, { 'Location' => location }, []]
+ end
end
module Authn
@@ -112,6 +120,57 @@ module Authn
end
end
+ class SessionsController
+ include ::HTTPHelpers
+
+ def call(env)
+ request = Rack::Request.new(env)
+ case request.request_method
+ when Rack::GET
+ case request.path
+ when '/sessions/new'
+ return get_login(request)
+ end
+ when Rack::POST
+ case request.path
+ when '/sessions'
+ if (user = User.find_by_credentials(request.params))
+ request.session[:user_id] = user[:id]
+ return http_redirect_to('/')
+ else
+ return http_redirect_to("/sessions/new")
+ end
+ when '/sessions/delete'
+ request.session.delete(:user_id)
+ return http_redirect_to('/')
+ end
+ end
+
+ http_not_found
+ end
+
+ private
+
+ def get_login(request)
+ template = <<~ERB
+ <!DOCTYPE html>
+ <html>
+ <head><title></title></head>
+ <body>
+ <form id="login-form" action="/sessions" method="post">
+ <input type="input" placeholder="Username" id="username" name="username" value="" />
+ <input type="password" placeholder="Password" id="password" name="password" value="" />
+ <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
+ end
+
class SAMLController
include ::HTTPHelpers
@@ -198,7 +257,7 @@ module Authn
def saml_post_back(request, user)
params = saml_params_from(request)
saml_request = binding_for(request).deserialize(params)
- request.session[:access_token] = user.create_access_token
+ request.session[:user_id] = user[:id]
@builder = nil
url, saml_params = saml_request.response_for(
@@ -330,22 +389,25 @@ module Authz
include ::HTTPHelpers
def call(env)
- path = env['PATH_INFO']
- case env['REQUEST_METHOD']
- when 'GET'
- case path
+ request = Rack::Request.new(env)
+
+ case request.request_method
+ when Rack::GET
+ case request.path_info
when "/authorize" # RFC-6749
- return get_authorize(Rack::Request.new(env))
+ if logged_in?(request)
+ return get_authorize(request)
+ else
+ http_redirect_to("/saml/")
+ end
else
return http_not_found
end
- when 'POST'
- case path
+ when Rack::POST
+ case request.path_info
when "/authorize" # RFC-6749
- return post_authorize(Rack::Request.new(env))
+ return post_authorize(request)
when "/token" # RFC-6749
- request = Rack::Request.new(env)
-
return [200, { 'Content-Type' => "application/json" }, [JSON.pretty_generate({
access_token: ::Authz::JWT.new(sub: SecureRandom.uuid, iat: Time.now.to_i).to_jwt,
token_type: "Bearer",
@@ -413,10 +475,17 @@ class IdentityProvider
include ::HTTPHelpers
def call(env)
- path = env['PATH_INFO']
- case env['REQUEST_METHOD']
- when 'GET'
- case path
+ request = Rack::Request.new(env)
+
+ case request.request_method
+ when Rack::GET
+ case request.path
+ when '/'
+ if logged_in?(request)
+ return get_dashboard(request)
+ else
+ return http_redirect_to("/sessions/new")
+ end
when '/.well-known/openid-configuration'
return openid_metadata
when '/.well-known/oauth-authorization-server'
@@ -432,6 +501,26 @@ class IdentityProvider
private
+ def get_dashboard(request)
+ template = <<~ERB
+ <!DOCTYPE html>
+ <html>
+ <head><title></title></head>
+ <body>
+ <h1>Dashboard</h1>
+ <pre><%= request.session[:access_token] %></pre>
+
+ <form action="/sessions/delete" method="post">
+ <input type="submit" value="logout" />
+ </form>
+ </body>
+ </html>
+ ERB
+ erb = ERB.new(template, trim_mode: '-')
+ html = erb.result(binding)
+ [200, { 'Content-Type' => "text/html" }, [html]]
+ end
+
# GET /.well-known/oauth-authorization-server
def oauth_metadata
[200, { 'Content-Type' => "application/json" }, [JSON.pretty_generate({
@@ -534,6 +623,10 @@ if __FILE__ == $0
map "/saml" do
run Authn::SAMLController.new($scheme, $host)
end
+
+ map "/sessions" do
+ run Authn::SessionsController.new
+ end
run IdentityProvider.new
end.to_app