sinatra-browserid 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,59 @@
1
+ Sinatra plugin that allows authentication against [BrowserID](https://browserid.org/). BrowserID lets you verify the email identity of a user.
2
+
3
+ To learn more, see how it works [from a users perspective](https://browserid.org/about) and [from a developers perspective](https://github.com/mozilla/browserid/wiki/How-to-Use-BrowserID-on-Your-Site).
4
+
5
+ Note that BrowserID logins are not done from within a form on your site -- you provide a login button, and that will start up the BrowserID login flow (either via a pop-up or an in-browser widget).
6
+
7
+ How to get started:
8
+
9
+ ```ruby
10
+ require 'sinatra/base'
11
+ require 'sinatra/browserid'
12
+
13
+ module MyApp < Sinatra::Base
14
+ register Sinatra::BrowserID
15
+
16
+ set :browserid_login_button, :orange
17
+ set :sessions, true
18
+
19
+ get '/'
20
+ if authorized?
21
+ "Welcome, #{authorized_email}"
22
+ else
23
+ render_login_button
24
+ end
25
+ end
26
+
27
+ get '/secure'
28
+ authorize! # require a user be logged in
29
+
30
+ email = authorized_email # browserid email
31
+ ...
32
+ end
33
+
34
+ get '/logout'
35
+ logout!
36
+
37
+ redirect '/'
38
+ end
39
+ end
40
+ ```
41
+
42
+ See the rdoc for more details on the helper functions. For a functioning
43
+ example app, run <tt>rackup -p $PORT</tt> in the example directory.
44
+
45
+ Available sinatra settings:
46
+
47
+ * <tt>:browserid_login_button</tt>: set to a color (:orange, :red, :blue,
48
+ :green, :grey) or an image URL
49
+ * <tt>:browserid_server</tt>: If you're using an alternate auth provider
50
+ other than https://browserid.org
51
+ * <tt>:browserid_login_url</tt>: URL users get redirected to when the
52
+ <tt>authorize!</tt> helper is called and a user is not logged in
53
+
54
+
55
+ Still TODO:
56
+
57
+ * better error handling
58
+ * local assertion verification (eliminate callback)
59
+
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $: << File.join(File.dirname(__FILE__), "..", "lib")
4
+
5
+ require "sinatra/base"
6
+ require "sinatra/browserid"
7
+
8
+ class TestApp < Sinatra::Base
9
+ register Sinatra::BrowserID
10
+
11
+ set :sessions, true
12
+
13
+ get '/' do
14
+ erb :index
15
+ end
16
+
17
+ get '/logout' do
18
+ logout!
19
+
20
+ redirect '/'
21
+ end
22
+
23
+ get '/confidential' do
24
+ authorize!
25
+
26
+ "Hey #{authorized_email}, you're authorized!"
27
+ end
28
+ end
@@ -0,0 +1,2 @@
1
+ require "./app"
2
+ run TestApp
@@ -0,0 +1,21 @@
1
+ <html>
2
+ <head>
3
+ </head>
4
+ <body>
5
+
6
+ <h1>Test App</h1>
7
+
8
+ <p>
9
+ <% if authorized? %>
10
+ Hello, <%= authorized_email %> <a href="/logout">(logout)</a>
11
+ <% else %>
12
+ <%= render_login_button %>
13
+ <% end %>
14
+ </p>
15
+
16
+ <p>
17
+ see a <a href="/confidential">page that requires a login</a>.
18
+ </p>
19
+
20
+ </body>
21
+ </html>
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "json"
4
+ require "net/https"
5
+ require "sinatra/base"
6
+
7
+ # This module provides an interface to verify a users email address
8
+ # with browserid.org.
9
+ module Sinatra
10
+ module BrowserID
11
+
12
+ module Helpers
13
+ # Returns true if the current user has logged in and presented
14
+ # a valid assertion.
15
+ def authorized?
16
+ ! session[:browserid_email].nil?
17
+ end
18
+
19
+ # If the current user is not logged in, redirects to a login
20
+ # page. Override the login page by setting the Sinatra
21
+ # option <tt>:browserid_login_url</tt>.
22
+ def authorize!
23
+ session[:authorize_redirect_url] = request.url
24
+ login_url = settings.browserid_login_url
25
+ redirect login_url unless authorized?
26
+ end
27
+
28
+ # Logs out the current user.
29
+ def logout!
30
+ session[:browserid_email] = nil
31
+ end
32
+
33
+ # Returns the BrowserID verified email address, or nil if the
34
+ # user is not logged in.
35
+ def authorized_email
36
+ session[:browserid_email]
37
+ end
38
+
39
+ # Returns the HTML to render the BrowserID login button.
40
+ # Optionally takes a URL parameter for where the user should
41
+ # be redirected to after the assert POST back. You can
42
+ # customize the button image by setting the Sinatra option
43
+ # <tt>:browserid_login_button</tt> to a color (:orange,
44
+ # :red, :blue, :green, :grey) or an actual URL.
45
+ def render_login_button(redirect_url = nil)
46
+ case settings.browserid_login_button
47
+ when :orange, :red, :blue, :green, :grey
48
+ button_url = "#{settings.browserid_url}/i/sign_in_" \
49
+ "#{settings.browserid_login_button.to_s}.png"
50
+ else
51
+ button_url = settings.browserid_login_button
52
+ end
53
+
54
+ if session[:authorize_redirect_url]
55
+ redirect_url = session[:authorize_redirect_url]
56
+ session[:authorize_redirect_url] = nil
57
+ end
58
+ redirect_url ||= request.url
59
+
60
+ template = ERB.new(Templates::LOGIN_BUTTON)
61
+ template.result(binding)
62
+ end
63
+ end # module Helpers
64
+
65
+ def self.registered(app)
66
+ app.helpers BrowserID::Helpers
67
+
68
+ app.set :browserid_url, "https://browserid.org"
69
+ app.set :browserid_login_button, :red
70
+ app.set :browserid_login_url, "/_browserid_login"
71
+
72
+ app.get '/_browserid_login' do
73
+ # TODO(petef): render a page that initiates login without
74
+ # waiting for a user click.
75
+ render_login_button
76
+ end
77
+
78
+ app.post '/_browserid_assert' do
79
+ # TODO(petef): do verification locally, without a callback
80
+ audience = request.host_with_port
81
+ http = Net::HTTP.new("browserid.org", 443)
82
+ http.use_ssl = true
83
+ data = {
84
+ "assertion" => params[:assertion],
85
+ "audience" => audience,
86
+ }
87
+ data_str = data.collect { |k, v| "#{k}=#{v}" }.join("&")
88
+ res, body = http.post("/verify", data_str)
89
+
90
+ # TODO: check res is a 200
91
+ verify = JSON.parse(body) || nil
92
+ if verify.nil?
93
+ # JSON parsing error
94
+ return
95
+ end
96
+
97
+ if verify["status"] != "okay"
98
+ $stderr.puts "status was not OK. #{verify.inspect}"
99
+ return
100
+ end
101
+
102
+ session[:browserid_email] = verify["email"]
103
+ session[:browserid_expires] = verify["expires"].to_f / 1000
104
+
105
+ redirect params[:redirect] || "/"
106
+ end
107
+ end # def self.registered
108
+
109
+ module Templates
110
+ LOGIN_BUTTON = %q{
111
+ <script src="<%= settings.browserid_url %>/include.js" type="text/javascript"></script>
112
+ <script type="text/javascript">
113
+ function _browserid_login() {
114
+ navigator.id.getVerifiedEmail(function(assertion) {
115
+ if (assertion) {
116
+ document.forms._browserid_assert.assertion.value = assertion;
117
+ document.forms._browserid_assert.submit();
118
+ } else {
119
+ // TODO: handle failure case?
120
+ }
121
+ });
122
+ }
123
+ </script>
124
+
125
+ <form name="_browserid_assert" action="/_browserid_assert" method="post">
126
+ <input type="hidden" name="redirect" value="<%= redirect_url %>">
127
+ <input type="hidden" name="assertion" value="">
128
+ </form>
129
+
130
+ <a href="#"><img src="<%= button_url %>" id="browserid_login_button" border=0 onClick="_browserid_login()" /></a>
131
+ }
132
+ end
133
+ end # module BrowserID
134
+
135
+ register BrowserID
136
+ end # module Sinatra
137
+
138
+ #set :sessions, true
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sinatra-browserid
3
+ version: !ruby/object:Gem::Version
4
+ hash: 9
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ version: "0.1"
10
+ platform: ruby
11
+ authors:
12
+ - Pete Fritchman
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-10-21 00:00:00 -04:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: sinatra
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 19
29
+ segments:
30
+ - 1
31
+ - 1
32
+ - 0
33
+ version: 1.1.0
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ description:
37
+ email:
38
+ - petef@databits.net
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ files:
46
+ - README.md
47
+ - lib/sinatra/browserid.rb
48
+ - example/app.rb
49
+ - example/config.ru
50
+ - example/views/index.erb
51
+ has_rdoc: true
52
+ homepage: https://github.com/fetep/sinatra-browserid
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options:
57
+ - --inline-source
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ hash: 3
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ hash: 3
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ requirements: []
79
+
80
+ rubyforge_project:
81
+ rubygems_version: 1.3.7
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: Sinatra extension for user authentication with browserid.org
85
+ test_files: []
86
+