about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorLionel Elie Mamane <lionel@mamane.lu>2012-06-25 03:54:34 +0000
committerEric Wong <normalperson@yhbt.net>2012-06-25 03:54:34 +0000
commit1ace6029b574443965ef6b2fc872f6517b430e20 (patch)
treec6c17ae994e2b4c09997c6fc39a9117fb461087a
parent836a4116373a69f6dbe9e909780403c5971fa390 (diff)
downloadlocal-openid-1ace6029b574443965ef6b2fc872f6517b430e20.tar.gz
separate OpenID Provider identifier and user identifier to be distinct
As per OpenID Authentication 2.0 specification section 11.2, the two
are not allowed to be equal.

The user identifier is unchanged: http://${HOST}/
The provider identifier (and provider endpoint URL) is now
http://${HOST}/provider

Signed-off-by: Eric Wong <normalperson@yhbt.net>
-rw-r--r--lib/local_openid.rb85
1 files changed, 62 insertions, 23 deletions
diff --git a/lib/local_openid.rb b/lib/local_openid.rb
index 3d87d5f..ab342a9 100644
--- a/lib/local_openid.rb
+++ b/lib/local_openid.rb
@@ -23,9 +23,12 @@ class LocalOpenID < Sinatra::Base
   Dir.mkdir(@@dir) unless File.directory?(@@dir)
 
   # all the sinatra endpoints:
-  get('/xrds') { big_lock { render_xrds(true) } }
-  get('/') { big_lock { get_or_post } }
-  post('/') { big_lock { get_or_post } }
+  get('/xrds') { big_lock { render_identity_xrds(true) } }
+  get('/provider/xrds') { big_lock { render_provider_xrds(true) } }
+  get('/provider') { big_lock { get_or_post_provider } }
+  post('/provider') { big_lock { get_or_post_provider } }
+  get('/') { big_lock { render_identity_xrds } }
+  post('/') { big_lock { render_identity_xrds } }
 
   private
 
@@ -35,21 +38,44 @@ class LocalOpenID < Sinatra::Base
   <body><h1>reload this page when approved: %s</h1></body>
   </html>!
 
-  XRDS_HTML = %q!<html><head>
-  <link rel="openid.server" href="%s" />
-  <link rel="openid2.provider" href="%s" />
-  <meta http-equiv="X-XRDS-Location" content="%sxrds" />
+  PROVIDER_XRDS_HTML = %q!<html><head>
+  <meta http-equiv="X-XRDS-Location" content="%sprovider/xrds" />
   <title>OpenID server endpoint</title>
   </head><body>OpenID server endpoint</body></html>!
 
-  XRDS_XML = %q!<?xml version="1.0" encoding="UTF-8"?>
+  IDENTITY_XRDS_HTML = %q!<html><head>
+  <link rel="openid.server" href="%sprovider" />
+  <link rel="openid2.provider" href="%sprovider" />
+  <link rel="openid2.local_id" href="%s" />
+  <link rel="openid.delegate"  href="%s" />
+  <meta http-equiv="X-XRDS-Location" content="%sxrds" />
+  <title>OpenID identity</title>
+  </head><body>OpenID identity</body></html>!
+
+  PROVIDER_XRDS_XML = %q!<?xml version="1.0" encoding="UTF-8"?>
+  <xrds:XRDS
+    xmlns:xrds="xri://$xrds"
+    xmlns:openid="http://openid.net/xmlns/1.0"
+    xmlns="xri://$xrd*($v*2.0)">
+  <XRD version="2.0">
+    <Service priority="0">
+      %types
+      <URI>%sprovider</URI>
+    </Service>
+  </XRD>
+  </xrds:XRDS>!
+
+  IDENTITY_XRDS_XML = %q!<?xml version="1.0" encoding="UTF-8"?>
   <xrds:XRDS
     xmlns:xrds="xri://$xrds"
+    xmlns:openid="http://openid.net/xmlns/1.0"
     xmlns="xri://$xrd*($v*2.0)">
-  <XRD>
+  <XRD version="2.0">
     <Service priority="0">
       %types
