local-openid 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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