deepblue / snippets

deepblue's thoughts

This URL has Read+Write access

snippets / sinatra / lib / openid_authentication.rb
100644 133 lines (104 sloc) 3.489 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# OpenID Consumer library for sinatra
# by deepblue (http://myruby.net)
 
%w(openid openid/extensions/sreg openid/store/memory uri).each{|lib| require lib}
 
module OpenIdAuthentication
  
  ###########################################################################
  # Template Methods
  def begin_openid_authentication(openid = nil)
    openid ||= params[:openid_identifier]
    oidreq = openid_consumer.begin(openid)
  
    oidreq.add_extension(sreg_request) if respond_to?(:sreg_request)
    yield(oidreq) if block_given?
      
    if oidreq.send_redirect?(realm, url_for_complete, params[:immediate])
      #redirect_to url_for_openid_challenge(ret, params[:openid_identifier])
      url = openid_reqeust_url(oidreq.redirect_url(realm, url_for_complete, params[:immediate]), openid)
      redirect url
    else
      @form_text = oidreq.form_markup(realm, url_for_complete, params[:immediate], {'id' => 'openid_form'})
      erb begin_template
    end
  end
  
  def complete_openid_authentication
    oidresp = openid_consumer.complete(openid_params, request.url)
    
    if oidresp.status == OpenID::Consumer::SUCCESS
      authentication_succeed(oidresp)
    else
      authentication_failed(oidresp, message_from_response(oidresp))
    end
  end
  
  ###########################################################################
  # You can override this methods
  
  def authentication_succeed(oidresp)
  end
  
  def authentication_failed(oidresp, message)
  end
  
  def openid_consumer
    @openid_consumer ||= OpenID::Consumer.new(session, openid_store)
  end
  
  def openid_store
    OpenID::Store::Memory.new
  end
  
  def url_for_complete
    uri = URI.parse(request.url)
    uri.path = '/openid/complete'
    uri.to_s
  end
    
  def realm
    uri = URI.parse(request.url)
    uri.path = '/'
    uri.query = nil
    uri.to_s
  end
    
  def openid_reqeust_url(url, openid)
    url
  end
  
  ###########################################################################
  # Internal Helper Methods
private
  
  def openid_params
    params
  end
  
  def message_from_response(oidresp)
    case oidresp.status
    when OpenID::Consumer::FAILURE
      oidresp.display_identifier ?
        "Verification of #{oidresp.display_identifier} failed: #{oidresp.message}" :
        "Verification failed: #{oidresp.message}"
    when OpenID::Consumer::SETUP_NEEDED
      "Immediate request failed: Setup needed"
    when OpenID::Consumer::CANCEL
      "Verification cancelled."
    when OpenID::Consumer::SUCCESS
      "Verification of #{oidresp.display_identifier} succeeded."
    else
      "Unknown response status: #{oidresp.status}"
    end
  end
  
  def begin_template
    ret = <<-END
<html><body>
<%= @form_text %>
<script type="text/javascript">
document.getElementById('openid_form').submit();
</script>
</body></html>
END
  end
  
  def sreg_data(oidresp)
    OpenID::SReg::Response.from_success_response(oidresp).data
  rescue Object
    {}
  end
end
Sinatra::EventContext.send :include, OpenIdAuthentication
 
 
 
 
##################################################
# Action URL
 
Sinatra.application.define_event(:post, '/openid/begin') do
  begin_openid_authentication(params[:openid_identifier])
end
 
Sinatra.application.define_event(:get, '/openid/complete') do
  complete_openid_authentication
end
 
Sinatra.application.define_event(:post, '/openid/complete') do
  complete_openid_authentication
end