local-openid 0.1.1 → 0.2.0

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.
data/.document CHANGED
@@ -1,4 +1,5 @@
1
- History.txt
2
- LICENSE.txt
3
- README.txt
4
- bin/local-openid
1
+ NEWS
2
+ LICENSE
3
+ ChangeLog
4
+ README
5
+ lib/
data/.gitignore CHANGED
@@ -1,2 +1,14 @@
1
1
  pkg
2
2
  doc
3
+ *.rbc
4
+ /.config
5
+ /InstalledFiles
6
+ /doc
7
+ pkg/
8
+ /NEWS
9
+ /ChangeLog
10
+ /.manifest
11
+ /GIT-VERSION-FILE
12
+ /man
13
+ tags
14
+ TAGS
File without changes
@@ -0,0 +1,40 @@
1
+ #!/bin/sh
2
+
3
+ GVF=GIT-VERSION-FILE
4
+ DEF_VER=v0.2.0.GIT
5
+
6
+ LF='
7
+ '
8
+
9
+ # First see if there is a version file (included in release tarballs),
10
+ # then try git-describe, then default.
11
+ if test -f version
12
+ then
13
+ VN=$(cat version) || VN="$DEF_VER"
14
+ elif test -d .git -o -f .git &&
15
+ VN=$(git describe --abbrev=4 HEAD 2>/dev/null) &&
16
+ case "$VN" in
17
+ *$LF*) (exit 1) ;;
18
+ v[0-9]*)
19
+ git update-index -q --refresh
20
+ test -z "$(git diff-index --name-only HEAD --)" ||
21
+ VN="$VN-dirty" ;;
22
+ esac
23
+ then
24
+ VN=$(echo "$VN" | sed -e 's/-/./g');
25
+ else
26
+ VN="$DEF_VER"
27
+ fi
28
+
29
+ VN=$(expr "$VN" : v*'\(.*\)')
30
+
31
+ if test -r $GVF
32
+ then
33
+ VC=$(sed -e 's/^GIT_VERSION = //' <$GVF)
34
+ else
35
+ VC=unset
36
+ fi
37
+ test "$VN" = "$VC" || {
38
+ echo >&2 "GIT_VERSION = $VN"
39
+ echo "GIT_VERSION = $VN" >$GVF
40
+ }
@@ -1,19 +1,145 @@
1
- all:
1
+ all::
2
+ RUBY = ruby
3
+ RAKE = rake
4
+ RSYNC = rsync
5
+ GIT_URL = git://git.bogomips.org/local-openid.git
6
+
7
+ GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
8
+ @./GIT-VERSION-GEN
9
+ -include GIT-VERSION-FILE
10
+
11
+ pkg_extra := GIT-VERSION-FILE NEWS ChangeLog
12
+ manifest: $(pkg_extra)
13
+ $(RM) .manifest
14
+ $(MAKE) .manifest
15
+
16
+ .manifest:
17
+ (git ls-files && \
18
+ for i in $@ $(pkg_extra) $(man1_paths); \
19
+ do echo $$i; done) | LC_ALL=C sort > $@+
20
+ cmp $@+ $@ || mv $@+ $@
21
+ $(RM) $@+
22
+
23
+ NEWS: GIT-VERSION-FILE
24
+ $(RAKE) -s news_rdoc > $@+
25
+ mv $@+ $@
26
+
27
+ SINCE = 0.1.0
28
+ ChangeLog: LOG_VERSION = \
29
+ $(shell git rev-parse -q "$(GIT_VERSION)" >/dev/null 2>&1 && \
30
+ echo $(GIT_VERSION) || git describe)
31
+ ifneq ($(SINCE),)
32
+ ChangeLog: log_range = v$(SINCE)..$(LOG_VERSION)
33
+ endif
34
+ ChangeLog: GIT-VERSION-FILE
35
+ @echo "ChangeLog from $(GIT_URL) ($(log_range))" > $@+
36
+ @echo >> $@+
37
+ git log $(log_range) | sed -e 's/^/ /' >> $@+
38
+ mv $@+ $@
39
+
40
+ news_atom := http://bogomips.org/local-openid/NEWS.atom.xml
41
+ cgit_atom := http://git.bogomips.org/cgit/local-openid.git/atom/?h=master
42
+ atom = <link rel="alternate" title="Atom feed" href="$(1)" \
43
+ type="application/atom+xml"/>
44
+
45
+ doc: .document NEWS ChangeLog
46
+ find bin lib -type f -name '*.rbc' -exec rm -f '{}' ';'
47
+ rdoc -a -t "$(shell sed -ne '1s/^= //p' README)"
48
+ install -m644 COPYING doc/COPYING
49
+ install -m644 $(shell grep '^[A-Z]' .document) doc/
50
+ $(RUBY) -i -p -e \
51
+ '$$_.gsub!("</title>",%q{\&$(call atom,$(cgit_atom))})' \
52
+ doc/ChangeLog.html
53
+ $(RUBY) -i -p -e \
54
+ '$$_.gsub!("</title>",%q{\&$(call atom,$(news_atom))})' \
55
+ doc/NEWS.html doc/README.html
56
+ $(RAKE) -s news_atom > doc/NEWS.atom.xml
57
+ cd doc && ln README.html tmp && mv tmp index.html
2
58
 
3
59
  publish_doc:
4
60
  -git set-file-times
5
- $(MAKE) doc
61
+ $(RM) -r doc ChangeLog NEWS
62
+ $(MAKE) doc LOG_VERSION=$(shell git tag -l | tail -1)
63
+ @awk 'BEGIN{RS="=== ";ORS=""}NR==2{sub(/\n$$/,"");print RS""$$0 }' \
64
+ < NEWS > doc/LATEST
65
+ find doc/images doc/js -type f | \
66
+ TZ=UTC xargs touch -d '1970-01-01 00:00:00' doc/rdoc.css
6
67
  $(MAKE) doc_gz
7
- rsync -av --delete doc/ dcvr:/srv/bogomips/local-openid/
68
+ chmod 644 $$(find doc -type f)
69
+ $(RSYNC) -av --delete doc/ bogomips.org:/srv/bogomips/local-openid/
8
70
  git ls-files | xargs touch
9
71
 
