Moderne Applikationen erlauben es ihren Benutzern über Single sign-on Dienste zu authentisieren.
In diesem Guide erkläre ich wie man mit Ruby on Rails eine Applikation erstellt die Multi-Provider Authentisierung über OAuth und OpenID Dienste wie die von Google, Facebook oder Twitter erlaubt.
Ich verwende dafür die Plugins Devise und OmniAuth.
Devise
Devise ist ein Authentisierungs-Plugin für Rails. In diesem Guide verwende ich es für
- Benutzerkonten Verwaltung
- Session Verwaltung
- Als Schnittstelle zu OmniAuth
Ich definiere den devise gem in meinem Gemfile.
gem 'devise'
und installiere ihn mit bundler
bundle install
Danach führe ich den Generator aus um den Initializer zu erstellen.
rails generate devise:install
Den Initializer kann ich nun anschauen und bei Bedarf editieren:
vi config/initializers/devise.rb
Als nächstes füge ich devise dem User Model an (falls das Model noch nicht existiert wird es angelegt)
rails generate devise User
Damit wird auch ein migration File erstellt in welchem Helper Methoden für erweiterte Funktion von devise auskommentiert werden können.
create_table(:users) do |t| t.database_authenticatable :null => false t.recoverable t.rememberable t.trackable # t.encryptable # t.confirmable # t.lockable :lock_strategy => :failed_attempts, :unlock_strategy => :both # t.token_authenticatable t.timestamps end
Für eine ausführliche Beschreibung der Optionen siehe: https://github.com/plataformatec/devise
Ich belasse die migration hier so wie sie generiert wurde und wende sie auf die Datenbank an.
rake db:migrate
OmniAuth
OmniAuth ist ein universell einsetzbarer Rubygem mit dem sich Multiprovider-Authentisierung realisieren lässt.
Erneut erweitere ich mein Gemfile. Diesmal um folgende Zeilen.
gem 'omniauth', :require => "omniauth/oauth" gem 'oa-openid', :require => 'omniauth/openid'
Und führe erneut bundler aus.
bundle install
Facebook (OAuth)
Ich will meinen Benutzern die Möglichkeit geben sich mit ihrem Facebook Account an meiner Applikation zu authentisieren. Dazu muss ich zuerst meine Applikation bei Facebook registrieren um eine App ID zu erhalten.
Danach konfiguriere ich diese in config/initializers/devise.rb
config.omniauth :facebook, "APP_ID", "APP_SECRET"
Danach muss ich dem Model (in unserem Fall User) noch sagen, dass es über omniauth authentisierbar ist.
devise :omniauthable
Zudem braucht mein Model noch eine Funktion die definiert was beim Facebook login geschehen soll.
In diesem Beispiel wird anhand der von Facebook erhaltenen E-Mail Adresse ein bestehender Benutzer gesucht. Falls keiner existiert wird ein neuer Angelegt.
def self.find_for_facebook_oauth(access_token, signed_in_resource=nil) data = access_token['extra']['user_hash'] if user = User.find_by_email(data["email"]) user else User.create!(:email => data["email"], :password => Devise.friendly_token[0,20]) end end
Jetzt muss meine Applikation nur noch die Callbacks verarbeiten können. Dazu ändere ich die devise_for Konfiguration in config/routes.rb zu:
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
und erstelle den Callback Controller
# app/controllers/users/omniauth_callbacks_controller.rb class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController def facebook @user = User.find_for_facebook_oauth(env["omniauth.auth"], current_user) if @user.persisted? flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Facebook" sign_in_and_redirect @user, :event => :authentication else session["devise.facebook_data"] = env["omniauth.auth"] redirect_to new_user_registration_url end end end
vereine.ch
Ein Beispiel für die produktive Anwendung ist die von mir geschriebene Vereine Plattform vereine.ch
Diese erlaubt Login über konventionellen E-Mail Sign-Up, den Facebook OAuth Dienst und Google OpenID.