Distributed Identity via OpenID

Post on 19-Jan-2015

1,788 views 3 download

Tags:

description

Chances are, if you've been paying attention to the internet lately, you've probably heard about Federated and Distributed Identity. OpenID is one attempt to implement a federated approach to our already distributed identities across the internet. In this presentation, originally given at the Orlando Ruby User Group in December 2008, we explore what "federation" means, why you should use it, and how you could implement OpenID support in a Ruby app. Impressive from a PHP guy, huh?

transcript

OPENID AND THE CASE OF

DISTRIBUTED IDENTITYEXPLORING THE PROBLEM OF DISTRIBUTED IDENTITY AND

OFFERING SOME SOLUTIONS

1

WHAT ARE WE TALKING ABOUT?

DIGITAL IDENTITY REFERS TO THE ASPECT O F D I G I T A L T E C H N O L O G Y T H A T I S CONCERNED WITH THE MEDIATION OF PEOPLE'S EXPERIENCE OF THEIR OWN IDENTITY AND THE IDENTITY OF OTHER PEOPLE AND THINGS.

“DIGITAL IDENTITY” ALSO HAS ANOTHER C O M M O N U S A G E A S T H E D I G I T A L REPRESENTATION OF A SET OF CLAIMS MADE BY ONE DIGITAL SUBJECT ABOUT ITSELF OR ANOTHER DIGITAL SUBJECT.

IDENTITY === AUTHENTICATION ?

IDENTITY == AUTHENTICATION

2

STANDARD AUTHENTICATION

3

STANDARD AUTHENTICATION

A “USER” AGENT REQUESTS A “PAGE” RESOURCE

4

STANDARD AUTHENTICATION

A “USER” AGENT REQUESTS A “PAGE” RESOURCE

IS THE RESOURCE REQUESTED PUBLIC?

4

STANDARD AUTHENTICATION

A “USER” AGENT REQUESTS A “PAGE” RESOURCE

IS THE RESOURCE REQUESTED PUBLIC?

IF NOT, IS THE REQUESTING AGENT AUTHENTICATED?

4

STANDARD AUTHENTICATION

A “USER” AGENT REQUESTS A “PAGE” RESOURCE

IS THE RESOURCE REQUESTED PUBLIC?

IF NOT, IS THE REQUESTING AGENT AUTHENTICATED?

IF NOT, IS THE REQUESTING AGENT REGISTERED?

4

STANDARD AUTHENTICATION

IF “USER” IS REGISTERED

BUT NOT AUTHENTICATED,

THEN PRESENT THE

“LOGIN” FORM...

5

STANDARD AUTHENTICATION

IF “USER” IS REGISTERED

BUT NOT AUTHENTICATED,

THEN PRESENT THE

“LOGIN” FORM...

IF “USER” IS NEITHER

AUTHENTICATED NOR

REGISTERED, THEN

PRESENT THE

“REGISTRATION” FORM...

5

STANDARD AUTHENTICATION

IF “USER” IS REGISTERED

BUT NOT AUTHENTICATED,

THEN PRESENT THE

“LOGIN” FORM...

IF “USER” IS NEITHER

AUTHENTICATED NOR

REGISTERED, THEN

PRESENT THE

“REGISTRATION” FORM...

SIMILAR PROCESSING;

SUCCESS RETURNS TO THE

ORIGINAL REQUEST.

5

STANDARD AUTHENTICATION

INPUT FILTERING TO

COMBAT SCRIPT

INJECTION

6

STANDARD AUTHENTICATION

INPUT FILTERING TO

COMBAT SCRIPT

INJECTION

UNIQUENESS OF LOCAL

IDENTITY

6

STANDARD AUTHENTICATION

INPUT FILTERING TO

COMBAT SCRIPT

INJECTION

UNIQUENESS OF LOCAL

IDENTITY

CREDENTIAL SECURITY

PASSWORD

STRENGTH

6

STANDARD AUTHENTICATION

INPUT FILTERING TO

COMBAT SCRIPT

INJECTION

UNIQUENESS OF LOCAL

IDENTITY

CREDENTIAL SECURITY

PASSWORD

STRENGTH

DATA STORE

6

STANDARD AUTHENTICATION

INPUT FILTERING TO

COMBAT SCRIPT

INJECTION

UNIQUENESS OF LOCAL

IDENTITY

CREDENTIAL SECURITY

PASSWORD

STRENGTH

DATA STORE

HEADACHE

S!!!

6

STANDARD AUTHENTICATION

INPUT FILTERING TO

COMBAT SCRIPT

INJECTION

UNIQUENESS OF LOCAL

IDENTITY

CREDENTIAL SECURITY

