From 9600c5e53b5fc5c51be58b5945ab779cbf2f5baf Mon Sep 17 00:00:00 2001 From: David Cook Date: Fri, 17 Jun 2022 04:43:44 +0000 Subject: [PATCH] Bug 30962: REST API: Add endpoint /auth/password/validation This patch adds an endpoint for /auth/password/validation This allows a third-party, using an authenticated and authorized Koha API user, to check if the username and password given by a user is correct in Koha. For example, a Keycloak extension can be created using its User Storage SPI to use Koha as the user database for Keycloak. This API allows us to authenticate the user as a particular Koha user - without creating a Koha user session for them. Test plan: 0. Apply patch and koha-plack --restart kohadev 1. Go to http://localhost:8081/cgi-bin/koha/admin/preferences.pl?op=search&searchfield=RESTBasicAuth 2. Enable "RESTBasicAuth" 3. Run the following commands while substituting correct values for and 3. curl -XPOST -H "Content-Type: application/json" -u : http://localhost:8081/api/v1/auth/password/validation -d '{ "username": ", "password": "" }' -v 4. Note "204 No Content" response 5. curl -XPOST -H "Content-Type: application/json" -u : http://localhost:8081/api/v1/auth/password/validation -d '{ "username": ", "password": "this is definitely not the password" }' -v 6. Note "400 Bad Request" response and error message {"error":"Validation failed"} Signed-off-by: David Nind --- Koha/REST/V1/Auth/Password.pm | 76 ++++++++++++++++++++++++++++++++++ api/v1/swagger/paths/auth.yaml | 57 ++++++++++++++++++++++++- api/v1/swagger/swagger.yaml | 2 + 3 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 Koha/REST/V1/Auth/Password.pm diff --git a/Koha/REST/V1/Auth/Password.pm b/Koha/REST/V1/Auth/Password.pm new file mode 100644 index 0000000000..8cc9304f84 --- /dev/null +++ b/Koha/REST/V1/Auth/Password.pm @@ -0,0 +1,76 @@ +package Koha::REST::V1::Auth::Password; + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +use Modern::Perl; + +use Mojo::Base 'Mojolicious::Controller'; + +use C4::Auth qw/checkpw/; +use Koha::Patrons; + +=head1 NAME + +Koha::REST::V1::Auth::Password - Controller library for handling +validation of username and password. + +Intended use case is authenticating Koha patrons in external +applications via Koha's REST API. + +=head2 Operations + +=head3 validate + +Controller method that checks a patron's password + +=cut + +sub validate { + my $c = shift->openapi->valid_input or return; + my $body = $c->validation->param('body'); + my $username = $body->{username} // ''; + my $patron = Koha::Patrons->find({ userid => $username }); + + unless ($patron) { + return $c->render( status => 400, openapi => { error => "Validation failed" } ); + } + + my $password = $body->{password} // ""; + + return try { + my ($status, $cardnumber, $userid) = C4::Auth::checkpw($patron->userid, $password ); + unless ( $status ) { + return $c->render( + status => 400, + openapi => { error => "Validation failed" } + ); + } + + return $c->render( status => 204, openapi => '' ); + } + catch { + if ( blessed $_ and $_->isa('Koha::Exceptions::Password') ) { + return $c->render( + status => 400, + openapi => { error => "$_" } + ); + } + + $c->unhandled_exception($_); + }; +} + +1; diff --git a/api/v1/swagger/paths/auth.yaml b/api/v1/swagger/paths/auth.yaml index d7be7e8687..7130860b89 100644 --- a/api/v1/swagger/paths/auth.yaml +++ b/api/v1/swagger/paths/auth.yaml @@ -1055,4 +1055,59 @@ $ref: ../swagger.yaml#/definitions/error x-koha-authorization: permissions: - parameters: manage_identity_providers \ No newline at end of file + parameters: manage_identity_providers +"/auth/password/validation": + post: + x-mojo-to: Auth::Password#validate + operationId: validateUserAndPassword + tags: + - patrons + summary: Check validity of username and password + parameters: + - name: body + in: body + description: A JSON object containing username and password information + schema: + type: object + properties: + username: + description: Username + type: string + password: + description: Password (plain text) + type: string + required: + - username + - password + additionalProperties: false + produces: + - application/json + responses: + "204": + description: Validation successful + "400": + description: Bad request + schema: + $ref: ../swagger.yaml#/definitions/error + "401": + description: Authentication required + schema: + $ref: ../swagger.yaml#/definitions/error + "403": + description: Access forbidden + schema: + $ref: ../swagger.yaml#/definitions/error + "500": + description: | + Internal server error. Possible `error_code` attribute values: + + * `internal_server_error` + schema: + $ref: ../swagger.yaml#/definitions/error + "503": + description: Under maintenance + schema: + $ref: ../swagger.yaml#/definitions/error + x-koha-authorization: + permissions: + borrowers: "1" diff --git a/api/v1/swagger/swagger.yaml b/api/v1/swagger/swagger.yaml index 696a73be8b..479c4d710b 100644 --- a/api/v1/swagger/swagger.yaml +++ b/api/v1/swagger/swagger.yaml @@ -125,6 +125,8 @@ paths: $ref: "./paths/article_requests.yaml#/~1article_requests~1{article_request_id}" /auth/otp/token_delivery: $ref: paths/auth.yaml#/~1auth~1otp~1token_delivery + "/auth/password/validation": + $ref: "./paths/auth.yaml#/~1auth~1password~1validation" /auth/two-factor/registration: $ref: paths/auth.yaml#/~1auth~1two-factor~1registration /auth/two-factor/registration/verification: -- 2.30.2