10
- doc: .document
11
- rdoc -Na -m README.txt -t "$(shell sed -ne '1s/^= //p' README.txt)"
72
+ ifneq ($(VERSION),)
73
+ rfproject := qrp
74
+ rfpackage := local-openid
75
+ pkggem := pkg/$(rfpackage)-$(VERSION).gem
76
+ pkgtgz := pkg/$(rfpackage)-$(VERSION).tgz
77
+ release_notes := release_notes-$(VERSION)
78
+ release_changes := release_changes-$(VERSION)
79
+
80
+ release-notes: $(release_notes)
81
+ release-changes: $(release_changes)
82
+ $(release_changes):
83
+ $(RAKE) -s release_changes > $@+
84
+ $(VISUAL) $@+ && test -s $@+ && mv $@+ $@
85
+ $(release_notes):
86
+ GIT_URL=$(GIT_URL) $(RAKE) -s release_notes > $@+
87
+ $(VISUAL) $@+ && test -s $@+ && mv $@+ $@
88
+
89
+ # ensures we're actually on the tagged $(VERSION), only used for release
90
+ verify:
91
+ test x"$(shell umask)" = x0022
92
+ git rev-parse --verify refs/tags/v$(VERSION)^{}
93
+ git diff-index --quiet HEAD^0
94
+ test `git rev-parse --verify HEAD^0` = \
95
+ `git rev-parse --verify refs/tags/v$(VERSION)^{}`
96
+
97
+ fix-perms:
98
+ -git ls-tree -r HEAD | awk '/^100644 / {print $$NF}' | xargs chmod 644
99
+ -git ls-tree -r HEAD | awk '/^100755 / {print $$NF}' | xargs chmod 755
100
+
101
+ gem: $(pkggem)
102
+
103
+ install-gem: $(pkggem)
104
+ gem install $(CURDIR)/$<
105
+
106
+ $(pkggem): manifest fix-perms
107
+ gem build $(rfpackage).gemspec
108
+ mkdir -p pkg
109
+ mv $(@F) $@
110
+
111
+ $(pkgtgz): distdir = $(basename $@)
112
+ $(pkgtgz): HEAD = v$(VERSION)
113
+ $(pkgtgz): manifest fix-perms
114
+ @test -n "$(distdir)"
115
+ $(RM) -r $(distdir)
116
+ mkdir -p $(distdir)
117
+ tar cf - `cat .manifest` | (cd $(distdir) && tar xf -)
118
+ cd pkg && tar c $(basename $(@F)) | gzip -9 > $(@F)+
119
+ mv $@+ $@
120
+
121
+ package: $(pkgtgz) $(pkggem)
122
+
123
+ test-release: verify package $(release_notes) $(release_changes)
124
+ release: verify package $(release_notes) $(release_changes)
125
+ # make tgz release on RubyForge
126
+ rubyforge add_release -f -n $(release_notes) -a $(release_changes) \
127
+ $(rfproject) $(rfpackage) $(VERSION) $(pkgtgz)
128
+ # push gem to Gemcutter
129
+ gem push $(pkggem)
130
+ # in case of gem downloads from RubyForge releases page
131
+ -rubyforge add_file \
132
+ $(rfproject) $(rfpackage) $(VERSION) $(pkggem)
133
+ else
134
+ gem install-gem: GIT-VERSION-FILE
135
+ $(MAKE) $@ VERSION=$(GIT_VERSION)
136
+ endif
12
137
 
13
138
  # Create gzip variants of the same timestamp as the original so nginx
14
139
  # "gzip_static on" can serve the gzipped versions directly.
15
- doc_gz: suf := html js css
16
- doc_gz: globs := $(addprefix doc/*.,$(suf)) $(addprefix doc/*/*.,$(suf))
17
- doc_gz: docs := $(wildcard $(globs))
140
+ doc_gz: docs = $(shell find doc -type f ! -regex '^.*\.\(gif\|jpg\|png\|gz\)$$')
18
141
  doc_gz:
19
- for i in $(docs); do gzip < $$i > $$i.gz; touch -r $$i $$i.gz; done
142
+ touch doc/NEWS.atom.xml -d "$$(awk 'NR==1{print $$4,$$5,$$6}' NEWS)"
143
+ for i in $(docs); do \
144
+ gzip --rsyncable -9 < $$i > $$i.gz; touch -r $$i $$i.gz; done
145
+ .PHONY: .FORCE-GIT-VERSION-FILE doc manifest
data/LICENSE ADDED
@@ -0,0 +1,5 @@
1
+ local-openid is copyrighted free software by all contributors, see logs
2
+ in revision control for names and email addresses of all of them. You
3
+ can redistribute it and/or modify it under either the terms of the GNU
4
+ Affero General Public License, version 3. See the link:COPYING file
5
+ for details.
@@ -1,9 +1,5 @@
1
1
  = local-openid: Single User, Ephemeral OpenID Provider
2
2
 
3
- * http://bogomips.org/local-openid
4
-
5
- == Description
6
-
7
3
  local-openid allows users with shell accounts on servers to authenticate
8
4
  with OpenID consumers by editing a YAML file in their home directory
9
5
  instead of authenticating through HTTP/HTTPS.
@@ -43,17 +39,35 @@ setup.rb is also provided for non-Rubygems users.
43
39
  == Requirements
44
40
 
45
41
  local-openid is a small Sinatra application. It requires the Ruby
46
- OpenID library (2.x), Sinatra (0.9+), Rack (0.9+), and any Rack-enabled
42
+ OpenID library (2.x), Sinatra (1.0), Rack and any Rack-enabled
47
43
  server. To be useful, it also depends on having a user account on a
48
44
  machine with a publically-accessible IP and DNS name to use as your
49
45
  OpenID identity.
50
46
 
47
+ == Running
48
+
49
+ "local-openid" should be installed in your $PATH by RubyGems or
50
+ setup.rb. It is a Sinatra application and takes the usual
51
+ command-line arguments. It binds on all addresses (0.0.0.0) and port
52
+ 4567 by default, using the standard WEBrick web server.
53
+
54
+ You may specify a different port with the *-p* switch and address with
55
+ the *-o* switch. The following command will start local-openid on port
56
+ 3000 bound to localhost (useful if behind a reverse proxy like nginx).
57
+
58
+ local-openid -o 127.0.0.1 -p 3000
59
+
51
60
  == Hacking
52
61
 
53
62
  I don't have any plans for more development with local-openid. It was
54
63
  after all, just a weekend hack. It does what I want it to and nothing
55
64
  more.
56
65
 
66
+ You can use the {mailing list}[mailto:local.openid@librelist.com] to
67
+ share ideas, patches, pull requests with other users. Remember, I
68
+ wrote local-openid because I find the web difficult to use. So I'll
69
+ only accept communication about local-openid via email :)
70
+
57
71
  Feel free to fork it and customize it to your needs. Of course, drop me
58
72
  a line if you fix any bugs or notice any security holes in it.
59
73
 
@@ -69,11 +83,6 @@ You may browse the code from the web and download the latest tarballs here:
69
83
  * http://git.bogomips.org/cgit/local-openid.git
70
84
  * http://repo.or.cz/w/local-openid.git (gitweb mirror)
71
85
 
72
- == License
73
-
74
- Copyright 2009 Eric Wong. It is licensed under the GNU Affero General
75
- Public License, version 3. See the LICENSE file for details.
76
-
77
86
  == Disclaimer
78
87
 
79
88
  There is NO WARRANTY whatsoever, implied or otherwise. OpenID may not
