summaryrefslogtreecommitdiffstats
path: root/Bugzilla/WebService
diff options
context:
space:
mode:
authorDave Lawrence <dlawrence@mozilla.com>2013-08-27 05:54:32 +0200
committerDave Lawrence <dlawrence@mozilla.com>2013-08-27 05:54:32 +0200
commit7450b47683d0aa972a522f5b70353e14269a95e6 (patch)
tree1c7908ede712092ac91b1508079e0b8dfebf67ec /Bugzilla/WebService
parent95aadcd21c9a56ef7d3478a2504980ea44f1bd9c (diff)
downloadbugzilla-7450b47683d0aa972a522f5b70353e14269a95e6.tar.gz
bugzilla-7450b47683d0aa972a522f5b70353e14269a95e6.tar.xz
Bug 893195 - Allow token based authentication for webservices
r=glob,a=sgreen
Diffstat (limited to 'Bugzilla/WebService')
-rw-r--r--Bugzilla/WebService/Server/JSONRPC.pm6
-rw-r--r--Bugzilla/WebService/Server/REST.pm38
-rw-r--r--Bugzilla/WebService/Server/REST/Resources/User.pm10
-rw-r--r--Bugzilla/WebService/User.pm29
-rw-r--r--Bugzilla/WebService/Util.pm23
5 files changed, 82 insertions, 24 deletions
diff --git a/Bugzilla/WebService/Server/JSONRPC.pm b/Bugzilla/WebService/Server/JSONRPC.pm
index e7b3fe7e7..5290caa5d 100644
--- a/Bugzilla/WebService/Server/JSONRPC.pm
+++ b/Bugzilla/WebService/Server/JSONRPC.pm
@@ -25,7 +25,7 @@ BEGIN {
use Bugzilla::Error;
use Bugzilla::WebService::Constants;
-use Bugzilla::WebService::Util qw(taint_data);
+use Bugzilla::WebService::Util qw(taint_data fix_credentials);
use Bugzilla::Util;
use HTTP::Message;
@@ -373,6 +373,10 @@ sub _argument_type_check {
}
}
+ # Update the params to allow for several convenience key/values
+ # use for authentication
+ fix_credentials($params);
+
Bugzilla->input_params($params);
if ($self->request->method eq 'POST') {
diff --git a/Bugzilla/WebService/Server/REST.pm b/Bugzilla/WebService/Server/REST.pm
index 454749b5d..4145455ec 100644
--- a/Bugzilla/WebService/Server/REST.pm
+++ b/Bugzilla/WebService/Server/REST.pm
@@ -16,7 +16,7 @@ use Bugzilla;
use Bugzilla::Constants;
use Bugzilla::Error;
use Bugzilla::WebService::Constants;
-use Bugzilla::WebService::Util qw(taint_data);
+use Bugzilla::WebService::Util qw(taint_data fix_credentials);
use Bugzilla::Util qw(correct_urlbase html_quote);
# Load resource modules
@@ -69,7 +69,7 @@ sub handle {
my $params = $self->_retrieve_json_params;
- $self->_fix_credentials($params);
+ fix_credentials($params);
# Fix includes/excludes for each call
rest_include_exclude($params);
@@ -131,7 +131,7 @@ sub response {
# If accessing through web browser, then display in readable format
if ($self->content_type eq 'text/html') {
- $result = $self->json->pretty->canonical->encode($result);
+ $result = $self->json->pretty->canonical->allow_nonref->encode($result);
my $template = Bugzilla->template;
$content = "";
@@ -162,8 +162,15 @@ sub handle_login {
# explicitly gives that site their username and password. (This is
# particularly important for JSONP, which would allow a remote site
# to use private data without the user's knowledge, unless we had this
- # protection in place.)
- if (!grep($_ eq $self->request->method, ('POST', 'PUT'))) {
+ # protection in place.) We do allow this for GET /login as we need to
+ # for Bugzilla::Auth::Persist::Cookie to create a login cookie that we
+ # can also use for Bugzilla_token support. This is OK as it requires
+ # a login and password to be supplied and will fail if they are not
+ # valid for the user.
+ if (!grep($_ eq $self->request->method, ('POST', 'PUT'))
+ && !($self->bz_class_name eq 'Bugzilla::WebService::User'
+ && $self->bz_method_name eq 'login'))
+ {
# XXX There's no particularly good way for us to get a parameter
# to Bugzilla->login at this point, so we pass this information
# around using request_cache, which is a bit of a hack. The
@@ -424,15 +431,6 @@ sub _find_resource {
return $handler_found;
}
-sub _fix_credentials {
- my ($self, $params) = @_;
- # Allow user to pass in &username=foo&password=bar
- if (exists $params->{'username'} && exists $params->{'password'}) {
- $params->{'Bugzilla_login'} = delete $params->{'username'};
- $params->{'Bugzilla_password'} = delete $params->{'password'};
- }
-}
-
sub _best_content_type {
my ($self, @types) = @_;
return ($self->_simple_content_negotiation(@types))[0] || '*/*';
@@ -545,15 +543,23 @@ if you have a Bugzilla account by providing your login credentials.
=over
-=item Username and password
+=item Login name and password
Pass in as query parameters of any request:
-username=fred@bedrock.com&password=ilovewilma
+login=fred@example.com&password=ilovecheese
Remember to URL encode any special characters, which are often seen in passwords and to
also enable SSL support.
+=item Login token
+
+By calling GET /login?login=fred@example.com&password=ilovecheese, you get back
+a C<token> value which can then be passed to each subsequent call as
+authentication. This is useful for third party clients that cannot use cookies
+and do not want to store a user's login and password in the client. You can also
+pass in "token" as a convenience.
+
=back
=head1 ERRORS
diff --git a/Bugzilla/WebService/Server/REST/Resources/User.pm b/Bugzilla/WebService/Server/REST/Resources/User.pm
index e2a2ea260..539a9313a 100644
--- a/Bugzilla/WebService/Server/REST/Resources/User.pm
+++ b/Bugzilla/WebService/Server/REST/Resources/User.pm
@@ -19,6 +19,16 @@ BEGIN {
sub _rest_resources {
my $rest_resources = [
+ qr{^/login$}, {
+ GET => {
+ method => 'login'
+ }
+ },
+ qr{^/logout$}, {
+ GET => {
+ method => 'logout'
+ }
+ },
qr{^/valid_login$}, {
GET => {
method => 'valid_login'
diff --git a/Bugzilla/WebService/User.pm b/Bugzilla/WebService/User.pm
index 44938a97a..ba8640f3d 100644
--- a/Bugzilla/WebService/User.pm
+++ b/Bugzilla/WebService/User.pm
@@ -19,6 +19,8 @@ use Bugzilla::User;
use Bugzilla::Util qw(trim);
use Bugzilla::WebService::Util qw(filter validate translate params_to_objects);
+use List::Util qw(first);
+
# Don't need auth to login
use constant LOGIN_EXEMPT => {
login => 1,
@@ -73,14 +75,25 @@ sub login {
$input_params->{'Bugzilla_password'} = $params->{password};
$input_params->{'Bugzilla_remember'} = $remember;
- Bugzilla->login();
- return { id => $self->type('int', Bugzilla->user->id) };
+ my $user = Bugzilla->login();
+
+ my $result = { id => $self->type('int', $user->id) };
+
+ # We will use the stored cookie value combined with the user id
+ # to create a token that can be used with future requests in the
+ # query parameters
+ my $login_cookie = first { $_->name eq 'Bugzilla_logincookie' }
+ @{ Bugzilla->cgi->{'Bugzilla_cookie_list'} };
+ if ($login_cookie) {
+ $result->{'token'} = $user->id . "-" . $login_cookie->value;
+ }
+
+ return $result;
}
sub logout {
my $self = shift;
Bugzilla->logout;
- return undef;
}
sub valid_login {
@@ -448,10 +461,12 @@ management of cookies across sessions.
=item B<Returns>
-On success, a hash containing one item, C<id>, the numeric id of the
-user that was logged in. A set of http cookies is also sent with the
-response. These cookies must be sent along with any future requests
-to the webservice, for the duration of the session.
+On success, a hash containing two items, C<id>, the numeric id of the
+user that was logged in, and a C<token> which can be passed in
+the parameters as authentication in other calls. A set of http cookies
+is also sent with the response. These cookies *or* the token can be sent
+along with any future requests to the webservice, for the duration of the
+session.
=item B<Errors>
diff --git a/Bugzilla/WebService/Util.pm b/Bugzilla/WebService/Util.pm
index c24f95923..be7251532 100644
--- a/Bugzilla/WebService/Util.pm
+++ b/Bugzilla/WebService/Util.pm
@@ -23,6 +23,7 @@ our @EXPORT_OK = qw(
validate
translate
params_to_objects
+ fix_credentials
);
sub filter ($$;$) {
@@ -146,6 +147,22 @@ sub params_to_objects {
return \@objects;
}
+sub fix_credentials {
+ my ($params) = @_;
+ # Allow user to pass in login=foo&password=bar as a convenience
+ # even if not calling GET /login. We also do not delete them as
+ # GET /login requires "login" and "password".
+ if (exists $params->{'login'} && exists $params->{'password'}) {
+ $params->{'Bugzilla_login'} = $params->{'login'};
+ $params->{'Bugzilla_password'} = $params->{'password'};
+ }
+ # Allow user to pass token=12345678 as a convenience which becomes
+ # "Bugzilla_token" which is what the auth code looks for.
+ if (exists $params->{'token'}) {
+ $params->{'Bugzilla_token'} = $params->{'token'};
+ }
+}
+
__END__
=head1 NAME
@@ -209,6 +226,12 @@ Helps make life simpler for WebService methods that internally create objects
via both "ids" and "names" fields. Also de-duplicates objects that were loaded
by both "ids" and "names". Returns an arrayref of objects.
+=head2 fix_credentials
+
+Allows for certain parameters related to authentication such as Bugzilla_login,
+Bugzilla_password, and Bugzilla_token to have shorter named equivalents passed in.
+This function converts the shorter versions to their respective internal names.
+
=head1 B<Methods in need of POD>
=over