[Jifty-commit] r4254 - in jifty/trunk: lib/Jifty/Plugin lib/Jifty/Plugin/Authentication/Password/Action lib/Jifty/Plugin/OAuth lib/Jifty/Plugin/OAuth/Action lib/Jifty/Plugin/OAuth/Model

jifty-commit at lists.jifty.org jifty-commit at lists.jifty.org
Thu Oct 18 15:36:38 EDT 2007


Author: sartak
Date: Thu Oct 18 15:36:32 2007
New Revision: 4254

Added:
   jifty/trunk/lib/Jifty/Plugin/OAuth/Action/
   jifty/trunk/lib/Jifty/Plugin/OAuth/Action/AuthorizeRequestToken.pm
Modified:
   jifty/trunk/   (props changed)
   jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm
   jifty/trunk/lib/Jifty/Plugin/OAuth.pm
   jifty/trunk/lib/Jifty/Plugin/OAuth/Dispatcher.pm
   jifty/trunk/lib/Jifty/Plugin/OAuth/Model/AccessToken.pm
   jifty/trunk/lib/Jifty/Plugin/OAuth/Model/RequestToken.pm
   jifty/trunk/lib/Jifty/Plugin/OAuth/Token.pm
   jifty/trunk/lib/Jifty/Plugin/OAuth/View.pm

Log:
 r43835 at onn:  sartak | 2007-10-18 15:36:22 -0400
 Many improvements, including some pages


Modified: jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm	(original)
+++ jifty/trunk/lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm	Thu Oct 18 15:36:32 2007
@@ -97,3 +97,102 @@
 }
 
 1;
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Plugin::Authentication::Password::Action::SendPasswordReminder
+
+=cut
+
+package Jifty::Plugin::Authentication::Password::Action::SendPasswordReminder;
+use base qw/Jifty::Action/;
+
+
+__PACKAGE__->mk_accessors(qw(user_object));
+
+=head2 arguments
+
+The field for C<SendLostPasswordReminder> is:
+
+=over 4
+
+=item address: the email address
+
+=back
+
+=cut
+
+sub arguments {
+    return (
+        {
+            address => {
+                label     => _('Email'),
+                mandatory => 1,
+            },
+        }
+    );
+
+}
+
+=head2 setup
+
+Create an empty user object to work with
+
+=cut
+
+sub setup {
+    my $self = shift;
+    my $LoginUser   = Jifty->app_class('Model','User');
+        my $CurrentUser = Jifty->app_class('CurrentUser');
+
+
+
+    # Make a blank user object
+    $self->user_object(
+        $LoginUser->new( current_user => $CurrentUser->superuser ) );
+}
+
+=head2 validate_address
+
+Make sure there's actually an account by that name.
+
+=cut
+
+sub validate_address {
+    my $self  = shift;
+    my $email = shift;
+    my $LoginUser   = Jifty->app_class('Model','User');
+        my $CurrentUser = Jifty->app_class('CurrentUser');
+        
+
+    return $self->validation_error(
+        address => _("That doesn't look like an email address.") )
+      unless ( $email =~ /\S\@\S/ );
+
+    $self->user_object(
+        $LoginUser->new( current_user => $CurrentUser->superuser ) );
+    $self->user_object->load_by_cols( email => $email );
+    return $self->validation_error(
+        address => _("It doesn't look like there's an account by that name.") )
+      unless ( $self->user_object->id );
+
+    return $self->validation_ok('address');
+}
+
+=head2 take_action
+
+Send out a Reminder email giving a link to a password-reset form.
+
+=cut
+
+sub take_action {
+    my $self = shift;
+    Jifty->app_class('Notification','ConfirmLostPassword')->new(
+        to => $self->user_object )->send;
+    return $self->result->message(
+        _("A link to reset your password has been sent to your email account."));
+}
+
+1;

Modified: jifty/trunk/lib/Jifty/Plugin/OAuth.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Plugin/OAuth.pm	(original)
+++ jifty/trunk/lib/Jifty/Plugin/OAuth.pm	Thu Oct 18 15:36:32 2007
@@ -28,4 +28,36 @@
 
 =cut
 