@@ -84,5 +93,6 @@ credentials when your provider implementation has 99.999% downtime :)
84
93
 
85
94
  == Contact
86
95
 
87
- Eric Wong, normalperson@yhbt.net
88
- OpenID: http://e.yhbt.net/
96
+ * Original author: Eric Wong, normalperson@yhbt.net
97
+ * OpenID: http://e.yhbt.net/
98
+ * mailing list: local.openid@librelist.com
data/Rakefile CHANGED
@@ -1,12 +1,183 @@
1
- require 'rubygems'
2
- require 'hoe'
1
+ # -*- encoding: binary -*-
2
+ autoload :Gem, 'rubygems'
3
3
 
4
- readme = File.readlines('README.txt')
4
+ def tags
5
+ timefmt = '%Y-%m-%dT%H:%M:%SZ'
6
+ @tags ||= `git tag -l`.split(/\n/).map do |tag|
7
+ if %r{\Av[\d\.]+\z} =~ tag
8
+ header, subject, body = `git cat-file tag #{tag}`.split(/\n\n/, 3)
9
+ header = header.split(/\n/)
10
+ tagger = header.grep(/\Atagger /).first
11
+ body ||= "initial"
12
+ {
13
+ :time => Time.at(tagger.split(/ /)[-2].to_i).utc.strftime(timefmt),
14
+ :tagger_name => %r{^tagger ([^<]+)}.match(tagger)[1].strip,
15
+ :tagger_email => %r{<([^>]+)>}.match(tagger)[1].strip,
16
+ :id => `git rev-parse refs/tags/#{tag}`.chomp!,
17
+ :tag => tag,
18
+ :subject => subject,
19
+ :body => body,
20
+ }
21
+ end
22
+ end.compact.sort { |a,b| b[:time] <=> a[:time] }
23
+ end
24
+
25
+ cgit_url = "http://git.bogomips.org/cgit/local-openid.git"
26
+ git_url = ENV['GIT_URL'] || 'git://git.bogomips.org/local-openid.git'
27
+
28
+ desc 'prints news as an Atom feed'
29
+ task :news_atom do
30
+ require 'nokogiri'
31
+ new_tags = tags[0,10]
32
+ puts(Nokogiri::XML::Builder.new do
33
+ feed :xmlns => "http://www.w3.org/2005/Atom" do
34
+ id! "http://bogomips.org/local-openid/NEWS.atom.xml"
35
+ title "local-openid news"
36
+ subtitle %q{Single User, Ephemeral OpenID Provider}
37
+ link! :rel => 'alternate', :type => 'text/html',
38
+ :href => 'http://bogomips.org/local-openid/NEWS.html'
39
+ updated(new_tags.empty? ? "1970-01-01T00:00:00Z" : new_tags.first[:time])
40
+ new_tags.each do |tag|
41
+ entry do
42
+ title tag[:subject]
43
+ updated tag[:time]
44
+ published tag[:time]
45
+ author {
46
+ name tag[:tagger_name]
47
+ email tag[:tagger_email]
48
+ }
49
+ url = "#{cgit_url}/tag/?id=#{tag[:tag]}"
50
+ link! :rel => "alternate", :type => "text/html", :href =>url
51
+ id! url
52
+ message_only = tag[:body].split(/\n.+\(\d+\):\n {6}/s).first.strip
53
+ content({:type =>:text}, message_only)
54
+ content(:type =>:xhtml) { pre tag[:body] }
55
+ end
56
+ end
57
+ end
58
+ end.to_xml)
59
+ end
60
+
61
+ desc 'prints RDoc-formatted news'
62
+ task :news_rdoc do
63
+ tags.each do |tag|
64
+ time = tag[:time].tr!('T', ' ').gsub!(/:\d\dZ/, ' UTC')
65
+ puts "=== #{tag[:tag].sub(/^v/, '')} / #{time}"
66
+ puts ""
67
+
68
+ body = tag[:body]
69
+ puts tag[:body].gsub(/^/sm, " ").gsub(/[ \t]+$/sm, "")
70
+ puts ""
71
+ end
72
+ end
73
+
74
+ desc "print release changelog for Rubyforge"
75
+ task :release_changes do
76
+ version = ENV['VERSION'] or abort "VERSION= needed"
77
+ version = "v#{version}"
78
+ vtags = tags.map { |tag| tag[:tag] =~ /\Av/ and tag[:tag] }.sort
79
+ prev = vtags[vtags.index(version) - 1]
80
+ if prev
81
+ system('git', 'diff', '--stat', prev, version) or abort $?
82
+ puts ""
83
+ system('git', 'log', "#{prev}..#{version}") or abort $?
84
+ else
85
+ system('git', 'log', version) or abort $?
86
+ end
87
+ end
88
+
89
+ desc "print release notes for Rubyforge"
90
+ task :release_notes do
91
+ spec = Gem::Specification.load('local-openid.gemspec')
92
+ puts spec.description.strip
93
+ puts ""
94
+ puts "* #{spec.homepage}"
95
+ puts "* #{spec.email}"
96
+ puts "* #{git_url}"
97
+
98
+ _, _, body = `git cat-file tag v#{spec.version}`.split(/\n\n/, 3)
99
+ print "\nChanges:\n\n"
100
+ puts body
101
+ end
102
+
103
+ desc "read news article from STDIN and post to rubyforge"
104
+ task :publish_news do
105
+ require 'rubyforge'
106
+ IO.select([STDIN], nil, nil, 1) or abort "E: news must be read from stdin"
107
+ msg = STDIN.readlines
108
+ subject = msg.shift
109
+ blank = msg.shift
110
+ blank == "\n" or abort "no newline after subject!"
111
+ subject.strip!
112
+ body = msg.join("").strip!
113
+
114
+ rf = RubyForge.new.configure
115
+ rf.login
116
+ rf.post_news('qrp', subject, body)
117
+ end
118
+
119
+ desc "post to RAA"
120
+ task :raa_update do
121
+ require 'net/http'
122
+ require 'net/netrc'
123
+ rc = Net::Netrc.locate('local-openid-raa') or abort "~/.netrc not found"
124
+ password = rc.password
125
+
126
+ s = Gem::Specification.load('local-openid.gemspec')
127
+ desc = [ s.description.strip ]
128
+ desc << ""
129
+ desc << "* #{s.email}"
130
+ desc << "* #{git_url}"
131
+ desc << "* #{cgit_url}"
132
+ desc = desc.join("\n")
133
+ uri = URI.parse('http://raa.ruby-lang.org/regist.rhtml')
134
+ form = {
135
+ :name => s.name,
136
+ :short_description => s.summary,
137
+ :version => s.version.to_s,
138
+ :status => 'stable',
139
+ :owner => s.authors.first,
140
+ :email => s.email,
141
+ :category_major => 'Application',
142
+ :category_minor => 'WWW',
143
+ :url => s.homepage,
144
+ :download => 'http://rubyforge.org/frs/?group_id=5626',
145
+ :license => "OpenSource", # AGPLv3, specifically
146
+ :description_style => 'Plain',
147
+ :description => desc,
148
+ :pass => password,
149
+ :submit => "Update",
150
+ }
151
+ res = Net::HTTP.post_form(uri, form)
152
+ p res
153
+ puts res.body
154
+ end
155
+
156
+ desc "post to FM"
157
+ task :fm_update do
158
+ require 'tempfile'
159
+ require 'net/http'
160
+ require 'net/netrc'
161
+ require 'json'
162
+ version = ENV['VERSION'] or abort "VERSION= needed"
163
+ uri = URI.parse('http://freshmeat.net/projects/local-openid/releases.json')
164
+ rc = Net::Netrc.locate('local-openid-fm') or abort "~/.netrc not found"
165
+ api_token = rc.password
166
+ changelog = tags.find { |t| t[:tag] == "v#{version}" }[:body]
167
+ tmp = Tempfile.new('fm-changelog')
168
+ tmp.syswrite(changelog)
169
+ system(ENV["VISUAL"], tmp.path) or abort "#{ENV["VISUAL"]} failed: #$?"
170
+ changelog = File.read(tmp.path).strip
5
171
 
