separate OpenID Provider identifier and user identifier to be distinct
authorLionel Elie Mamane <lionel@mamane.lu>
Mon, 25 Jun 2012 03:54:34 +0000 (25 03:54 +0000)
committerEric Wong <normalperson@yhbt.net>
Mon, 25 Jun 2012 03:54:34 +0000 (25 03:54 +0000)
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>
lib/local_openid.rb

index 3d87d5f..ab342a9 100644 (file)
@@ -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