+=head2 init
+
+Provides defaults for the three URLs that OAuth needs:
+
+=over 4
+
+=item request_token: Request a RequestToken
+
+/oauth/request_token
+
+=item authorize: Authorize a RequestToken
+
+/oauth/authorize
+
+=item access_token: Exchange a RequestToken for an Accesstoken
+
+/oauth/access_token
+
+=cut
+
+our %CONFIG;
+
+sub init {
+    my $self = shift;
+    %CONFIG = (
+        request_token => '/oauth/request_token',
+        authorize     => '/oauth/authorize',
+        access_token  => '/oauth/access_token',
+        @_
+    );
+}
+
 1;

Added: jifty/trunk/lib/Jifty/Plugin/OAuth/Action/AuthorizeRequestToken.pm
==============================================================================
--- (empty file)
+++ jifty/trunk/lib/Jifty/Plugin/OAuth/Action/AuthorizeRequestToken.pm	Thu Oct 18 15:36:32 2007
@@ -0,0 +1,74 @@
+package Jifty::Plugin::OAuth::Action::AuthorizeRequestToken;
+use warnings;
+use strict;
+use base qw/Jifty::Action/;
+
+=head1 NAME
+
+Jifty::Plugin::OAuth::Action::AuthorizeRequestToken
+
+=cut
+
+use Jifty::Param::Schema;
+use Jifty::Action schema {
+
+    param 'token',
+        render as 'text',
+        max_length is 30,
+        hints are 'The site you just came from should have provided it';
+
+    param 'authorize',
+        valid_values are qw(allow deny);
+
+};
+
+=head2 validate_token
+
+Make sure we have such a token, and that it is not already authorized
+
+=cut
+
+sub validate_token {
+    my $self = shift;
+    my $token = shift;
+
+    my $request_token = Jifty::Plugin::OAuth::Model::RequestToken->new(current_user => Jifty::CurrentUser->superuser);
+    $request_token->load_by_cols(
+        token => $token,
+        authorized => 'f',
+    );
+
+    return $self->validation_error(token => "I don't know of that request token.") unless $request_token->id;
+
+    return $self->validation_ok('token');
+}
+
+=head2 take_action
+
+Actually authorize or deny this request token
+
+=cut
+
+sub take_action {
+    my $self = shift;
+
+    my $token = Jifty::Plugin::OAuth::Model::RequestToken->new(current_user => Jifty::CurrentUser->superuser);
+    $token->load_by_cols(
+        token => $self->argument_value('token'),
+        user => Jifty->web->current_user->id
+    );
+
+    if ($self->argument_value('authorize') eq 'allow') {
+        $token->set_authorized('t');
+        $self->result->message("Allowing " . $token->consumer->name . " to access your stuff.");
+    }
+    else {
+        $token->delete;
+        $self->result->message("Denying " . $token->consumer->name . " the right to access your stuff.");
+    }
+
+    return 1;
+}
+
+1;
+

Modified: jifty/trunk/lib/Jifty/Plugin/OAuth/Dispatcher.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Plugin/OAuth/Dispatcher.pm	(original)
+++ jifty/trunk/lib/Jifty/Plugin/OAuth/Dispatcher.pm	Thu Oct 18 15:36:32 2007
@@ -8,13 +8,9 @@
 use Net::OAuth::AccessTokenRequest;
 use Net::OAuth::ProtectedResourceRequest;
 
