Skip to content

Commit

Permalink
resolved merge conflict
Browse files Browse the repository at this point in the history
  • Loading branch information
atruskie committed Dec 6, 2012
2 parents 973e744 + 24173f7 commit 1775db4
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 87 deletions.
199 changes: 114 additions & 85 deletions app/controllers/api/callbacks_controller.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
class Api::CallbacksController < Devise::OmniauthCallbacksController
# see https://gist.github.com/993566
# this may be needed, but haven't needed it yet.
#skip_before_filter :verify_authenticity_token, :only => [:open_id]

# NOTES

# https://github.com/intridea/omniauth/wiki/Managing-Multiple-Providers
# Typically authentication systems have a User model which handles most of the
Expand All @@ -8,14 +11,55 @@ class Api::CallbacksController < Devise::OmniauthCallbacksController
# method which a user has used to identify themselves with your site whilst a User
# manages data which is directly related to your site itself.

#respond_to :json
# good info about the omniauth flow
# http://www.arailsdemo.com/posts/18

# see https://gist.github.com/993566

# END NOTES

# any failure
def failure
#set_flash_message :alert, :failure, :kind => failed_strategy.name.to_s.humanize, :reason => failure_message
#redirect_to after_omniauth_failure_path_for(resource_name)

#render :json => {:response => 'failure', :provider_id => failed_strategy.name.to_s, :reason => failure_message}.to_json, :status => :bad_request

window_data = {:response => 'failure', :provider_id => failed_strategy.name.to_s, :reason => failure_message}
javascript_data = "<script type='text/javascript'>(function(){ returneddata = #{window_data.to_json}; window.close(); return false;})()</script>"
displayed_data = '<p>Authentication callback page. If you are seeing this page, something went wrong. <a href="/">Return to homepage</a>.</p>'
window_content = "<!DOCTYPE html><head></head><body>#{displayed_data} #{javascript_data}</body></html>"

# use this javscript to get access to the returned data
# returneddata = 0; dataitem = window.open('/security/auth/open_id/callback', 'dataitem'); dataitem.returneddata = returneddata;
# to access the object: dataitem.returneddata
render :text => window_content, :status => :bad_request
end

def success_complete(canonical_data)
user = store_provider_info(canonical_data, current_user)

sign_in(user, :event => :authentication)

current_user.reset_authentication_token!
content = Api::SessionsController.login_info(current_user, user, canonical_data[:canonical][:provider])

respond_to do |format|
format.json { render :json => content.as_json, :status => :ok }
format.xml { render :xml => content.to_xml, :status => :ok }
format.any { render :json => content.as_json, :status => :ok }
end
end

#
# External providers
#

def browser_id
# https://developer.mozilla.org/en-US/docs/Persona/Remote_Verification_API
# this callback will have an assertion included. The assertion should be POST'ed with the
# audience to the remote verification API


if params[:assertion].blank?

head :bad_request
Expand All @@ -31,17 +75,9 @@ def browser_id
if verify_response.code == '200'
verify_response_attr = JSON.parse(verify_response.body, { :symbolize_names => true })
if verify_response_attr[:status] == 'okay'
user = store_provider_info('browser_id',verify_response_attr, current_user)
canonical_data = browser_id_info(verify_response_attr)

sign_in(user, :event => :authentication)
current_user.reset_authentication_token!

respond_to do |format|
format.json do
content = Api::SessionsController.login_info(current_user, user, 'browser_id')
render :json => content.to_json, :status => :ok
end
end
success_complete(canonical_data)

end
end
Expand All @@ -55,77 +91,85 @@ def browser_id
end
end

def open_id
canonical_data = open_id_info(request.env["omniauth.auth"])
success_complete(canonical_data)
end

private

def store_provider_info(provider, access_token, resource=nil)
user = nil
email = nil
display_name = nil
uid = nil
auth_attr = {}
def browser_id_info(raw)
{
:canonical =>
{
:provider => 'browser_id',
:uid => raw[:email],
#:user_id =>,
:token => raw[:issuer], # stores issuer instead
:secret => raw[:expires], # stores expirses instead
:name => nil,
:link => 'https://persona.org' # link to external provider profile when logged in
},
:email => raw[:email],
:display_name => nil
}
end

case provider
when 'browser_id'
uid = access_token[:email]
email = access_token[:email]
# using the token field to store the issuer identity
# using the secret field to store the expires time
auth_attr = { :uid => uid, :token => access_token[:issuer],
:secret => access_token[:expires], :link => 'https://persona.org' }
def open_id_info(raw)
{
:canonical =>
{
:provider => 'open_id',
:uid => raw.uid,
#:user_id =>,
:token => raw.extra.response.endpoint.local_id, # stores open id issuer/server instead
:secret => nil,
:name => if raw.info.include?(:name) then
raw.info.name
elsif raw.info.include?(:nickname) then
raw.info.nickname
else
nil
end,
:link => raw.extra.response.identity_url
},
:email => raw.info.include?(:email) ? raw.info.email : '',
:display_name => raw.info.include?(:nickname) ? raw.info.nickname : nil,
}
end