PASSWORD

STRENGTH

DATA STORE

HEADACHE

S!!!

REPETITION!!!

6

STANDARD AUTHENTICATION

INPUT FILTERING TO

COMBAT SCRIPT

INJECTION

UNIQUENESS OF LOCAL

IDENTITY

CREDENTIAL SECURITY

PASSWORD

STRENGTH

DATA STORE

HEADACHE

S!!!

REPETITION!!!

FAIL!!!6

IDENTITY FEDERATIONWHY CAN’T SOMEBODY ELSE DO ALL THIS FOR ME?

INTRODUCING!

NOT NEW BUT

IMPROVED!

7

FEDERATED IDENTITY

HOW THIS IS SUPPOSED TO WORK...

8

FEDERATED IDENTITY

HOW THIS IS SUPPOSED TO WORK...

8

FEDERATION VIA OPENID

9

THAT SEEMS EASY...

EVEN EASIER WITH EXISTING LIBRARIES:

ZEND_OPENID FOR PHP5

RUBY-OPENID FOR RUBY

NET::OPENID FOR PERL

MOD_AUTH_OPENID FOR APACHE2

OPENID4JAVA FOR JAVA

CHECK THE OPENID.NET WIKI FOR MORE...!

10

def openid_consumer if @openid_consumer.blank? @openid_consumer = OpenID::Consumer.new(session, OpenID::Store::Filesystem.new("#{RAILS_ROOT}/tmp/openid")) end

return @openid_consumerend

def create # Get the OpenID parameter openid_url = params[:openid_url]

# Make sure we got something if openid_url.blank? flash[:error] = "No OpenID was entered; try again" redirect_to :back return end

# Get an OpenID response openid_response = openid_consumer.begin openid_url

home_url = url_for :controller => "openid", :action => "index" complete_url = url_for :controller => "openid", :action => "complete" openid_redirect_url = openid_response.redirect_url(home_url, complete_url) redirect_to openid_redirect_url

returnend

LET’S TRY IT OUT!

$> gem install ruby-openid$> script/generate controller openid new create complete openid_consumerviews/openid/new.html.erb:<html> <head> <title>Log in with OpenID</title> </head> <body> <% if not flash[:error].blank? %> <p><b><%= flash[:error] -%></b></p> <% end %>

<% form_tag "/openid/create" do %> <%= text_field_tag "openid_url" %> <%= submit_tag "Log in with OpenID" %> <% end %> </body></html>

{ }

def complete home_url = url_for :controller => "openid", :action => "index" complete_url = url_for :controller => "openid", :action => "complete"

openid_response = openid_consumer.complete(params, complete_url)

session[:openid] = openid_response.identity_url flash[:error] = "You have been logged in as '#{session[:openid]}'" redirect_to :action => "new" returnend

HTTP://WWW.LINUXJOURNAL.COM/ARTICLE/10104

11

def openid_consumer if @openid_consumer.blank? @openid_consumer = OpenID::Consumer.new(session, OpenID::Store::Filesystem.new("#{RAILS_ROOT}/tmp/openid")) end

return @openid_consumerend

def create # Get the OpenID parameter openid_url = params[:openid_url]

# Make sure we got something if openid_url.blank? flash[:error] = "No OpenID was entered; try again" redirect_to :back return end

# Get an OpenID response openid_response = openid_consumer.begin openid_url

home_url = url_for :controller => "openid", :action => "index" complete_url = url_for :controller => "openid", :action => "complete" openid_redirect_url = openid_response.redirect_url(home_url, complete_url) redirect_to openid_redirect_url

returnend

LET’S TRY IT OUT!

$> gem install ruby-openid$> script/generate controller openid new create complete openid_consumerviews/openid/new.html.erb:<html> <head> <title>Log in with OpenID</title> </head> <body> <% if not flash[:error].blank? %> <p><b><%= flash[:error] -%></b></p> <% end %>

<% form_tag "/openid/create" do %> <%= text_field_tag "openid_url" %> <%= submit_tag "Log in with OpenID" %> <% end %> </body></html>

{ }

def complete home_url = url_for :controller => "openid", :action => "index" complete_url = url_for :controller => "openid", :action => "complete"

openid_response = openid_consumer.complete(params, complete_url)

session[:openid] = openid_response.identity_url flash[:error] = "You have been logged in as '#{session[:openid]}'" redirect_to :action => "new" returnend

HTTP://WWW.LINUXJOURNAL.COM/ARTICLE/10104

11

def openid_consumer if @openid_consumer.blank? @openid_consumer = OpenID::Consumer.new(session, OpenID::Store::Filesystem.new("#{RAILS_ROOT}/tmp/openid")) end