-      <URI>%s</URI>
+      <URI>%sprovider</URI>
+      <LocalID>%s</LocalID>
+      <openid:Delegate>%s</openid:Delegate>
     </Service>
   </XRD>
   </xrds:XRDS>!
@@ -81,7 +107,7 @@ class LocalOpenID < Sinatra::Base
     - updated       Time this entry was updated, strictly informational.
     - session_id    Unique identifier in your session cookie to prevent
                     other users from hijacking your session.  You may
-                    delete this if you've changed browsers or computers.
+                    delete this if you have changed browsers or computers.
     - assoc_handle  See the OpenID specs, may be empty.  Do not edit this.
 
   SReg keys supported by the Ruby OpenID implementation should be
@@ -97,14 +123,14 @@ class LocalOpenID < Sinatra::Base
 
   # this is the heart of our provider logic, adapted from the
   # Ruby OpenID gem Rails example
-  def get_or_post
+  def get_or_post_provider
     oidreq = begin
       server.decode_request(params)
     rescue ProtocolError => err
       halt(500, err.to_s)
     end
 
-    oidreq or return render_xrds
+    oidreq or return render_provider_xrds
 
     oidresp = case oidreq
     when CheckIDRequest
@@ -116,7 +142,7 @@ class LocalOpenID < Sinatra::Base
         add_pape(oidreq, resp)
         resp
       elsif oidreq.immediate
-        oidreq.answer(false, server_root)
+        oidreq.answer(false, server_root + "provider")
       else
         session[:id] ||= "#{Time.now.to_i}.#$$.#{rand}"
         session[:ip] = request.ip
@@ -144,7 +170,7 @@ class LocalOpenID < Sinatra::Base
   def server
     @server ||= Server.new(
         OpenID::Store::Filesystem.new("#@@dir/store"),
-        server_root)
+        server_root + "provider")
   end
 
   # support the simple registration extension if possible,
@@ -264,22 +290,35 @@ class LocalOpenID < Sinatra::Base
   end
 
   # this output is designed to be parsed by OpenID consumers
-  def render_xrds(force = false)
+  def render_provider_xrds(force = false)
+    if force || request.accept.include?('application/xrds+xml')
+
+      # this seems to work...
+      types = [ OpenID::OPENID_IDP_2_0_TYPE ]
+
+      headers['Content-Type'] = 'application/xrds+xml'
+      types = types.map { |uri| "<Type>#{uri}</Type>" }.join("\n")
+      PROVIDER_XRDS_XML.gsub(/%s/, server_root).gsub!(/%types/, types)
+    else # render a browser-friendly page with an XRDS pointer
+      headers['X-XRDS-Location'] = "#{server_root}provider/xrds"
+      PROVIDER_XRDS_HTML.gsub(/%s/, server_root)
+    end
+  end
+
+  def render_identity_xrds(force = false)
     if force || request.accept.include?('application/xrds+xml')
 
       # this seems to work...
-      types = request.accept.include?('application/xrds+xml') ?
-         [ OpenID::OPENID_2_0_TYPE,
-           OpenID::OPENID_1_0_TYPE,
-           OpenID::SREG_URI ] :
-         [ OpenID::OPENID_IDP_2_0_TYPE ]
+      types = [ OpenID::OPENID_2_0_TYPE,
+                OpenID::OPENID_1_0_TYPE,
+                OpenID::SREG_URI ]
 
       headers['Content-Type'] = 'application/xrds+xml'
       types = types.map { |uri| "<Type>#{uri}</Type>" }.join("\n")
-      XRDS_XML.gsub(/%s/, server_root).gsub!(/%types/, types)
+      IDENTITY_XRDS_XML.gsub(/%s/, server_root).gsub!(/%types/, types)
     else # render a browser-friendly page with an XRDS pointer
       headers['X-XRDS-Location'] = "#{server_root}xrds"
-      XRDS_HTML.gsub(/%s/, server_root)
+      IDENTITY_XRDS_HTML.gsub(/%s/, server_root)
     end
   end