Description
Julian Maurice
2015-03-26 18:37:23 UTC
Created attachment 37286 [details] [review] Bug 13920: API Authentication, part 1: API keys management in interface This introduces the concept of API keys for use in the new REST API. A key is a string of 32 alphanumerical characters (32 is purely arbitrary, it can be changed easily). A user can have multiple keys (unlimited at the moment) Keys can be generated automatically, and then we have the possibility to delete or revoke each one individually. Test plan: 1/ Go to staff interface 2/ Go to a borrower page 3/ In toolbar, click on More -> Manage API keys 4/ Click on "Generate new key" multiple times, check that they are correctly displayed under the button, and they are active by default 5/ Revoke some keys, check that they are not active anymore 6/ Delete some keys, check that they disappear from table 7/ Go to opac interface, log in 8/ In your user account pages, you now have a new tab to the left "your API keys". Click on it. 9/ Repeat steps 4-6 Created attachment 37287 [details] [review] Bug 13920: API Authentication, part 2: implement authentication in API For authentication to succeed, the client have to send 3 custom HTTP headers: - X-Koha-Username: userid of borrower - X-Koha-Timestamp: timestamp of the request - X-Koha-Signature: signature of the request The signature is a HMAC-SHA256 hash of several elements of the request, separated by spaces: - HTTP method (uppercase) - URL path and query string - username - timestamp of the request The server then tries to rebuild the signature with each user's API key. If one matches the received X-Koha-Signature, then authentication is almost OK. To avoid requests to be replayed, the last request's timestamp is stored in database and the authentication succeeds only if the stored timestamp is lesser than X-Koha-Timestamp. This patch implements both server-side authentication (in Koha/REST/V1.pm) and client-side authentication in Swagger UI (api/v1/doc/index.html). There is also an "anonymous" mode if X-Koha-* headers are not set. Anonymous mode differ from authenticated mode in one thing: if user is authenticated, the corresponding Koha::Borrower object is stored in Mojolicious stash, so it can easily be retrieved by controllers. Controllers then have the responsability of what to do if user is authenticated or not. Created attachment 37288 [details] [review] [DO NOT PUSH] Bug 13920: Example usage for api authentication 2nd test plan: 1/ Go to http://api.YOURLIBRARY/v1/doc 2/ Try route /borrowers/{borrowernumber} and see you have a 401 (Unauthorized) error 3/ Generate an API key (like described in 1st test plan) for a user that have the 'borrowers' permission 4/ Fill 'username' and 'api_key' inputs at the top of the Swagger UI page and retry /borrowers/{borrowernumber}. You should have a 200 status and the json representation of a borrower (if it exists) Created attachment 40583 [details] [review] Bug 13920 - API authentication system - Swagtenticator authentication - WIP This feature implements REST API-key authentication and Koha permission validation in the Swagger2-plugin extension. This is basically a Mojolicious to Koha authentication using Swagger2 RESTful API definition to autodocument and check for proper user permissions, aka. "KohaliciousSwagtenticator". With this feature the API provider doesn't need to code anything in the Controller to support Koha permissions. Simply by defining a custom Swagger2 parameter "x-koha-parameters": {} the Swagtenticator knows to check the user for proper Koha permissions. Example (require any borrowers-permission): ... "paths": { "/borrowers": { "get": { "x-mojo-controller": "Koha::REST::V1::Borrowers", "x-koha-permission": { "borrowers": "*" }, "operationId": "listBorrowers", ... This x-koha-permission definition is turned to a HASH and given to the C4::Auth::haspermission() for verification by the Swagger2-based plugin. Bug dependencies: Buugg 13995 - Proper Exception handling, which helps a lot in dealing with all the various ways authentication can fail. Buugg 14437 - Refactor C4::Auth::haspermission() to Koha::Object and return better errors. Which returns the failing permission so we can create a more helpful API which tells which permissions are missing (also helps admins in giving the right permissions) This feature is implemented by inheriting Mojolicious::Plugin::Swagger2 in Koha::REST::V1::Plugins::KohaliciousSwagtenticator and overloading the necessary subroutines. TEST PLAN: 1. Add the given example (up) to any "Operation Object *". 2. Call the "Operation object" (eg. /v1/borrowers/10) with user credetials not having any borrower-permissions. 3. Fail because of myriad of reasons. (see. KohaliciousSwagtenticator::check_key_auth()) 4. Add some borrowers-permissions to the same user. 5. Succeed in your operation. * from Swagger2.0 specification Created attachment 40590 [details] [review] Bug 13920: 7. API Authentication, part 1: API keys management in interface Created attachment 40591 [details] [review] Bug 13920: 8. API Authentication, part 2: implement authentication in API Created attachment 40592 [details] [review] Bug 13920 - 9. API authentication system - Swagtenticator authentication - WIP Created attachment 40623 [details] [review] Bug 13920: 7. API Authentication, part 1: API keys management in interface This introduces the concept of API keys for use in the new REST API. A key is a string of 32 alphanumerical characters (32 is purely arbitrary, it can be changed easily). A user can have multiple keys (unlimited at the moment) Keys can be generated automatically, and then we have the possibility to delete or revoke each one individually. Test plan: 1/ Go to staff interface 2/ Go to a borrower page 3/ In toolbar, click on More -> Manage API keys 4/ Click on "Generate new key" multiple times, check that they are correctly displayed under the button, and they are active by default 5/ Revoke some keys, check that they are not active anymore 6/ Delete some keys, check that they disappear from table 7/ Go to opac interface, log in 8/ In your user account pages, you now have a new tab to the left "your API keys". Click on it. 9/ Repeat steps 4-6 Created attachment 40624 [details] [review] Bug 13920: 8. API Authentication, part 2: implement authentication in API For authentication to succeed, the client have to send 3 custom HTTP headers: - X-Koha-Username: userid of borrower - X-Koha-Timestamp: timestamp of the request - X-Koha-Signature: signature of the request The signature is a HMAC-SHA256 hash of several elements of the request, separated by spaces: - HTTP method (uppercase) - URL path and query string - username - timestamp of the request The server then tries to rebuild the signature with each user's API key. If one matches the received X-Koha-Signature, then authentication is almost OK. To avoid requests to be replayed, the last request's timestamp is stored in database and the authentication succeeds only if the stored timestamp is lesser than X-Koha-Timestamp. This patch implements server-side authentication (in Koha/REST/V1.pm) There is also an "anonymous" mode if X-Koha-* headers are not set. Anonymous mode differ from authenticated mode in one thing: if user is authenticated, the corresponding Koha::Borrower object is stored in Mojolicious stash, so it can easily be retrieved by controllers. Controllers then have the responsability of what to do if user is authenticated or not. Created attachment 40625 [details] [review] Bug 13920: 9. API authentication system - Swagtenticator authentication - WIP This feature implements REST API-key authentication and Koha permission validation in the Swagger2-plugin extension. This is basically a Mojolicious to Koha authentication using Swagger2 RESTful API definition to autodocument and check for proper user permissions, aka. "KohaliciousSwagtenticator". With this feature the API provider doesn't need to code anything in the Controller to support Koha permissions. Simply by defining a custom Swagger2 parameter "x-koha-parameters": {} the Swagtenticator knows to check the user for proper Koha permissions. Example (require any borrowers-permission): ... "paths": { "/borrowers": { "get": { "x-mojo-controller": "Koha::REST::V1::Borrowers", "x-koha-permission": { "borrowers": "*" }, "operationId": "listBorrowers", ... This x-koha-permission definition is turned to a HASH and given to the C4::Auth::haspermission() for verification by the Swagger2-based plugin. Bug dependencies: Buugg 13995 - Proper Exception handling, which helps a lot in dealing with all the various ways authentication can fail. Buugg 14437 - Refactor C4::Auth::haspermission() to Koha::Object and return better errors. Which returns the failing permission so we can create a more helpful API which tells which permissions are missing (also helps admins in giving the right permissions) This feature is implemented by inheriting Mojolicious::Plugin::Swagger2 in Koha::REST::V1::Plugins::KohaliciousSwagtenticator and overloading the necessary subroutines. TEST PLAN: 1. Add the given example (up) to any "Operation Object *". 2. Call the "Operation object" (eg. /v1/borrowers/10) with user credetials not having any borrower-permissions. 3. Fail because of myriad of reasons. (see. KohaliciousSwagtenticator::check_key_auth()) 4. Add some borrowers-permissions to the same user. 5. Succeed in your operation. * from Swagger2.0 specification Those patches were applied on top on bug 13895 and 13903 but do not depend on them and that was causing problems to apply this bug's patches Also a strange thing happened because the updatedatabase code was placed between two already existing updates. This was causing problems too. These issues are now fixed (I hope) and patches should apply cleanly. Apply order: 13799 13995 14437 13920 As SwaggerUI has its own bug now, the authentication code for SwaggerUI was also moved in another bug: bug 14461 We agreed to move the SwaggerUI to another bug, because it is a API discovery tool and we shouldn't force people to use our API discovery tool (because there is a whole ecosystem of API discovery tools). Swagger2-plugin extension is a critical feature to make the authentication system easy to use and be "behaviour from documentation". This is exactly the reason why we chose Swagger2 and are using the Mojolicious-framework. Moving the Swagger2-authentication extension to another bug makes no sense because it is an integral part of the REST API authentication system and should be pushed to master as part of the cure REST authentication mechanism. If the Swagger2-extension is not pushed as a core authentication mechanism, then we end up with people doing auth the non-Swagger2-way and then people who do it the Swagger2-way. So I don't see why that commit should be in it's own bug. I don't know what you mean by "Swagger2-authentication extension". It's the SwaggerUI authentication code that was moved to another bug and it makes perfect sense to me as SwaggerUI will not be integrated as part of the REST API With Swagger2-plugin extension I mean Koha::REST::V1::Plugins::KohaliciousSwagtenticator which extends Mojolicious::Plugin::Swagger2, making it possible to define the needed permissions in the swagger.json -file. (In reply to Julian Maurice from comment #13) > As SwaggerUI has its own bug now, the authentication code for SwaggerUI was > also moved in another bug: bug 14461 But I have a gut-feeling that I am misunderstanding what you mean with "the authentication code for SwaggerUI" Since the Swagtenticator-patch seems to still be in this bug :) (In reply to Olli-Antti Kivilahti from comment #17) > But I have a gut-feeling that I am misunderstanding what you mean with > "the authentication code for SwaggerUI" > Since the Swagtenticator-patch seems to still be in this bug :) SwaggerUI (the thing in api/v1/doc) was modified to work with the authentication system proposed in this bug. Only these modifications were moved in another bug. Swagtenticator is still here and it's not a mistake ;) Created attachment 41165 [details] [review] Bug 13920: 7. API Authentication, part 1: API keys management in interface Created attachment 41166 [details] [review] Bug 13920: 8. API authentication system - Swagtenticator authentication Created attachment 41195 [details] [review] Bug 13920: 7. API Authentication, part 1: API keys management in interface Depends on Buugg 14539. Moved CRUD from controller to Koha::ApiKeys. Created attachment 41196 [details] [review] Bug 13920: 7. API Authentication, part 1: API keys management in interface With meaningful return values :) Created attachment 41257 [details] [review] Bug 13920: 7. API Authentication, part 1: API keys management in interface Created attachment 41260 [details] [review] Bug 13920: 7. API Authentication, part 1: API keys management in interface Includes unit tests and selenium integration tests for Intra and OPAC. Moving the authentication system under the main REST API Bug because this is no longer WIP or a draft but a real working authentication system. (with some bugs on it) *** This bug has been marked as a duplicate of bug 13799 *** Created attachment 42041 [details] [review] Bug 13920: API Authentication, part 1: API keys management in interface Depends on Bug 14539 and Bug 7174. This introduces the concept of API keys for use in the new REST API. A key is a string of 32 alphanumerical characters (32 is purely arbitrary, it can be changed easily). A user can have multiple keys (unlimited at the moment) Keys can be generated automatically, and then we have the possibility to delete or revoke each one individually. ApiKeys can be easily accessed using the Koha::ApiKeys-package. Includes unit tests and selenium integration tests for Intra and OPAC. Test plan: 1/ Go to staff interface 2/ Go to a borrower page 3/ In toolbar, click on More -> Manage API keys 4/ Click on "Generate new key" multiple times, check that they are correctly displayed under the button, and they are active by default 5/ Revoke some keys, check that they are not active anymore 6/ Delete some keys, check that they disappear from table 7/ Go to opac interface, log in 8/ In your user account pages, you now have a new tab to the left "your API keys". Click on it. 9/ Repeat steps 4-6 Created attachment 42042 [details] [review] Bug 13920: API authentication system - Swagtenticator authentication Reads the Swagger2 definitions and defines the API routes and controllers for Mojolicious. Authentiates the API consumer using Koha::Auth::Challenge::RESTV1 with all the necessary details inferred from Swagger2, like permissions. Validates all input to match the Swagger2 definition. Authentication is based on the permissions defined in the Swagger2 definition. Add x-koha-permission to the Operation Object to define needed Koha permissions to access the resource. Eg. "/borrowers/{borrowernumber}": { "get": { "x-mojo-controller": "Koha::REST::V1::Borrowers", "x-koha-permission": { "borrowers": "*" }, "operationId": "getBorrower", "tags": ["borrowers"], Created attachment 42555 [details] [review] Bug 13920: 5.1. API authentication system - Swagtenticator authentication - Replace Swagtenticator with x-around-action -hook. Where are we at with this? I've been thinking about how API keys would be nice... tcohen and ashimema are cooking something as we speak. This patchset cannot depend on bug 14539... that's too much for such a simple feature. Now that bug 20402 is in master, this can be closed. |