return @openid_consumerend

def create # Get the OpenID parameter openid_url = params[:openid_url]

# Make sure we got something if openid_url.blank? flash[:error] = "No OpenID was entered; try again" redirect_to :back return end

# Get an OpenID response openid_response = openid_consumer.begin openid_url

home_url = url_for :controller => "openid", :action => "index" complete_url = url_for :controller => "openid", :action => "complete" openid_redirect_url = openid_response.redirect_url(home_url, complete_url) redirect_to openid_redirect_url

returnend

LET’S TRY IT OUT!

$> gem install ruby-openid$> script/generate controller openid new create complete openid_consumerviews/openid/new.html.erb:<html> <head> <title>Log in with OpenID</title> </head> <body> <% if not flash[:error].blank? %> <p><b><%= flash[:error] -%></b></p> <% end %>

<% form_tag "/openid/create" do %> <%= text_field_tag "openid_url" %> <%= submit_tag "Log in with OpenID" %> <% end %> </body></html>

{ }

def complete home_url = url_for :controller => "openid", :action => "index" complete_url = url_for :controller => "openid", :action => "complete"

openid_response = openid_consumer.complete(params, complete_url)

session[:openid] = openid_response.identity_url flash[:error] = "You have been logged in as '#{session[:openid]}'" redirect_to :action => "new" returnend

HTTP://WWW.LINUXJOURNAL.COM/ARTICLE/10104

11

def openid_consumer if @openid_consumer.blank? @openid_consumer = OpenID::Consumer.new(session, OpenID::Store::Filesystem.new("#{RAILS_ROOT}/tmp/openid")) end

return @openid_consumerend

def create # Get the OpenID parameter openid_url = params[:openid_url]

# Make sure we got something if openid_url.blank? flash[:error] = "No OpenID was entered; try again" redirect_to :back return end

# Get an OpenID response openid_response = openid_consumer.begin openid_url

home_url = url_for :controller => "openid", :action => "index" complete_url = url_for :controller => "openid", :action => "complete" openid_redirect_url = openid_response.redirect_url(home_url, complete_url) redirect_to openid_redirect_url

returnend

LET’S TRY IT OUT!

$> gem install ruby-openid$> script/generate controller openid new create complete openid_consumerviews/openid/new.html.erb:<html> <head> <title>Log in with OpenID</title> </head> <body> <% if not flash[:error].blank? %> <p><b><%= flash[:error] -%></b></p> <% end %>

<% form_tag "/openid/create" do %> <%= text_field_tag "openid_url" %> <%= submit_tag "Log in with OpenID" %> <% end %> </body></html>

{ }

def complete home_url = url_for :controller => "openid", :action => "index" complete_url = url_for :controller => "openid", :action => "complete"

openid_response = openid_consumer.complete(params, complete_url)

session[:openid] = openid_response.identity_url flash[:error] = "You have been logged in as '#{session[:openid]}'" redirect_to :action => "new" returnend

HTTP://WWW.LINUXJOURNAL.COM/ARTICLE/10104

11

def openid_consumer if @openid_consumer.blank? @openid_consumer = OpenID::Consumer.new(session, OpenID::Store::Filesystem.new("#{RAILS_ROOT}/tmp/openid")) end

return @openid_consumerend

def create # Get the OpenID parameter openid_url = params[:openid_url]

# Make sure we got something if openid_url.blank? flash[:error] = "No OpenID was entered; try again" redirect_to :back return end

# Get an OpenID response openid_response = openid_consumer.begin openid_url

home_url = url_for :controller => "openid", :action => "index" complete_url = url_for :controller => "openid", :action => "complete" openid_redirect_url = openid_response.redirect_url(home_url, complete_url) redirect_to openid_redirect_url

returnend

LET’S TRY IT OUT!

$> gem install ruby-openid$> script/generate controller openid new create complete openid_consumerviews/openid/new.html.erb:<html> <head> <title>Log in with OpenID</title> </head> <body> <% if not flash[:error].blank? %> <p><b><%= flash[:error] -%></b></p> <% end %>

<% form_tag "/openid/create" do %> <%= text_field_tag "openid_url" %> <%= submit_tag "Log in with OpenID" %> <% end %> </body></html>

{ }

def complete home_url = url_for :controller => "openid", :action => "index" complete_url = url_for :controller => "openid", :action => "complete"

openid_response = openid_consumer.complete(params, complete_url)

session[:openid] = openid_response.identity_url flash[:error] = "You have been logged in as '#{session[:openid]}'" redirect_to :action => "new" returnend

HTTP://WWW.LINUXJOURNAL.COM/ARTICLE/10104

11