# Referenzimplementierung für die nachträgliche Integration der OpenID-Unterstützung in eine
# Relying Party anwendung
#
# Dieses Beispiel beruht auf dem Einsatz von Ruby on Rails ab Version 1.2 und folgenden Ruby Gems:
# * ruby-openid (Version 2.0.4, http://www.openidenabled.com/ruby-openid/)
# * ruby-yadis (Version 0.3.4)
#
# Neben der folgenden Implementierung eines Controllers, welcher die Möglichkeit bietet, ein bestehendes
# Benutzerkonto mit einer OpenID zu verknüpfen und diese Verknüpfung auch wieder aufzuheben, müssen noch
# weitere Teile dem Projekt hinzugefügt werden.
#
# Folgende Routes müssen in der Datei config/routes.rb ergänzt werden:
#
# map.with_options :controller => 'users' do |users|
# users.add_openid 'users/add_openid', :action => 'add_openid'
# users.associate_openid 'users/associate_openid', :action => 'associate_openid'
# users.remove_openid 'users/remove_openid', :action => 'remove_openid'
# end
#
# Folgende Migration muss ergänzt werden, um dem Benutzerpofil die Identity URL hinzuzufügen:
#
# class AddIdentityUrlToUsers < ActiveRecord::Migration
# def self.up
# add_column :users, :identity_url, :string
# end
#
# def self.down
# remove_column :users, :identity_url
# end
# end
#
# Mittels des folgenden Formulars kann der Benutzer beim Bearbeiten des Profils den Identifier angeben:
#
#
Ihre OpenID
# <% if @user.identity_url.blank? %>
# Ihr Benutzerkonto ist bisher mit keiner OpenID verbunden. Wenn Sie sich für die Anwendung zukünftig
# mit ihrer OpenID anmelden wollen, dann klicken Sie den Button und bestätigen Sie die Anfrage.
# <% form_for :user, :url => { :action => 'add_openid' } do |f| %>
# <%= image_submit_tag 'https://openid.tzi.de/images/login_button.png' %>
# <% end %>
# <% else %>
# Ihr Benutzerkonto ist mit aktuell mit folgender OpenID verbunden:
<%=h @user.identity_url %>
# Wenn Sie diese Verbindung entfernen, ist es nicht mehr möglich,
sich per OpenID einzuloggen.
# <% form_for :user, :url => { :action => 'remove_openid' }, :html => { :method => :put } do |f| %>
# <%= submit_tag 'Verbindung mit dieser OpenID entfernen' %>
# <% end %>
#
# Das Formular enthält lediglich den Login-Buttons des OpenID-Servers vom Fachbereich 3 und startet
# beim Abschicken den Verknüpfungsvorgang in der add_openid-Action des folgenden UsersControllers.
#
# ------------------------------------------------------------------------------------------------------------
require 'openid' # Einbinden der benötigten Bibliotheken aus den Gems
require 'openid/store/filesystem' # Store fürs Speichern der OpenID-Transaktionsdaten
require 'openid/consumer/discovery' # Yadis Discovery Funktionalitäten
class UsersController < ApplicationController
# Startet den Vorgang zum Hinzufügen einer OpenID
def add_openid
begin
oidreq = openid_consumer.begin(identity_provider)
rescue OpenID::OpenIDError => e
flash[:error] = "Der OpenID-Server #{identity_provider} konnte nicht kontaktiert werden.
#{e}"
redirect_to :action => 'edit'
return
end
redirect_to oidreq.redirect_url(home_url, url_for(:action => 'associate_openid'))
end
# Verknüpft ein Benutzerkonto mit einer OpenID
def associate_openid
parameters = params.reject{ |k,v| request.path_parameters[k] }
oidresp = openid_consumer.complete(parameters, url_for({}))
if oidresp && oidresp.endpoint && oidresp.endpoint.server_url.match(identity_provider)
if oidresp.status == OpenID::Consumer::SUCCESS
current_user.update_attribute(:identity_url, oidresp.display_identifier)
flash[:notice] = "Ihr Benutzerkontos wurde mit der OpenID #{oidresp.display_identifier} verbunden."
else
flash[:error] = "Die Verknüpfung mit der OpenID ist fehlgeschlagen."
end
else
flash[:error] = "Es werden nur OpenIDs von #{identity_provider} akzeptiert."
end
redirect_to :action => 'edit'
end
# Entfernt die Verknüpfung des Benutzerkontos mit einer OpenID
def remove_openid
current_user.update_attribute(:identity_url, nil)
flash[:notice] = "Die Verknüpfung Ihres Benutzerkontos mit der OpenID wurde aufgehoben."
redirect_to :action => 'edit'
end
private
# Die Daten der OpenID-Transaktionen werden in diesem Fall im Dateisystem abgelegt.
# Sollte dies nicht erwünscht sein, kann auch ein anderer Store-Mechanismus angegeben
# werden - näheres dazu findet sich in der Dokumentation des ruby-openid Gems unter:
# http://www.openidenabled.com/ruby-openid/
def openid_consumer
store = OpenID::Store::Filesystem.new("#{RAILS_ROOT}/tmp/openid")
@openid_consumer ||= OpenID::Consumer.new(session, store)
end
# Die URL des Identity Providers - in diesem Fall die URL
# des OpenID-Servers des Fachbereich 3 der Uni Bremen
def identity_provider
'https://openid.tzi.de/'
end
end