6
- Hoe.new('local-openid', '0.1.1') do |p|
7
- p.rubyforge_name = 'qrp'
8
- p.developer('Eric Wong', 'normalperson@yhbt.net')
9
- p.summary = readme[0].split(/\s*:\s*/)[1]
10
- p.url = 'http://bogomips.org/local-openid'
11
- p.extra_deps << [ 'sinatra', '>= 0.9' ]
172
+ req = {
173
+ "auth_code" => api_token,
174
+ "release" => {
175
+ "tag_list" => "Stable",
176
+ "version" => version,
177
+ "changelog" => changelog,
178
+ },
179
+ }.to_json
180
+ Net::HTTP.start(uri.host, uri.port) do |http|
181
+ p http.post(uri.path, req, {'Content-Type'=>'application/json'})
182
+ end
12
183
  end
@@ -1,300 +1,19 @@
1
- #!/home/ew/bin/ruby
2
- # A personal OpenID identity provider, authentication is done by editing
3
- # a YAML file on the server where this application runs
4
- # (~/.local-openid/config.yml by default) instead of via HTTP/HTTPS
5
- # form authentication in the browser.
6
-
7
- require 'tempfile'
8
- require 'time'
9
- require 'yaml'
10
-
11
- require 'sinatra'
12
- require 'openid'
13
- require 'openid/extensions/sreg'
14
- require 'openid/extensions/pape'
15
- require 'openid/store/filesystem'
16
- set :static, false
17
- set :sessions, true
18
- set :environment, :production
19
- set :logging, false # load Rack::CommonLogger in config.ru instead
20
-
21
- BEGIN {
22
- $local_openid ||=
23
- File.expand_path(ENV['LOCAL_OPENID_DIR'] || '~/.local-openid')
24
- Dir.mkdir($local_openid) unless File.directory?($local_openid)
1
+ #!/usr/bin/env ruby
2
+ require 'local_openid'
3
+ require 'optparse'
4
+ require 'socket'
5
+ BasicSocket.do_not_reverse_lookup = true
6
+ opts = {
7
+ :server => 'webrick', # webrick is standard, and plenty fast enough
25
8
  }
26
-
27
- # all the sinatra endpoints:
28
- get('/xrds') { big_lock { render_xrds(true) } }
29
- get('/') { big_lock { get_or_post } }
30
- post('/') { big_lock { get_or_post } }
31
-
32
- private
33
-
34
- # yes, I use gsub for templating because I find it easier than erb :P
35
- PROMPT = %q!<html>
36
- <head><title>OpenID login: %s</title></head>
37
- <body><h1>reload this page when approved: %s</h1></body>
38
- </html>!
39
-
40
- XRDS_HTML = %q!<html><head>
41
- <link rel="openid.server" href="%s" />
42
- <link rel="openid2.provider" href="%s" />
43
- <meta http-equiv="X-XRDS-Location" content="%sxrds" />
44
- <title>OpenID server endpoint</title>
45
- </head><body>OpenID server endpoint</body></html>!
46
-
47
- XRDS_XML = %q!<?xml version="1.0" encoding="UTF-8"?>
48
- <xrds:XRDS
49
- xmlns:xrds="xri://$xrds"
50
- xmlns="xri://$xrd*($v*2.0)">
51
- <XRD>
52
- <Service priority="0">
53
- %types
54
- <URI>%s</URI>
55
- </Service>
56
- </XRD>
57
- </xrds:XRDS>!
58
-
59
- CONFIG_HEADER = %!
60
- This file may be changed by #{__FILE__} or your favorite $EDITOR
61
- comments will be deleted when modified by #{__FILE__}. See the
62
- comments end of this file for help on the format.
63
- !.lstrip!
64
-
65
- CONFIG_TRAILER = %!
66
- Configuration file description.
67
-
68
- * allowed_ips An array of strings representing IPs that may
69
- authenticate through local-openid. Only put
70
- IP addresses that you trust in here.
71
-
72
- Each OpenID consumer trust root will have its own hash keyed by
73
- the trust root URL. Keys in this hash are:
74
-
75
- - expires The time at which this login will expire.
76
- This is generally the only entry you need to edit
77
- to approve a site. You may also delete this line
78
- and rename the "expires1m" to this.
79
- - expires1m The time 1 minute from when this entry was updated.
80
- This is provided as a convenience for replacing
81
- the default "expires" entry. This key may be safely
82
- removed by a user editing it.
83
- - updated Time this entry was updated, strictly informational.
84
- - session_id Unique identifier in your session cookie to prevent
85
- other users from hijacking your session. You may
86
- delete this if you've changed browsers or computers.
87
- - assoc_handle See the OpenID specs, may be empty. Do not edit this.
88
-
89
- SReg keys supported by the Ruby OpenID implementation should be
90
- supported, they include (but are not limited to):
91
- ! << OpenID::SReg::DATA_FIELDS.map do |key, value|
92
- " - #{key}: #{value}"
93
- end.join("\n") << %!
94
- SReg keys may be global at the top-level or private to each trust root.
95
- Per-trust root SReg entries override the global settings.
96
- !
97
-
98
- include OpenID::Server
99
-
100
- # this is the heart of our provider logic, adapted from the
101
- # Ruby OpenID gem Rails example
102
- def get_or_post
103
- oidreq = begin
104
- server.decode_request(params)
105
- rescue ProtocolError => err
106
- halt(500, err.to_s)
107
- end
108
-
109
- oidreq or return render_xrds
110
-
111
- oidresp = case oidreq
112
- when CheckIDRequest
113
- if oidreq.id_select && oidreq.immediate
114
- oidreq.answer(false)
115
- elsif is_authorized?(oidreq)
116
- resp = oidreq.answer(true, nil, server_root)
117
- add_sreg(oidreq, resp)
118
- add_pape(oidreq, resp)
119
- resp
120
- elsif oidreq.immediate
121
- oidreq.answer(false, server_root)
122
- else
123
- session[:id] ||= "#{Time.now.to_i}.#$$.#{rand}"
124
- session[:ip] = request.ip
125
- merge_config(oidreq)
126
- write_config
127
-
128
- # here we allow our user to open $EDITOR and edit the appropriate
129
- # 'expires' field in config.yml corresponding to oidreq.trust_root
130
- return PROMPT.gsub(/%s/, oidreq.trust_root)
131
- end
132
- else
133
- server.handle_request(oidreq)
134
- end
135
-
136
- finalize_response(oidresp)
137
- end
138
-
139
- # we're the provider for exactly one identity. However, we do rely on
140
- # being proxied and being hit with an appropriate HTTP Host: header.
141
- # Don't expect OpenID consumers to handle port != 80.
142
- def server_root
143
- "http://#{request.host}/"
144
- end
145
-
146
- def server
147
- @server ||= Server.new(
148
- OpenID::Store::Filesystem.new("#$local_openid/store"),
149
- server_root)
150
- end
151
-
152
- # support the simple registration extension if possible,
153
- # allow per-site overrides of various data points
154
- def add_sreg(oidreq, oidresp)
155
- sregreq = OpenID::SReg::Request.from_openid_request(oidreq) or return
156
- per_site = config[oidreq.trust_root] || {}
157
-
158
- sreg_data = {}
159
- sregreq.all_requested_fields.each do |field|
160
- sreg_data[field] = per_site[field] || config[field]
161
- end
162
-
163
- sregresp = OpenID::SReg::Response.extract_response(sregreq, sreg_data)
164
- oidresp.add_extension(sregresp)
165
- end
166
-
167
- def add_pape(oidreq, oidresp)
168
- papereq = OpenID::PAPE::Request.from_openid_request(oidreq) or return
169
- paperesp = OpenID::PAPE::Response.new(papereq.preferred_auth_policies,
170
- papereq.max_auth_age)
171
- # since this implementation requires shell/filesystem access to the
172
- # OpenID server to authenticate, we can say we're at the highest
173
- # auth level possible...
174
- paperesp.add_policy_uri(OpenID::PAPE::AUTH_MULTI_FACTOR_PHYSICAL)
175
- paperesp.auth_time = Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
176
- paperesp.nist_auth_level = 4
177
- oidresp.add_extension(paperesp)
178
- end
179
-
180
- def err(msg)
181
- env['rack.errors'].write("#{msg}\n")
182
- false
183
- end
184
-
185
- def finalize_response(oidresp)
186
- server.signatory.sign(oidresp) if oidresp.needs_signing
187
- web_response = server.encode_response(oidresp)
188
-
189
- case web_response.code
190
- when HTTP_OK
191
- web_response.body
192
- when HTTP_REDIRECT
193
- location = web_response.headers['location']
194
- err("redirecting to: #{location} ...")
195
- redirect(location)
196
- else
197
- halt(500, web_response.body)
9
+ OptionParser.new { |op|
10
+ op.on('-s <mongrel|thin|webrick>') { |v| opts[:server] = v }
11
+ op.on('-p port') { |val| opts[:port] = val.to_i }
12
+ op.on('-o addr') { |val| opts[:bind] = val }
13
+ op.on('-h', '--help', 'Show this message') do
14
+ puts op.to_s
15
+ exit
198
16
  end
199
- end
200
-
201
- # the heart of our custom authentication logic
202
- def is_authorized?(oidreq)
203
- (config['allowed_ips'] ||= []).include?(request.ip) or
204
- return err("Not allowed: #{request.ip}\n" \
205
- "You need to put this IP in the 'allowed_ips' array "\
206
- "in:\n #$local_openid/config.yml")
207
-
208
- request.ip == session[:ip] or
209
- return err("session IP mismatch: " \
210
- "#{request.ip.inspect} != #{session[:ip].inspect}")
211
-
212
- trust_root = oidreq.trust_root
213
- per_site = config[trust_root] or
214
- return err("trust_root unknown: #{trust_root}")
215
-
216
- session_id = session[:id] or return err("no session ID")
217
-
218
- assoc_handle = per_site['assoc_handle'] # this may be nil
219
- expires = per_site['expires'] or
220
- return err("no expires (trust_root=#{trust_root})")
221
-
222
- assoc_handle == oidreq.assoc_handle or
223
- return err("assoc_handle mismatch: " \
224
- "#{assoc_handle.inspect} != #{oidreq.assoc_handle.inspect}" \
225
- " (trust_root=#{trust_root})")
17
+ }.parse!(ARGV)
226
18
 
227
- per_site['session_id'] == session_id or
228
- return err("session ID mismatch: " \
229
- "#{per_site['session_id'].inspect} != #{session_id.inspect}" \
230
- " (trust_root=#{trust_root})")
231
-
232
- expires > Time.now or
233
- return err("Expired: #{expires.inspect} (trust_root=#{trust_root})")
234
-
235
- true
236
- end
237
-
238
- def config
239
- @config ||= begin
240
- YAML.load(File.read("#$local_openid/config.yml"))
241
- rescue Errno::ENOENT
242
- {}
243
- end
244
- end
245
-
246
- def merge_config(oidreq)
247
- per_site = config[oidreq.trust_root] ||= {}
248
- per_site.merge!({
249
- 'assoc_handle' => oidreq.assoc_handle,
250
- 'expires' => Time.at(0).utc,
251
- 'updated' => Time.now.utc,
252
- 'expires1m' => Time.now.utc + 60, # easy edit to "expires" in $EDITOR
253
- 'session_id' => session[:id],
254
- })
255
- end
256
-
257
- def write_config
258
- path = "#$local_openid/config.yml"
259
- tmp = Tempfile.new('config.yml', File.dirname(path))
260
- tmp.syswrite(CONFIG_HEADER.gsub(/^/m, "# "))
261
- tmp.syswrite(config.to_yaml)
262
- tmp.syswrite(CONFIG_TRAILER.gsub(/^/m, "# "))
263
- tmp.fsync
264
- File.rename(tmp.path, path)
265
- tmp.close!
266
- end
267
-
268
- # this output is designed to be parsed by OpenID consumers
269
- def render_xrds(force = false)
270
- if force || request.accept.include?('application/xrds+xml')
271
-
272
- # this seems to work...
273
- types = request.accept.include?('application/xrds+xml') ?
274
- [ OpenID::OPENID_2_0_TYPE, OpenID::OPENID_1_0_TYPE, OpenID::SREG_URI ] :
275
- [ OpenID::OPENID_IDP_2_0_TYPE ]
276
-
277
- headers['Content-Type'] = 'application/xrds+xml'
278
- types = types.map { |uri| "<Type>#{uri}</Type>" }.join("\n")
279
- XRDS_XML.gsub(/%s/, server_root).gsub!(/%types/, types)
280
- else # render a browser-friendly page with an XRDS pointer
281
- headers['X-XRDS-Location'] = "#{server_root}xrds"
282
- XRDS_HTML.gsub(/%s/, server_root)
283
- end
284
- end
285
-
286
- # if a single-user OpenID provider like us is being hit by multiple
287
- # clients at once, then something is seriously wrong. Can't use
288
- # Mutexes here since somebody could be running this as a CGI script
289
- def big_lock(&block)
290
- lock = "#$local_openid/lock"
291
- File.open(lock, File::WRONLY|File::CREAT|File::EXCL, 0600) do |fp|
292
- begin
293
- yield
294
- ensure
295
- File.unlink(lock)
296
- end
297
- end
298
- rescue Errno::EEXIST
299
- err("Lock: #{lock} exists! Possible hijacking attempt") rescue nil
300
- end
19
+ LocalOpenID.run!(opts)
@@ -0,0 +1,302 @@
1
+ # A personal OpenID identity provider, authentication is done by editing
2
+ # a YAML file on the server where this application runs
3
+ # (~/.local-openid/config.yml by default) instead of via HTTP/HTTPS
4
+ # form authentication in the browser.
5
+ #:stopdoc:
6
+ require 'tempfile'
7
+ require 'time'
8
+ require 'yaml'
9
+
10
+ require 'sinatra/base'
11
+ require 'openid'
12
+ require 'openid/extensions/sreg'
13
+ require 'openid/extensions/pape'
14
+ require 'openid/store/filesystem'
15
+
16
+ class LocalOpenID < Sinatra::Base
17
+ set :static, false
18
+ set :sessions, true
19
+ set :environment, :production
20
+ set :logging, false # load Rack::CommonLogger in config.ru instead
21
+
22
+ @@dir ||= File.expand_path(ENV['LOCAL_OPENID_DIR'] || '~/.local-openid')
23
+ Dir.mkdir(@@dir) unless File.directory?(@@dir)
24
+
25
+ # all the sinatra endpoints:
26
+ get('/xrds') { big_lock { render_xrds(true) } }
27
+ get('/') { big_lock { get_or_post } }
28
+ post('/') { big_lock { get_or_post } }
29
+
30
+ private
31
+
32
+ # yes, I use gsub for templating because I find it easier than erb :P
33
+ PROMPT = %q!<html>
34
+ <head><title>OpenID login: %s</title></head>
35
+ <body><h1>reload this page when approved: %s</h1></body>
36
+ </html>!
37
+
38
+ XRDS_HTML = %q!<html><head>
39
+ <link rel="openid.server" href="%s" />
40
+ <link rel="openid2.provider" href="%s" />
41
+ <meta http-equiv="X-XRDS-Location" content="%sxrds" />
42
+ <title>OpenID server endpoint</title>
43
+ </head><body>OpenID server endpoint</body></html>!
44
+
45
+ XRDS_XML = %q!<?xml version="1.0" encoding="UTF-8"?>
46
+ <xrds:XRDS
47
+ xmlns:xrds="xri://$xrds"
48
+ xmlns="xri://$xrd*($v*2.0)">
49
+ <XRD>
50
+ <Service priority="0">
51
+ %types
52
+ <URI>%s</URI>
53
+ </Service>
54
+ </XRD>
55
+ </xrds:XRDS>!
56
+
57
+ CONFIG_HEADER = %!
58
+ This file may be changed by #{__FILE__} or your favorite $EDITOR
59
+ comments will be deleted when modified by #{__FILE__}. See the
60
+ comments end of this file for help on the format.
61
+ !.lstrip!
62
+
63
+ CONFIG_TRAILER = %!
64
+ Configuration file description.
65
+
66
+ * allowed_ips An array of strings representing IPs that may
67
+ authenticate through local-openid. Only put
68
+ IP addresses that you trust in here.
69
+
70
+ Each OpenID consumer trust root will have its own hash keyed by
71
+ the trust root URL. Keys in this hash are:
72
+
73
+ - expires The time at which this login will expire.
74
+ This is generally the only entry you need to edit
75
+ to approve a site. You may also delete this line
76
+ and rename the "expires1m" to this.
77
+ - expires1m The time 1 minute from when this entry was updated.
78
+ This is provided as a convenience for replacing
79
+ the default "expires" entry. This key may be safely
80
+ removed by a user editing it.
81
+ - updated Time this entry was updated, strictly informational.
82
+ - session_id Unique identifier in your session cookie to prevent
83
+ other users from hijacking your session. You may
84
+ delete this if you've changed browsers or computers.
85
+ - assoc_handle See the OpenID specs, may be empty. Do not edit this.
86
+
87
+ SReg keys supported by the Ruby OpenID implementation should be
88
+ supported, they include (but are not limited to):
89
+ ! << OpenID::SReg::DATA_FIELDS.map do |key, value|
90
+ " - #{key}: #{value}"
91
+ end.join("\n") << %!
92
+ SReg keys may be global at the top-level or private to each trust root.
93
+ Per-trust root SReg entries override the global settings.
94
+ !
95
+
96
+ include OpenID::Server
97
+
98
+ # this is the heart of our provider logic, adapted from the
99
+ # Ruby OpenID gem Rails example
100
+ def get_or_post
101
+ oidreq = begin
102
+ server.decode_request(params)
103
+ rescue ProtocolError => err
104
+ halt(500, err.to_s)
105
+ end
106
+
107
+ oidreq or return render_xrds
108
+
109
+ oidresp = case oidreq
110
+ when CheckIDRequest
111
+ if oidreq.id_select && oidreq.immediate
112
+ oidreq.answer(false)
113
+ elsif is_authorized?(oidreq)
114
+ resp = oidreq.answer(true, nil, server_root)
115
+ add_sreg(oidreq, resp)
116
+ add_pape(oidreq, resp)
117
+ resp
118
+ elsif oidreq.immediate
119
+ oidreq.answer(false, server_root)
120
+ else
121
+ session[:id] ||= "#{Time.now.to_i}.#$$.#{rand}"
122
+ session[:ip] = request.ip
123
+ merge_config(oidreq)
124
+ write_config
125
+
126
+ # here we allow our user to open $EDITOR and edit the appropriate
127
+ # 'expires' field in config.yml corresponding to oidreq.trust_root
128
+ return PROMPT.gsub(/%s/, oidreq.trust_root)
129
+ end
130
+ else
131
+ server.handle_request(oidreq)
132
+ end
133
+
134
+ finalize_response(oidresp)
135
+ end
136
+
137
+ # we're the provider for exactly one identity. However, we do rely on
138
+ # being proxied and being hit with an appropriate HTTP Host: header.
139
+ # Don't expect OpenID consumers to handle port != 80.
140
+ def server_root
141
+ "http://#{request.host}/"
142
+ end
143
+
144
+ def server
145
+ @server ||= Server.new(
146
+ OpenID::Store::Filesystem.new("#@@dir/store"),
147
+ server_root)
148
+ end
149
+
150
+ # support the simple registration extension if possible,
151
+ # allow per-site overrides of various data points
152
+ def add_sreg(oidreq, oidresp)
153
+ sregreq = OpenID::SReg::Request.from_openid_request(oidreq) or return
154
+ per_site = config[oidreq.trust_root] || {}
155
+
156
+ sreg_data = {}
157
+ sregreq.all_requested_fields.each do |field|
158
+ sreg_data[field] = per_site[field] || config[field]
159
+ end
160
+
161
+ sregresp = OpenID::SReg::Response.extract_response(sregreq, sreg_data)
162
+ oidresp.add_extension(sregresp)
163
+ end
164
+
165
+ def add_pape(oidreq, oidresp)
166
+ papereq = OpenID::PAPE::Request.from_openid_request(oidreq) or return
167
+ paperesp = OpenID::PAPE::Response.new(papereq.preferred_auth_policies,
168
+ papereq.max_auth_age)
169
+ # since this implementation requires shell/filesystem access to the
170
+ # OpenID server to authenticate, we can say we're at the highest
171
+ # auth level possible...
172
+ paperesp.add_policy_uri(OpenID::PAPE::AUTH_MULTI_FACTOR_PHYSICAL)
173
+ paperesp.auth_time = Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
174
+ paperesp.nist_auth_level = 4
175
+ oidresp.add_extension(paperesp)
176
+ end
177
+
178
+ def err(msg)
179
+ env['rack.errors'].write("#{msg}\n")
180
+ false
181
+ end
182
+
183
+ def finalize_response(oidresp)
184
+ server.signatory.sign(oidresp) if oidresp.needs_signing
185
+ web_response = server.encode_response(oidresp)
186
+
187
+ case web_response.code
188
+ when HTTP_OK
189
+ web_response.body
190
+ when HTTP_REDIRECT
191
+ location = web_response.headers['location']
192
+ err("redirecting to: #{location} ...")
193
+ redirect(location)
194
+ else
195
+ halt(500, web_response.body)
196
+ end
197
+ end
198
+
199
+ # the heart of our custom authentication logic
200
+ def is_authorized?(oidreq)
201
+ (config['allowed_ips'] ||= []).include?(request.ip) or
202
+ return err("Not allowed: #{request.ip}\n" \
203
+ "You need to put this IP in the 'allowed_ips' array "\
204
+ "in:\n #@@dir/config.yml")
205
+
206
+ request.ip == session[:ip] or
207
+ return err("session IP mismatch: " \
208
+ "#{request.ip.inspect} != #{session[:ip].inspect}")
209
+
210
+ trust_root = oidreq.trust_root
211
+ per_site = config[trust_root] or
212
+ return err("trust_root unknown: #{trust_root}")
213
+
214
+ session_id = session[:id] or return err("no session ID")
215
+
216
+ assoc_handle = per_site['assoc_handle'] # this may be nil
217
+ expires = per_site['expires'] or
218
+ return err("no expires (trust_root=#{trust_root})")
219
+
220
+ assoc_handle == oidreq.assoc_handle or
221
+ return err("assoc_handle mismatch: " \
222
+ "#{assoc_handle.inspect} != #{oidreq.assoc_handle.inspect}" \
223
+ " (trust_root=#{trust_root})")
224
+
225
+ per_site['session_id'] == session_id or
226
+ return err("session ID mismatch: " \
227
+ "#{per_site['session_id'].inspect} != #{session_id.inspect}" \
228
+ " (trust_root=#{trust_root})")
229
+
230
+ expires > Time.now or
231
+ return err("Expired: #{expires.inspect} (trust_root=#{trust_root})")
232
+
233
+ true
234
+ end
235
+
236
+ def config
237
+ @config ||= begin
238
+ YAML.load(File.read("#@@dir/config.yml"))
239
+ rescue Errno::ENOENT
240
+ {}
241
+ end
242
+ end
243
+
244
+ def merge_config(oidreq)
245
+ per_site = config[oidreq.trust_root] ||= {}
246
+ per_site.merge!({
247
+ 'assoc_handle' => oidreq.assoc_handle,
248
+ 'expires' => Time.at(0).utc,
249
+ 'updated' => Time.now.utc,
250
+ 'expires1m' => Time.now.utc + 60, # easy edit to "expires" in $EDITOR
251
+ 'session_id' => session[:id],
252
+ })
253
+ end
254
+
255
+ def write_config
256
+ path = "#@@dir/config.yml"
257
+ tmp = Tempfile.new('config.yml', File.dirname(path))
258
+ tmp.syswrite(CONFIG_HEADER.gsub(/^/m, "# "))
259
+ tmp.syswrite(config.to_yaml)
260
+ tmp.syswrite(CONFIG_TRAILER.gsub(/^/m, "# "))
261
+ tmp.fsync
262
+ File.rename(tmp.path, path)
263
+ tmp.close!
264
+ end
265
+
266
+ # this output is designed to be parsed by OpenID consumers
267
+ def render_xrds(force = false)
268
+ if force || request.accept.include?('application/xrds+xml')
269
+
270
+ # this seems to work...
271
+ types = request.accept.include?('application/xrds+xml') ?
272
+ [ OpenID::OPENID_2_0_TYPE,
273
+ OpenID::OPENID_1_0_TYPE,
274
+ OpenID::SREG_URI ] :
275
+ [ OpenID::OPENID_IDP_2_0_TYPE ]
276
+
277
+ headers['Content-Type'] = 'application/xrds+xml'
278
+ types = types.map { |uri| "<Type>#{uri}</Type>" }.join("\n")
279
+ XRDS_XML.gsub(/%s/, server_root).gsub!(/%types/, types)
280
+ else # render a browser-friendly page with an XRDS pointer
281
+ headers['X-XRDS-Location'] = "#{server_root}xrds"
282
+ XRDS_HTML.gsub(/%s/, server_root)
283
+ end
284
+ end
285
+
286
+ # if a single-user OpenID provider like us is being hit by multiple
287
+ # clients at once, then something is seriously wrong. Can't use
288
+ # Mutexes here since somebody could be running this as a CGI script
289
+ def big_lock(&block)
290
+ lock = "#@@dir/lock"
291
+ File.open(lock, File::WRONLY|File::CREAT|File::EXCL, 0600) do |fp|
292
+ begin
293
+ yield
294
+ ensure
295
+ File.unlink(lock)
296
+ end
297
+ end
298
+ rescue Errno::EEXIST
299
+ err("Lock: #{lock} exists! Possible hijacking attempt") rescue nil
300
+ end
301
+ end
302
+ #:startdoc:
@@ -0,0 +1,34 @@
1
+ ENV["VERSION"] or abort "VERSION= must be specified"
2
+ manifest = File.readlines('.manifest').map! { |x| x.chomp! }
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = %q{local-openid}
6
+ s.version = ENV["VERSION"]
7
+
8
+ s.authors = ["Eric Wong"]
9
+ s.date = Time.now.utc.strftime('%Y-%m-%d')
10
+ s.description = File.read("README").split(/\n\n/)[1]
11
+ s.email = %q{local-openid@librelist.com}
12
+ s.executables = %w(local-openid)
13
+
14
+ s.extra_rdoc_files = File.readlines('.document').map! do |x|
15
+ x.chomp!
16
+ if File.directory?(x)
17
+ manifest.grep(%r{\A#{x}/})
18
+ elsif File.file?(x)
19
+ x
20
+ else
21
+ nil
22
+ end
23
+ end.flatten.compact
24
+
25
+ s.files = manifest
26
+ s.homepage = %q{http://bogomips.org/local-openid/}
27
+ s.summary = %q{Single User, Ephemeral OpenID Provider}
28
+ s.rdoc_options = [ "-a", "-t", "local-openid - #{s.summary}" ]
29
+ s.require_paths = %w(lib)
30
+ s.rubyforge_project = %q{qrp}
31
+ s.add_dependency(%q<sinatra>, ["~> 1.0.0"])
32
+ s.add_dependency(%q<ruby-openid>, ["~> 2.1.7"])
33
+ # s.licenses = %w(AGPLv3) # accessor not compatible with older RubyGems
34
+ end
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: local-openid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
5
11
  platform: ruby
6
12
  authors:
7
13
  - Eric Wong
@@ -9,78 +15,107 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2009-04-06 00:00:00 -07:00
18
+ date: 2010-06-26 00:00:00 +00:00
13
19
  default_executable:
14
20
  dependencies:
15
21
  - !ruby/object:Gem::Dependency
16
22
  name: sinatra
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
20
26
  requirements:
21
- - - ">="
27
+ - - ~>
22
28
  - !ruby/object:Gem::Version
23
- version: "0.9"
24
- version:
29
+ hash: 23
30
+ segments:
31
+ - 1
32
+ - 0
33
+ - 0
34
+ version: 1.0.0
35
+ type: :runtime
36
+ version_requirements: *id001
25
37
  - !ruby/object:Gem::Dependency
26
- name: hoe
27
- type: :development
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
38
+ name: ruby-openid
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
30
42
  requirements:
31
- - - ">="
43
+ - - ~>
32
44
  - !ruby/object:Gem::Version
33
- version: 1.11.0
34
- version:
35
- description: local-openid allows users with shell accounts on servers to authenticate with OpenID consumers by editing a YAML file in their home directory instead of authenticating through HTTP/HTTPS. 1. Encounter a login page that accepts OpenID (the consumer) 2. Login into your own server (if you're not already logged in) 3. Start the local-openid app on your server 4. Login using your OpenID (on the consumer) - you should be redirected to your local-openid application 5. edit ~/.local-openid/config.yml on your server to approve the consumer 6. Reload the local-openid page your browser was on. - you should be logged in to the OpenID consumer site - If not, check the error log (usually stderr) of local-openid 8. Shut down the local-openid application.
36
- email:
37
- - normalperson@yhbt.net
45
+ hash: 5
46
+ segments:
47
+ - 2
48
+ - 1
49
+ - 7
50
+ version: 2.1.7
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ description: |-
54
+ local-openid allows users with shell accounts on servers to authenticate
55
+ with OpenID consumers by editing a YAML file in their home directory
56
+ instead of authenticating through HTTP/HTTPS.
57
+ email: local-openid@librelist.com
38
58
  executables:
39
59
  - local-openid
40
60
  extensions: []
41
61
 
42
62
  extra_rdoc_files:
43
- - History.txt
44
- - LICENSE.txt
45
- - Manifest.txt
46
- - README.txt
63
+ - NEWS
64
+ - LICENSE
65
+ - ChangeLog
66
+ - README
47
67
  files:
48
68
  - .document
49
69
  - .gitignore
70
+ - .manifest
71
+ - COPYING
72
+ - ChangeLog
73
+ - GIT-VERSION-FILE
74
+ - GIT-VERSION-GEN
50
75
  - GNUmakefile
51
- - History.txt
52
- - LICENSE.txt
53
- - Manifest.txt
54
- - README.txt
76
+ - LICENSE
77
+ - NEWS
78
+ - README
55
79
  - Rakefile
56
80
  - bin/local-openid
81
+ - lib/local_openid.rb
82
+ - local-openid.gemspec
57
83
  - setup.rb
58
84
  has_rdoc: true
59
- homepage: http://bogomips.org/local-openid
85
+ homepage: http://bogomips.org/local-openid/
86
+ licenses: []
87
+
60
88
  post_install_message:
61
89
  rdoc_options:
62
- - --main
63
- - README.txt
90
+ - -a
91
+ - -t
92
+ - local-openid - Single User, Ephemeral OpenID Provider
64
93
  require_paths:
65
94
  - lib
66
95
  required_ruby_version: !ruby/object:Gem::Requirement
96
+ none: false
67
97
  requirements:
68
98
  - - ">="
69
99
  - !ruby/object:Gem::Version
100
+ hash: 3
101
+ segments:
102
+ - 0
70
103
  version: "0"
71
- version:
72
104
  required_rubygems_version: !ruby/object:Gem::Requirement
105
+ none: false
73
106
  requirements:
74
107
  - - ">="
75
108
  - !ruby/object:Gem::Version
109
+ hash: 3
110
+ segments:
111
+ - 0
76
112
  version: "0"
77
- version:
78
113
  requirements: []
79
114
 
80
115
  rubyforge_project: qrp
81
- rubygems_version: 1.3.1
116
+ rubygems_version: 1.3.7
82
117
  signing_key:
83
- specification_version: 2
118
+ specification_version: 3
84
119
  summary: Single User, Ephemeral OpenID Provider
85
120
  test_files: []
86
121
 
@@ -1,7 +0,0 @@
1
- === 0.1.1 / 2009-04-06
2
-
3
- * add Sinatra dependency
4
-
5
- === 0.1.0 / 2009-04-04
6
-
7
- * initial
@@ -1,10 +0,0 @@
1
- .document
2
- .gitignore
3
- GNUmakefile
4
- History.txt
5
- LICENSE.txt
6
- Manifest.txt
7
- README.txt
8
- Rakefile
9
- bin/local-openid
10
- setup.rb