else
raise "Provider '#{provider}' not handled."
end
def store_provider_info(canonical_data,resource=nil)
user = resource

if resource.nil?
if email
user = find_or_create_by_name(display_name, email, resource)
elsif uid && name
user = find_or_create_by_uid(uid, display_name, email, resource)
if user.nil?
user = find_or_create_by_display_name(display_name, email, resource)
end
end
else
user = resource
if user.blank?
authn = Authorization.find_by_uid(canonical_data[:canonical][:uid])
user = authn.user unless authn.blank?
user = User.find_by_email(canonical_data[:email]) if !canonical_data[:email].blank? && user.blank?
user = User.find_by_display_name(canonical_data[:display_name]) if !canonical_data[:display_name].blank? && user.blank?
user = User.create!(:display_name => canonical_data[:display_name], :email => canonical_data[:email], :password => Devise.friendly_token[0,20]) if user.blank?
end

auth = user.authorizations.find_by_provider(provider)
if auth.nil?
auth = user.authorizations.build(:provider => provider)
user.authorizations << auth
# update display_name if given and it was blank
if user.display_name.blank? && !canonical_data[:display_name].blank?
user.display_name = canonical_data[:display_name]
end

auth.update_attributes auth_attr
# update email is given and it was blank
if user.email.blank? && !canonical_data[:email].blank?
user.email = canonical_data[:email]
end

user
end
raise 'Could not find or create a user for external provider information' if user.blank?

def find_or_create_by_uid(uid, display_name, email, resource=nil)
user = Authorization.find_by_uid(uid.to_s)
if user.blank?
user = User.new(:display_name => display_name, :email => email, :password => Devise.friendly_token[0,20])
user.save
auth = user.authorizations.find_by_provider(canonical_data[:canonical][:provider])
if auth.nil?
auth = user.authorizations.build(:provider => canonical_data[:canonical][:provider])
user.authorizations.push(auth)
end
user
end

def find_or_create_by_display_name(display_name, email, resource=nil)
user = User.find_by_email(email)
if user.blank?
user = User.new(:display_name => display_name, :email => email, :password => Devise.friendly_token[0,20])
user.save
end
user
end
# update all auth attributes. This will remove info if it is not provided in canonical_data[:canonical].
auth.update_attributes canonical_data[:canonical]

def find_or_create_by_name(display_name, email, resource=nil)
user = User.find_by_display_name(display_name)
if user.blank?
user = User.new(:display_name => display_name, :email => email, :password => Devise.friendly_token[0,20], )
# save(false) will skip validations
user.save(:validate => false)
end
user
end

Expand All @@ -137,21 +181,6 @@ def construct_post(endpoint_uri, body)
post_request
end

def construct_browser_id_attrs(response_body)

end

def find_or_create_user_by_email(email, display_name)
user = User.find_by_email(email)
if user
user
else
user = User.new(:display_name => display_name, :email => email, :password => Devise.friendly_token[0,20])
user.save
end
user
end

=begin
require 'uuidtools'
Expand Down
1 change: 1 addition & 0 deletions app/controllers/api/registrations_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
class Api::RegistrationsController < Devise::RegistrationsController
respond_to :json
# see C:\Ruby\193\lib\ruby\gems\1.9.1\gems\devise-2.1.2\app\controllers\devise
# Not Used - disabled

# GET /resource/sign_up
def new
Expand Down
23 changes: 22 additions & 1 deletion app/controllers/api/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,25 @@ def create

end

# DELETE (or GET depending on devise setting) /resource/sign_out
def destroy
# don't redirect at all
#redirect_path = after_sign_out_path_for(resource_name)
# still sign out
signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
#set_flash_message :notice, :signed_out if signed_out

# We actually need to hardcode this as Rails default responder doesn't
# support returning empty response on GET request
# only respond with a HEAD 200 OK.
respond_to do |format|
#format.any(*navigational_formats) { redirect_to redirect_path }
format.all do
head :ok
end
end
end

# returns 401 or 200 depending on if a user is signed in or not
def ping
if user_signed_in?
Expand All @@ -51,9 +70,11 @@ def ping

def self.login_info(current_user, user, provider_id)
{ :response => 'ok',
:user_id => user.id,
:auth_token => current_user.authentication_token,
:friendly_name => user.display_name,
:provider_id => provider_id
:provider_id => provider_id,
:email => user.email
}
end

Expand Down
3 changes: 2 additions & 1 deletion app/models/user.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
class User < ActiveRecord::Base
# Include devise modules.
devise :confirmable, :omniauthable, :registerable,
# :registerable,
devise :confirmable, :omniauthable,
:recoverable, :rememberable, :token_authenticatable,
:trackable, :database_authenticatable, :lockable,
:validatable, :timeoutable
Expand Down

0 comments on commit 1775db4

Please sign in to comment.