From 2274c804ce4fc3fcb7cc3e6bde2a06bd95fca685 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 /patrons/:patron_id/check_password This patch adds an endpoint for /patrons/:patron_id/check_password 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/patrons/51/check_password -d '{ "password": "" }' -v 4. Note "200 OK" response 5. curl -XPOST -H "Content-Type: application/json" -u : http://localhost:8081/api/v1/patrons/51/check_password -d '{ "password": "this is definitely not the password" }' -v 6. Note "400 Bad Request" response and error message {"error":"Invalid password"} Signed-off-by: David Nind --- Koha/REST/V1/Patrons/Password.pm | 43 +++++++++++++++++ api/v1/swagger/paths/patrons_password.yaml | 56 ++++++++++++++++++++++ api/v1/swagger/swagger.yaml | 2 + 3 files changed, 101 insertions(+) diff --git a/Koha/REST/V1/Patrons/Password.pm b/Koha/REST/V1/Patrons/Password.pm index 35379edf18..f5ef3025aa 100644 --- a/Koha/REST/V1/Patrons/Password.pm +++ b/Koha/REST/V1/Patrons/Password.pm @@ -144,4 +144,47 @@ sub set_public { }; } +=head3 check_password + +Controller method that checks a patron's password + +=cut + +sub check_password { + + my $c = shift->openapi->valid_input or return; + + my $patron = Koha::Patrons->find( $c->validation->param('patron_id') ); + my $body = $c->validation->param('body'); + + unless ($patron) { + return $c->render( status => 404, openapi => { error => "Patron not found." } ); + } + + my $password = $body->{password} // ""; + + return try { + my $dbh = C4::Context->dbh; + my ($status, $cardnumber, $userid) = C4::Auth::checkpw($dbh, $patron->userid, $password ); + unless ( $status ) { + return $c->render( + status => 400, + openapi => { error => "Invalid password" } + ); + } + + return $c->render( status => 200, 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/patrons_password.yaml b/api/v1/swagger/paths/patrons_password.yaml index 393dfa6e91..696d122ffd 100644 --- a/api/v1/swagger/paths/patrons_password.yaml +++ b/api/v1/swagger/paths/patrons_password.yaml @@ -116,3 +116,59 @@ x-koha-authorization: permissions: superlibrarian: "1" +"/patrons/{patron_id}/check_password": + post: + x-mojo-to: Patrons::Password#check_password + operationId: checkPatronPassword + tags: + - patrons + summary: Check password for a patron + parameters: + - $ref: ../swagger.yaml#/parameters/patron_id_pp + - name: body + in: body + description: A JSON object containing password information + schema: + type: object + properties: + password: + description: Password (plain text) + type: string + required: + - password + additionalProperties: false + produces: + - application/json + responses: + "200": + description: Check password succeeded + "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 + "404": + description: Patron not found + 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 88e3bef4bd..d30d5f6f52 100644 --- a/api/v1/swagger/swagger.yaml +++ b/api/v1/swagger/swagger.yaml @@ -179,6 +179,8 @@ paths: $ref: "./paths/patrons_password.yaml#/~1patrons~1{patron_id}~1password" "/patrons/{patron_id}/password/expiration_date": $ref: "./paths/patrons_password.yaml#/~1patrons~1{patron_id}~1password~1expiration_date" + "/patrons/{patron_id}/check_password": + $ref: "./paths/patrons_password.yaml#/~1patrons~1{patron_id}~1check_password" "/public/biblios/{biblio_id}": $ref: "./paths/biblios.yaml#/~1public~1biblios~1{biblio_id}" "/public/biblios/{biblio_id}/items": -- 2.30.2