-my $request_token_url = '/oauth/request_token';
-my $authorize_url     = '/oauth/authorize';
-my $access_token_url  = '/oauth/access_token';
-
-before POST $request_token_url => \&request_token;
-before GET  $authorize_url     => \&authorize;
-before POST $access_token_url  => \&access_token;
+before POST $Jifty::Plugin::OAuth::CONFIG{request_token} => \&request_token;
+before GET  $Jifty::Plugin::OAuth::CONFIG{authorize}     => \&authorize;
+before POST $Jifty::Plugin::OAuth::CONFIG{access_token}  => \&access_token;
 
 # a consumer wants a request token
 sub request_token {
@@ -27,7 +23,7 @@
 
     # Net::OAuth::Request will die hard if it doesn't get everything it wants
     my $request = eval { Net::OAuth::RequestTokenRequest->new(
-        request_url     => $request_token_url,
+        request_url     => Jifty->web->url(path => $Jifty::Plugin::OAuth::CONFIG{request_token}),
         request_method  => Jifty->handler->apache->method(),
         consumer_secret => $consumer->secret,
 
@@ -59,23 +55,47 @@
 
 # the user is authorizing (or denying) a consumer's request token
 sub authorize {
+    my @params = qw/token callback/;
 
+    set no_abort => 1;
+    my %oauth_params = get_parameters(@params);
+
+    set next => $oauth_params{callback};
+
+    if ($oauth_params{token}) {
+        my $request_token = Jifty::Plugin::OAuth::Model::RequestToken->new(current_user => Jifty::CurrentUser->superuser);
+        $request_token->load_by_cols(token => $oauth_params{token});
+
+        if ($request_token->id) {
+            set consumer => $request_token->consumer;
+            set token    => $oauth_params{token};
+        }
+    }
+
+    default consumer => 'Some application';
 }
 
 # the consumer is trying to trade a request token for an access token
 sub access_token {
     my @params = qw/consumer_key signature_method signature
-                    timestamp nonce token token_secret version/;
+                    timestamp nonce token version/;
 
     my %oauth_params = get_parameters(@params);
     validate_signature_method($oauth_params{signature_method});
     my $consumer = get_consumer($oauth_params{consumer_key});
 
+    # is the request token they're using still valid?
+    my $request_token = Jifty::Plugin::OAuth::Model::RequestToken->new(current_user => Jifty::CurrentUser->superuser);
+    $request_token->load_by_cols(consumer => $consumer, token => $oauth_params{token});
+    abort(401) unless $request_token->id;
+    abort(401) unless $request_token->can_trade_for_access_token;
+
     # Net::OAuth::Request will die hard if it doesn't get everything it wants
     my $request = eval { Net::OAuth::AccessTokenRequest->new(
-        request_url     => $request_token_url,
+        request_url     => Jifty->web->url(path => $Jifty::Plugin::OAuth::CONFIG{access_token}),
         request_method  => Jifty->handler->apache->method(),
         consumer_secret => $consumer->secret,
+        token_secret    => $request_token->secret,
 
         map { $_ => $oauth_params{$_} } @params
     ) };
@@ -85,12 +105,6 @@
     # make sure the signature matches the rest of what the consumer gave us
     abort(401) unless $request->verify;
 
-    # is the request token they're using still valid?
-    my $request_token = Jifty::Plugin::OAuth::Model::RequestToken->new(current_user => Jifty::CurrentUser->superuser);
-    $request_token->load_by_cols(consumer => $consumer, token => $oauth_params{token}, token_secret => $oauth_params{token_secret});
-    abort(401) unless $request_token->id;
-    abort(401) unless $request_token->can_trade_for_access_token;
-
     my $token = Jifty::Plugin::OAuth::Model::AccessToken->new(current_user => Jifty::CurrentUser->superuser);
 
     my ($ok) = eval {
@@ -122,6 +136,7 @@
     my %p;
 
     # XXX: Check Authorization header
+    # XXX: Check WWW-Authenticate header
 
     %p = ((map {
         my $v = Jifty->handler->apache->header_in("oauth_$_");
@@ -131,7 +146,11 @@
     # XXX: Check query string
 
     $p{version} ||= '1.0';
-    abort(400) if grep { !defined($p{$_}) } @_;
+
+    unless (get 'no_abort') {
+        abort(400) if grep { !defined($p{$_}) } @_
+    }
+
     return %p;
 }
 

Modified: jifty/trunk/lib/Jifty/Plugin/OAuth/Model/AccessToken.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Plugin/OAuth/Model/AccessToken.pm	(original)
+++ jifty/trunk/lib/Jifty/Plugin/OAuth/Model/AccessToken.pm	Thu Oct 18 15:36:32 2007
@@ -21,7 +21,7 @@
         type is 'timestamp',
         filters are 'Jifty::DBI::Filter::DateTime';
 
-    column token_secret =>
+    column secret =>
         type is 'varchar';
 
     column consumer =>

Modified: jifty/trunk/lib/Jifty/Plugin/OAuth/Model/RequestToken.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Plugin/OAuth/Model/RequestToken.pm	(original)
+++ jifty/trunk/lib/Jifty/Plugin/OAuth/Model/RequestToken.pm	Thu Oct 18 15:36:32 2007
@@ -35,7 +35,7 @@
     column token =>
         type is 'varchar';
 
-    column token_secret =>
+    column secret =>
         type is 'varchar';
 
     # we use these to make sure we aren't being hit with a replay attack
@@ -46,7 +46,7 @@
         type is 'varchar';
 };
 
-sub set_authorized {
+sub after_set_authorized {
     my $self = shift;
     $self->set_authorized_by(Jifty->web->current_user->id);
 }

Modified: jifty/trunk/lib/Jifty/Plugin/OAuth/Token.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Plugin/OAuth/Token.pm	(original)
+++ jifty/trunk/lib/Jifty/Plugin/OAuth/Token.pm	Thu Oct 18 15:36:32 2007
@@ -28,7 +28,7 @@
     return if !defined($attr->{token});
 
     # generate a secret. need not be unique, just hard to guess
-    $attr->{token_secret} = generate_token();
+    $attr->{secret} = generate_token();
 
     # default the lifetime of this token to 1 hour
     $attr->{valid_until} ||= DateTime->now->add(hours => 1);

Modified: jifty/trunk/lib/Jifty/Plugin/OAuth/View.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Plugin/OAuth/View.pm	(original)
+++ jifty/trunk/lib/Jifty/Plugin/OAuth/View.pm	Thu Oct 18 15:36:32 2007
@@ -4,5 +4,115 @@
 
 use Jifty::View::Declare -base;
 
+template 'oauth' => page {
+    p {
+        b { a { attr { href => "http://oauth.net/" } "OAuth" } };
+        outs " is an open protocol to allow secure authentication to users' private data."
+    }
+
+    p {
+        "This application supports OAuth. If you'd like to access the private resources of users of this site, you must first establish a Consumer Key and Consumer Secret with us. You can do so by contacting " . (Jifty->config->framework('AdminEmail')||'us') . ".";
+    }
+
+    p {
+        "Once you have a Consumer Key and Consumer Secret, you may begin letting users grant you access to our site. The relevant URLs are:"
+    }
+
+    dl {
+        dt {
+            outs "Request a Request Token";
+            dd { Jifty->web->url(path => $Jifty::Plugin::OAuth::CONFIG{request_token}) }
+        }
+        dt {
+            outs "Obtain user authorization for a Request Token";
+            dd { Jifty->web->url(path => $Jifty::Plugin::OAuth::CONFIG{authorize}) }
+        }
+        dt {
+            outs "Exchange a Request Token for an Access Token";
+            dd { Jifty->web->url(path => $Jifty::Plugin::OAuth::CONFIG{access_token}) }
+        }
+    }
+
+    p {
+        my $restful = 0;
+        for (@{ Jifty->config->framework('Plugins') }) {
+            if (defined $_->{REST}) {
+                $restful = 1;
+                last;
+            }
+        }
+
+        outs "While you have a valid access token, you may browse the site as the user normally does.";
+
+        if ($restful) {
+            outs " You may also use our REST interface. See ";
+            a {
+                attr { href => Jifty->web->url(path => '=/help') }
+                Jifty->web->url(path => '=/help')
+            }
+        }
+    }
+};
+
+template 'oauth/authorize' => page { title => 'Someone wants stuff!' }
+content {
+    show '/oauth/help';
+
+    my $authorize = Jifty->web->new_action(
+        moniker => 'authorize_request_token',
+        class   => 'AuthorizeRequestToken',
+    );
+
+    Jifty->web->form->start( call => get('next') );
+
+    # if the site put the token in the request, then use it
+    # otherwise, prompt the user for it
+    my %args;
+    my $token = get 'token';
+    if ($token) {
+        $args{token} = $token;
+    }
+    else {
+        $authorize->form_field('token')->render;
+    }
+
+    $authorize->button(
+        label => 'Allow',
+        arguments => { %args, authorize => 'allow' },
+    );
+
+    $authorize->button(
+        label => 'Deny',
+        arguments => { %args, authorize => 'deny' },
+    );
+
+    Jifty->web->form->end();
+};
+
+private template 'oauth/help' => sub {
+    div {
+        p {
+            show '/oauth/consumer';
+            outs ' is trying to access some of your data on this site. If you trust this application, you may grant it access. Note that access is read-only and will expire in one hour.';
+        }
+        p {
+            "If you're at all uncomfortable with the idea of someone rifling through your things, click Deny."
+        }
+    }
+};
+
+private template 'oauth/consumer' => sub {
+    my $consumer = get 'consumer' || 'Some application';
+
+    span {
+        outs ref($consumer) ? $consumer->name : $consumer;
+        if (ref($consumer) && $consumer->url) {
+            outs ' (';
+            a { attr { $consumer->url } $consumer->url };
+            outs ')';
+        }
+    }
+};
+
 1;
 


More information about the Jifty-commit mailing list