{"id":25907964,"url":"https://github.com/ivan-montes/auth-and-user","last_synced_at":"2026-06-08T17:31:10.197Z","repository":{"id":280093237,"uuid":"940965932","full_name":"Ivan-Montes/auth-and-user","owner":"Ivan-Montes","description":"When gRPC met Spring... but also Hexagonal Arch, Authorization Server and JWT. The system allows users to register, create categories, products, and leave opinions, reviews, and votes.","archived":false,"fork":false,"pushed_at":"2025-03-31T05:46:34.000Z","size":395,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-31T06:28:20.513Z","etag":null,"topics":["grpc","java","jwt","spring"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Ivan-Montes.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-03-01T06:43:49.000Z","updated_at":"2025-03-31T05:48:46.000Z","dependencies_parsed_at":"2025-03-16T09:18:41.955Z","dependency_job_id":"4571669a-1d6c-4fde-acd1-48ee62058312","html_url":"https://github.com/Ivan-Montes/auth-and-user","commit_stats":null,"previous_names":["ivan-montes/auth-and-user"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Ivan-Montes/auth-and-user","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ivan-Montes%2Fauth-and-user","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ivan-Montes%2Fauth-and-user/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ivan-Montes%2Fauth-and-user/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ivan-Montes%2Fauth-and-user/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Ivan-Montes","download_url":"https://codeload.github.com/Ivan-Montes/auth-and-user/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ivan-Montes%2Fauth-and-user/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34073650,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["grpc","java","jwt","spring"],"created_at":"2025-03-03T07:15:57.862Z","updated_at":"2026-06-08T17:31:10.193Z","avatar_url":"https://github.com/Ivan-Montes.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# auth-and-user\n\nWhen gRPC met Spring... but also Hexagonal Arch, Authorization Server and JWT. The system allows users to register, create categories, products, and leave opinions, reviews, and votes.\n\n**Components**\n- [Kafka](https://kafka.apache.org/) [9092] + [9093] \n- Eureka server as service registry and discovery service [8761]\n- Authorization Server (the-grpc-autho) [9000] + [9001]\n- gRPC Server the-grpc-user-pack [0]\n- gRPC Server the-grpc-opinator [0]\n\n\n## Table of contents\n\n- [Installation](#installation)\n- [Usage](#usage)\n- [It's not a bug, it's a feature](#features)\n- [Maintainers](#maintainers)\n- [License](#license)\n\n\n## Installation\n\n#### First steps\n\n1. As usual, please clone or download the project.\n\n1. Inside the main folder, you could find a docker-compose yaml file.\n\n1. From there use the command line to start the project\n\n```    \n    **Developer mode**  \n    docker-compose -f docker-compose-dev.yml up -d\n\n```\n      \nThe dev environment is ready for using with your IDE. The microservice attempts to communicate with Kafka using the local host. \n   \n4. You could stop the project and free resources with any of this orders\n\n```\n    **Developer mode**\n    docker-compose -f docker-compose-dev.yml down --rmi local -v\n    \n```\n5. It is important to have [grpcurl](https://github.com/fullstorydev/grpcurl) to call gRPC services in your system. \n  \n#### About certificates\n\nThe communication between the gRPC server and clients is secure thanks to SSL certificates. The document  located at the root project, certificates.md, and the explanation on [grpc-ecosystem](https://grpc-ecosystem.github.io/grpc-spring/en/server/security.html) could clarify you how it works. \n     \n     \n## Usage\n\n#### Initial considerations\n\n- In your IDE, you should always follow this order to run microservices. First Discovery service, then the-grpc-autho, the-grpc-user-pack, and finally the-grpc-opinator.\n- In the project, when using [grpcurl](https://github.com/fullstorydev/grpcurl), **it is mandatory to send a certificate with the command.** For convenience the same certificate is used for all services and is located in the folder `certificates` within each module, except for the discovery server. \n- Additionally, some gRPC methods require including a JWT token with the request. If this constraint is configured, you could revise it in the `GrpcConfig` class, under the `dev.ime.common.config` package in that module\n\n| Module | Service | Method | Token JWT Required|\n|-----|-----|-----|-----|\n| the-grpc-opinator | ReviewGrpcService | CreateReview | X |\n| the-grpc-opinator | ReviewGrpcService | UpdateReview | X | \n| the-grpc-opinator | ReviewGrpcService | DeleteReview | X | \n| the-grpc-opinator | VoteGrpcService | CreateVote | X | \n| the-grpc-opinator | VoteGrpcService | UpdateVote | X | \n| the-grpc-opinator | VoteGrpcService | DeleteVote | X | \n\n- To learn more about each gRPC service methods simply revise its .proto file under `src.main.proto` folder. An alternative approach is to run against the microservice the following commands, adjusting the port as needed:\n\n```\ngrpcurl -cacert ./ca.crt localhost:9001 list\ngrpcurl -cacert ./ca.crt localhost:9001 describe\n```\n\n#### Register\n\n- In the first place you should register an user using the suitable gRPC method. Here is an example of the command you need to send:\n\n```\ngrpcurl -cacert ./ca.crt -d '{\"name\":\"Momo\",\"lastname\":\"Ayase\",\"email\":\"momo@ayase.tk\",\"password\":\"12345\"}' localhost:9001 net.proto.AuthGrpcService.CreateUser\n```\n- Next, since form-based login authorization is active, we need to use a browser. Navigate to `http://localhost:9000/login` and use the credentials you have just created.\n- If the authentication is successful, you will be redirected to the success page where you can request an **authorization code**.\n\n#### Request Token\n\nA good way for knowing more about the JWT generation and validation flow, is reading [this article](https://adictosaltrabajo.com/2023/06/29/securizacion-aplicacion-oauth-2-spring-authorization-server-spring-resource-server/). Otherwise you can follow these steps:\n\n- From the success page, push the button `Request Auth Code`. The authorization server will respond with a code, which the client can exchange for tokens over a secure channel.\n- We use the POST method to request our JWT token sending the authorization code and the rest of parameters\n\n\u003cimg src=\"./src/main/resources/static/images/request_token_conf.png\" style=\"width: 800px; max-width: 1024px; flex-grow: 1;\" /\u003e\n\n\u0026nbsp;\n\n- Now we can use the retrieved JWT token with the tool [grpcurl](https://github.com/fullstorydev/grpcurl) when necessary\n\nYou can find a [SoapUI](https://www.soapui.org/) profile with the request token order configured at the root folder.\n  \n#### Main operations\n\nYou can use [grpcurl](https://github.com/fullstorydev/grpcurl) to call gRPC services by selecting the appropriate port. **Since the port is random, you will need to adjust the examples accordingly**. The main operations in the project are managed by `the-grpc-opinator` microservice, so the following commands are for it. Remember to request and update the token too.\n\n```   \n- Category endpoint examples\n\ngrpcurl -cacert ./ca.crt -d '{\"categoryName\":\"Grocery\"}' localhost:50051 net.proto.CategoryGrpcService.CreateCategory\ngrpcurl -cacert ./ca.crt -d '{\"categoryId\":\"1\", \"categoryName\":\"Vegetables\"}' localhost:50051 net.proto.CategoryGrpcService.UpdateCategory\ngrpcurl -cacert ./ca.crt -d '{\"categoryId\":\"1\"}' localhost:50051 net.proto.CategoryGrpcService.DeleteCategory\ngrpcurl -cacert ./ca.crt localhost:50051 net.proto.CategoryGrpcService.ListCategories\ngrpcurl -cacert ./ca.crt -d '{\"page\":0, \"size\":2, \"sortBy\":\"categoryName\", \"sortDir\":\"DESC\"}' localhost:50051 net.proto.CategoryGrpcService.ListCategoriesPaginated\ngrpcurl -cacert ./ca.crt -d '{\"categoryId\":\"1\"}' localhost:50051 net.proto.CategoryGrpcService.GetCategory\n\n- Product endpoint examples\n\ngrpcurl -cacert ./ca.crt localhost:50051 describe net.proto.ProductGrpcService\ngrpcurl -cacert ./ca.crt -d '{\"productName\":\"Lettuce\", \"productDescription\":\"green\", \"categoryId\":\"1\"}' localhost:50051 net.proto.ProductGrpcService.CreateProduct\ngrpcurl -cacert ./ca.crt -d '{\"productId\":\"1\", \"productName\":\"Tomatoes\", \"productDescription\":\"full of red\", \"categoryId\":\"1\"}' localhost:50051 net.proto.ProductGrpcService.UpdateProduct\ngrpcurl -cacert ./ca.crt -d '{\"productId\":\"1\"}' localhost:50051 net.proto.ProductGrpcService.DeleteProduct\ngrpcurl -cacert ./ca.crt localhost:50051 net.proto.ProductGrpcService.ListProducts\ngrpcurl -cacert ./ca.crt -d '{\"page\":0, \"size\":2, \"sortBy\":\"productName\", \"sortDir\":\"DESC\"}' localhost:50051 net.proto.ProductGrpcService.ListProductsPaginated\ngrpcurl -cacert ./ca.crt -d '{\"productId\":\"1\"}' localhost:50051 net.proto.ProductGrpcService.GetProduct\n\n- Review endpoint examples\n\ngrpcurl -cacert ./ca.crt -H \"Authorization: Bearer eyJraWQiOiIwYTU0ZTg2Ny1hMjViLTQ4Y2QtOTdjZC0wMGFhZWY0NjRiMTYiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJsaXphQGxpemEuanAiLCJhdWQiOiJjbGllbnQiLCJuYmYiOjE3NDAzODMwNTAsInNjb3BlIjpbIm9wZW5pZCJdLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjkwMDAiLCJleHAiOjE3NDAzODQ4NTAsImlhdCI6MTc0MDM4MzA1MCwianRpIjoiMGQxYjZiMmYtYmU2Yy00Mzk1LWE3ZTQtNzU5NTFhNzAxMDJhIn0.e8fRyXi_W1ek3thgKuZoJxmdjFYQkNnH2p-IbqRdyDzWw9I1FNnq5Q85K-uUGB75Y2xJrBy9zB4m6dEn74_z3ijsaxa_1XNWwT-zVH0PnJJwuow2p-ZKFdnoDbV2A0hRCrk87YfYKEZqNqQlkfxo7iJzqpZX-6MOG-b4b-Cik1uaqkTx4kFYcssu3b7bqu6OcSKknPz1RNgitG2s-N3SrIC17rWkDMBtqvhToe0mwzQwD2bn-V52HbIzYyMAzTK0PlwwserH_Wj0Wg7osqRGvo2IHspLNTZYyBwpAgOOwN-KMvvx77mBZZ-M7HUTQDHK7RZQrzkOuOE96Gg882sTiA\" -d '{\"productId\":\"1\", \"reviewText\":\"Medium\", \"rating\":\"3\"}' localhost:50051 net.proto.ReviewGrpcService.CreateReview\ngrpcurl -cacert ./ca.crt -H \"Authorization: Bearer eyJraWQiOiIwYTU0ZTg2Ny1hMjViLTQ4Y2QtOTdjZC0wMGFhZWY0NjRiMTYiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJsaXphQGxpemEuanAiLCJhdWQiOiJjbGllbnQiLCJuYmYiOjE3NDAzODMwNTAsInNjb3BlIjpbIm9wZW5pZCJdLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjkwMDAiLCJleHAiOjE3NDAzODQ4NTAsImlhdCI6MTc0MDM4MzA1MCwianRpIjoiMGQxYjZiMmYtYmU2Yy00Mzk1LWE3ZTQtNzU5NTFhNzAxMDJhIn0.e8fRyXi_W1ek3thgKuZoJxmdjFYQkNnH2p-IbqRdyDzWw9I1FNnq5Q85K-uUGB75Y2xJrBy9zB4m6dEn74_z3ijsaxa_1XNWwT-zVH0PnJJwuow2p-ZKFdnoDbV2A0hRCrk87YfYKEZqNqQlkfxo7iJzqpZX-6MOG-b4b-Cik1uaqkTx4kFYcssu3b7bqu6OcSKknPz1RNgitG2s-N3SrIC17rWkDMBtqvhToe0mwzQwD2bn-V52HbIzYyMAzTK0PlwwserH_Wj0Wg7osqRGvo2IHspLNTZYyBwpAgOOwN-KMvvx77mBZZ-M7HUTQDHK7RZQrzkOuOE96Gg882sTiA\" -d '{\"reviewId\":\"1\", \"reviewText\":\"Awesome\", \"rating\":\"4\"}' localhost:50051 net.proto.ReviewGrpcService.UpdateReview\ngrpcurl -cacert ./ca.crt -H \"Authorization: Bearer eyJraWQiOiIwYTU0ZTg2Ny1hMjViLTQ4Y2QtOTdjZC0wMGFhZWY0NjRiMTYiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJsaXphQGxpemEuanAiLCJhdWQiOiJjbGllbnQiLCJuYmYiOjE3NDAzODMwNTAsInNjb3BlIjpbIm9wZW5pZCJdLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjkwMDAiLCJleHAiOjE3NDAzODQ4NTAsImlhdCI6MTc0MDM4MzA1MCwianRpIjoiMGQxYjZiMmYtYmU2Yy00Mzk1LWE3ZTQtNzU5NTFhNzAxMDJhIn0.e8fRyXi_W1ek3thgKuZoJxmdjFYQkNnH2p-IbqRdyDzWw9I1FNnq5Q85K-uUGB75Y2xJrBy9zB4m6dEn74_z3ijsaxa_1XNWwT-zVH0PnJJwuow2p-ZKFdnoDbV2A0hRCrk87YfYKEZqNqQlkfxo7iJzqpZX-6MOG-b4b-Cik1uaqkTx4kFYcssu3b7bqu6OcSKknPz1RNgitG2s-N3SrIC17rWkDMBtqvhToe0mwzQwD2bn-V52HbIzYyMAzTK0PlwwserH_Wj0Wg7osqRGvo2IHspLNTZYyBwpAgOOwN-KMvvx77mBZZ-M7HUTQDHK7RZQrzkOuOE96Gg882sTiA\" -d '{\"reviewId\":\"1\"}' localhost:50051 net.proto.ReviewGrpcService.DeleteReview\ngrpcurl -cacert ./ca.crt localhost:50051 net.proto.ReviewGrpcService.ListReviews\ngrpcurl -cacert ./ca.crt -d '{\"page\":0, \"size\":2, \"sortBy\":\"reviewId\", \"sortDir\":\"DESC\"}' localhost:50051 net.proto.ReviewGrpcService.ListReviewsPaginated\ngrpcurl -cacert ./ca.crt -d '{\"reviewId\":\"1\"}' localhost:50051 net.proto.ReviewGrpcService.GetReview\n\n- Vote endpoint examples\n\ngrpcurl -cacert ./ca.crt -H \"Authorization: Bearer eyJraWQiOiIwYTU0ZTg2Ny1hMjViLTQ4Y2QtOTdjZC0wMGFhZWY0NjRiMTYiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJsaXphQGxpemEuanAiLCJhdWQiOiJjbGllbnQiLCJuYmYiOjE3NDAzODMwNTAsInNjb3BlIjpbIm9wZW5pZCJdLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjkwMDAiLCJleHAiOjE3NDAzODQ4NTAsImlhdCI6MTc0MDM4MzA1MCwianRpIjoiMGQxYjZiMmYtYmU2Yy00Mzk1LWE3ZTQtNzU5NTFhNzAxMDJhIn0.e8fRyXi_W1ek3thgKuZoJxmdjFYQkNnH2p-IbqRdyDzWw9I1FNnq5Q85K-uUGB75Y2xJrBy9zB4m6dEn74_z3ijsaxa_1XNWwT-zVH0PnJJwuow2p-ZKFdnoDbV2A0hRCrk87YfYKEZqNqQlkfxo7iJzqpZX-6MOG-b4b-Cik1uaqkTx4kFYcssu3b7bqu6OcSKknPz1RNgitG2s-N3SrIC17rWkDMBtqvhToe0mwzQwD2bn-V52HbIzYyMAzTK0PlwwserH_Wj0Wg7osqRGvo2IHspLNTZYyBwpAgOOwN-KMvvx77mBZZ-M7HUTQDHK7RZQrzkOuOE96Gg882sTiA\" -d '{\"reviewId\":\"1\", \"useful\":\"true\"}' localhost:50051 net.proto.VoteGrpcService.CreateVote\ngrpcurl -cacert ./ca.crt -H \"Authorization: Bearer eyJraWQiOiIwYTU0ZTg2Ny1hMjViLTQ4Y2QtOTdjZC0wMGFhZWY0NjRiMTYiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJsaXphQGxpemEuanAiLCJhdWQiOiJjbGllbnQiLCJuYmYiOjE3NDAzODMwNTAsInNjb3BlIjpbIm9wZW5pZCJdLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjkwMDAiLCJleHAiOjE3NDAzODQ4NTAsImlhdCI6MTc0MDM4MzA1MCwianRpIjoiMGQxYjZiMmYtYmU2Yy00Mzk1LWE3ZTQtNzU5NTFhNzAxMDJhIn0.e8fRyXi_W1ek3thgKuZoJxmdjFYQkNnH2p-IbqRdyDzWw9I1FNnq5Q85K-uUGB75Y2xJrBy9zB4m6dEn74_z3ijsaxa_1XNWwT-zVH0PnJJwuow2p-ZKFdnoDbV2A0hRCrk87YfYKEZqNqQlkfxo7iJzqpZX-6MOG-b4b-Cik1uaqkTx4kFYcssu3b7bqu6OcSKknPz1RNgitG2s-N3SrIC17rWkDMBtqvhToe0mwzQwD2bn-V52HbIzYyMAzTK0PlwwserH_Wj0Wg7osqRGvo2IHspLNTZYyBwpAgOOwN-KMvvx77mBZZ-M7HUTQDHK7RZQrzkOuOE96Gg882sTiA\" -d '{\"voteId\":\"1\", \"useful\":\"false\"}' localhost:50051 net.proto.VoteGrpcService.UpdateVote\ngrpcurl -cacert ./ca.crt -H \"Authorization: Bearer eyJraWQiOiIwYTU0ZTg2Ny1hMjViLTQ4Y2QtOTdjZC0wMGFhZWY0NjRiMTYiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJsaXphQGxpemEuanAiLCJhdWQiOiJjbGllbnQiLCJuYmYiOjE3NDAzODMwNTAsInNjb3BlIjpbIm9wZW5pZCJdLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjkwMDAiLCJleHAiOjE3NDAzODQ4NTAsImlhdCI6MTc0MDM4MzA1MCwianRpIjoiMGQxYjZiMmYtYmU2Yy00Mzk1LWE3ZTQtNzU5NTFhNzAxMDJhIn0.e8fRyXi_W1ek3thgKuZoJxmdjFYQkNnH2p-IbqRdyDzWw9I1FNnq5Q85K-uUGB75Y2xJrBy9zB4m6dEn74_z3ijsaxa_1XNWwT-zVH0PnJJwuow2p-ZKFdnoDbV2A0hRCrk87YfYKEZqNqQlkfxo7iJzqpZX-6MOG-b4b-Cik1uaqkTx4kFYcssu3b7bqu6OcSKknPz1RNgitG2s-N3SrIC17rWkDMBtqvhToe0mwzQwD2bn-V52HbIzYyMAzTK0PlwwserH_Wj0Wg7osqRGvo2IHspLNTZYyBwpAgOOwN-KMvvx77mBZZ-M7HUTQDHK7RZQrzkOuOE96Gg882sTiA\" -d '{\"voteId\":\"1\"}' localhost:50051 net.proto.VoteGrpcService.DeleteVote\ngrpcurl -cacert ./ca.crt localhost:50051 net.proto.VoteGrpcService.ListVotes\ngrpcurl -cacert ./ca.crt -d '{\"page\":0, \"size\":2, \"sortBy\":\"voteId\", \"sortDir\":\"DESC\"}' localhost:50051 net.proto.VoteGrpcService.ListVotesPaginated\ngrpcurl -cacert ./ca.crt -d '{\"voteId\":\"1\"}' localhost:50051 net.proto.VoteGrpcService.GetVote\n      \n```\n \n\n## Features\n\n#### :arrow_forward: Secure gRPC communications with SSL encryption\n\n#### :arrow_forward: JWT token-based authorization for secure access\n\n#### :arrow_forward: Comprehensive unit testing for business logic classes\n\n\n\n## Maintainers\n\nJust me, [Iván](https://github.com/Ivan-Montes) :sweat_smile:\n\n\n## License\n\n[GPLv3 license](https://choosealicense.com/licenses/gpl-3.0/)\n\n\n---\n\n\n[![Java](https://badgen.net/static/JavaSE/21/orange)](https://www.java.com/es/)\n[![Maven](https://badgen.net/badge/icon/maven?icon=maven\u0026label\u0026color=red)](https://https://maven.apache.org/)\n[![Spring](https://img.shields.io/badge/spring-blue?logo=Spring\u0026logoColor=white)](https://spring.io)\n[![GitHub](https://badgen.net/badge/icon/github?icon=github\u0026label)](https://github.com)\n[![Eclipse](https://badgen.net/badge/icon/eclipse?icon=eclipse\u0026label)](https://https://eclipse.org/)\n[![SonarQube](https://badgen.net/badge/icon/sonarqube?icon=sonarqube\u0026label\u0026color=purple)](https://www.sonarsource.com/products/sonarqube/downloads/)\n[![Docker](https://badgen.net/badge/icon/docker?icon=docker\u0026label)](https://www.docker.com/)\n[![Kafka](https://badgen.net/static/Apache/Kafka/cyan)](https://kafka.apache.org/)\n[![GPLv3 license](https://badgen.net/static/License/GPLv3/blue)](https://choosealicense.com/licenses/gpl-3.0/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivan-montes%2Fauth-and-user","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fivan-montes%2Fauth-and-user","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivan-montes%2Fauth-and-user/lists"}