{"id":25563450,"url":"https://github.com/manojkrgupta/small_bank","last_synced_at":"2026-02-09T06:35:14.519Z","repository":{"id":277796275,"uuid":"850223250","full_name":"manojkrgupta/small_bank","owner":"manojkrgupta","description":"An example of Python3 FastAPI, Keycloak and MongoDb with a story of a Banking Application.","archived":false,"fork":false,"pushed_at":"2025-02-16T06:35:34.000Z","size":25,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-08-08T19:26:53.714Z","etag":null,"topics":["api","fastapi","iam","keycloak","mongodb","oauth2","python"],"latest_commit_sha":null,"homepage":"https://www.linkedin.com/pulse/example-python3-fastapi-keycloak-mongodb-manojkumar-gupta-s3tef/?trackingId=CTSjxCcrQ6O8unk%2FjhFWjQ%3D%3D","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/manojkrgupta.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"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":"2024-08-31T07:27:45.000Z","updated_at":"2025-02-16T06:35:38.000Z","dependencies_parsed_at":"2025-02-16T07:34:28.465Z","dependency_job_id":null,"html_url":"https://github.com/manojkrgupta/small_bank","commit_stats":null,"previous_names":["manojkrgupta/small_bank"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/manojkrgupta/small_bank","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/manojkrgupta%2Fsmall_bank","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/manojkrgupta%2Fsmall_bank/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/manojkrgupta%2Fsmall_bank/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/manojkrgupta%2Fsmall_bank/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/manojkrgupta","download_url":"https://codeload.github.com/manojkrgupta/small_bank/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/manojkrgupta%2Fsmall_bank/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29258245,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-09T04:11:57.159Z","status":"ssl_error","status_checked_at":"2026-02-09T04:11:56.117Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["api","fastapi","iam","keycloak","mongodb","oauth2","python"],"created_at":"2025-02-20T20:19:55.802Z","updated_at":"2026-02-09T06:35:14.504Z","avatar_url":"https://github.com/manojkrgupta.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"### Summary\n* An example of Python3 FastAPI, Keycloak and MongoDB. \n* Keycloak takes care of accounts, access, permissions, privileges and session management, letting the application code very light and yet secured.\n* And yes, MongoDB supports atomic operations -- letting the logic to \"check and debit (and also audit)\" to work as one operation -- ensuring data integrity.\n\n### Plan\n* The plan is to relinquish authentication from code and give it to standard IAM tools like keycloak.\n* User account management, Profile management, Roles, Group, Permissions etc all are moved to keycloak.\n* The plan is also to demonstrate Python3 FastAPI integration with keycloak and MongoDB. \n\n### Story\n* In this example, we are trying to show a Banking application.\n* Allow Banks to create accounts (user accounts)\n* Allow Users to add fund and withdraw (debit, credit)\n* In this example, we have two types of Role:\n  * Role = bank_teller:\n    * for every bank there will be a user like (icici_teller) belonging to this role.\n    * This role/user will be able to create account(users account) for new customer.\n    * This role/user can see deposits in account.\n    * But, will not be able to add or withdraw from account.\n  * Role = account_owner:\n      * This is a general bank account user role. Example bob and charlie\n      * This role/user will be able to add and/or withdraw from his/her account.\n      * This role/user will be able to see fund balance in his/her account.\n* We also have two Groups:\n  * Group = hdfc:\n    * User list: charlie, hdfc_teller\n  * Group = icici:\n    * User list: bob, icici_teller\n\n### Tabular Summary of URI, Method, Keycloak Role and Keycloak Users having permissions\n\n| Present URL                | Method | Description                        | Allowed by Roles | Users having this permission |\n|----------------------------|--------|------------------------------------|------------------|------------------------------|\n| /bank_user/{bank}          | GET    | to see balance                     | account_owner    | bob, charlie                 |\n| /bank_user/{bank}          | PUT    | to transact (credit or debit)      | account_owner    | bob, charlie                 |\n| /bank_teller/{bank}/{user} | PUT    | to create account for user in bank | bank_teller      | icici_teller, hdfc_teller    |\n| /bank_teller/{bank}/{user} | GET    | to get balance for every account   | bank_teller      | icici_teller, hdfc_teller    |\n\n### System dependencies\n* You need python3 version 3.10+.\n* And, you need to install necessary libraries by using command `python3 -m pip install -r requirements.txt`\n\n### Start environment\n```\n]$ cd docker/\n]$ mkdir keycloak_data\n]$ mkdir mongodb_data\n]$ sudo docker login\n]$ sudo docker compose -f docker_compose_keycloak_mongodb.yml --env-file docker_compose_env up\n```\n\n### URL\n* MongoDB web  -- http://localhost:8084\n* Keycloak     -- http://localhost:8085\n* Application  -- http://localhost:8086\n\n### Ensure mongodb is initialised (Below is a method from shell. You can also login to MongoDB web)\n* You will see database named=small_banks is auto created\n* You will see collection named=banks.hdfc and banks.icici is also auto created\n```\n]$ sudo docker exec -it mongodb bash\nroot@mongodb:/# mongosh -u admin -p \nEnter password: \u003cget_password_from_file docker_compose_env\u003e\n\ntest\u003e show dbs\n...\nsmall_banks   24.00 KiB\ntest\u003e \n\ntest\u003e use small_banks\nswitched to db small_banks\n\nsmall_banks\u003e show collections\nbanks.hdfc\nbanks.icici\nsmall_banks\u003e\nsmall_banks\u003e db.banks.hdfc.find({})\nsmall_banks\u003e db.banks.icici.find({})\nsmall_banks\u003e\n```\n\n### Initialise keycloak\n* go to keycloak http://127.0.0.1:8085/\n* login with admin (password in file=docker/docker_compose_env)\n* Select Keycloak drop down from top left -\u003e Create realm -\u003e Browser -\u003e Select file docker/small_bank_init_keycloak.json -\u003e Create\n* After this you will see, below objects are auto created\n  * realm   = small_bank \n  * client  = sm:api\n  * user    = bob           (role=account_owner, group=icici)   default password=password\n  * user    = charlie       (role=account_owner, group=hdfc)    default password=password\n  * user    = icici_teller  (role=bank_teller  , group=icici)   default password=password\n  * user    = hdfc_teller   (role=bank_teller  , group=hdfc)    default password=password\n  \n### Start application\n```\n]$ cd bin\n]$ uvicorn main:app --log-level debug --port 8086 --host 127.0.0.1 --reload\n```\n\n### First API call\n* Before users can use their account, bank teller needs to create account for bob and charlie \n* Go to http://127.0.0.1:8086/docs\n  * Authenticate as icici_teller\n  * Extend PUT /bank_teller/{bank}/{user}\n  * Try, giving bank=icici, user=bob\n* Now logout, restart browser or clear session for icici_teller from keycloak admin page\n  * And, Authenticate as hdfc_teller\n  * Extend PUT /bank_teller/{bank}/{user}\n  * Try, giving bank=hdfc, user=charlie\n\n### Note (warning|caution): \n  * In keycloak, bob belongs to group=icici and charlie belongs to group=hdfc\n  * hence, we choose icici_teller to create bobs account\n  * and, hdfc_teller to create charlie account\n  * incase, icici_teller also creates account for charlie -- then charlie will have two accounts in both the banks\n    * But, to use icici account, charlie will need to be also added in keycloak group=icici\n\n### Test 1 -- Authenticate as bob(or charlie) and check balance\n* GET    /bank_user/{bank}     # for bob use bank=icici, for charlie use bank=hdfc\n\n### Test 2 -- Authenticate as bob(or charlie) and perform credit/debit operation\n* PUT    /bank_user/{bank}     # for bob use bank=icici, for charlie use bank=hdfc\n\n### An example of curl\n```\ncurl -X 'PUT' \\\n'http://127.0.0.1:8086/bank_teller/icici/bob' \\\n-H 'accept: application/json' \\\n-H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJVNm0zNG1rNW1ZVFNpaUpWcE9QTFZERjZpdkhoU094TnAwQ096dXJhRGljIn0.eyJleHAiOjE3MjUwODU0OTksImlhdCI6MTcyNTA4NTE5OSwiYXV0aF90aW1lIjoxNzI1MDg1MTk5LCJqdGkiOiIzY2QxNjRjNy1kMWM4LTQ5ZGUtYTAzMi1hMjYzZWNlMzJlYWUiLCJpc3MiOiJodHRwOi8vMTI3LjAuMC4xOjgwODUvcmVhbG1zL3NtYWxsX2JhbmsiLCJhdWQiOlsic206YXBpIiwiYWNjb3VudCJdLCJzdWIiOiJhNmMyMzliMi1mOWI5LTQ3MzctOTc4NC1lYWNhOTRiYTRiYzYiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJzbTphcGkiLCJzaWQiOiI5NDI4NmZjNS1jOTQ2LTQwYjYtYTFlNC04YWUyYzBhZWY0YWIiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbImh0dHA6Ly8xMjcuMC4wLjE6ODA4NiJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiIsImRlZmF1bHQtcm9sZXMtc21hbGxfYmFuayJdfSwicmVzb3VyY2VfYWNjZXNzIjp7InNtOmFwaSI6eyJyb2xlcyI6WyJiYW5rX3RlbGxlciJdfSwiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoiSUNJQ0kgVGVsbGVyIiwiZ3JvdXBzIjpbIi9pY2ljaSJdLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJpY2ljaV90ZWxsZXIiLCJnaXZlbl9uYW1lIjoiSUNJQ0kiLCJmYW1pbHlfbmFtZSI6IlRlbGxlciIsImVtYWlsIjoidGVsbGVyQGljaWNpLmNvIn0.xi7elqZ2EyfZrqWjkYAJwpHiJJxdUp8hwwhkXdECclkwd7Ds5hjymw6GYS2cy-cNa7Jz9escPYVYV1MyCN5O673FmPiIsnL2CdW4Mqf4236_20Uam71GcZpzSjs4DiYAm8KtsI8ux13FoklF1ou8S9Lml0Xh_XIG2-wq4jNnxxUlrlQMxgRllgEPme7oxIE4oJJkiOmVW2WFQWYeANKa7vhJ7IOe_mmiqzTn39vdGEmijxzfkE5hInmJtzW0-w9D0dTp5ZObAitxbth5-qupCzvgXwRmV-LM1gGNpNbIp7uKr_QdXZqsthpyURBC_KixR9IxN4RGHVeFybDCKUDaYA'\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmanojkrgupta%2Fsmall_bank","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmanojkrgupta%2Fsmall_bank","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmanojkrgupta%2Fsmall_bank/lists"}