diff options
author | Dave Lawrence <dlawrence@mozilla.com> | 2013-08-27 05:54:32 +0200 |
---|---|---|
committer | Dave Lawrence <dlawrence@mozilla.com> | 2013-08-27 05:54:32 +0200 |
commit | 7450b47683d0aa972a522f5b70353e14269a95e6 (patch) | |
tree | 1c7908ede712092ac91b1508079e0b8dfebf67ec /Bugzilla/WebService | |
parent | 95aadcd21c9a56ef7d3478a2504980ea44f1bd9c (diff) | |
download | bugzilla-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.pm | 6 | ||||
-rw-r--r-- | Bugzilla/WebService/Server/REST.pm | 38 | ||||
-rw-r--r-- | Bugzilla/WebService/Server/REST/Resources/User.pm | 10 | ||||
-rw-r--r-- | Bugzilla/WebService/User.pm | 29 | ||||
-rw-r--r-- | Bugzilla/WebService/Util.pm | 23 |
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 |