legate 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (317) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +345 -0
  4. data/bin/legate +13 -0
  5. data/examples/00_quickstart.rb +51 -0
  6. data/examples/01_simple_agent.rb +105 -0
  7. data/examples/02_multi_tool_agent.rb +140 -0
  8. data/examples/03_custom_tool.rb +93 -0
  9. data/examples/04_agent_instructions.rb +84 -0
  10. data/examples/05_state_and_sessions.rb +91 -0
  11. data/examples/06_callbacks.rb +186 -0
  12. data/examples/07_async_jobs.rb +112 -0
  13. data/examples/08_loop_agent.rb +197 -0
  14. data/examples/09_sequential_workflow.rb +40 -0
  15. data/examples/10_parallel_workflow.rb +34 -0
  16. data/examples/11_agent_delegation.rb +24 -0
  17. data/examples/12_http_client_tool.rb +156 -0
  18. data/examples/13_authentication.rb +220 -0
  19. data/examples/14_mcp_client.rb +154 -0
  20. data/examples/15_mcp_server.rb +79 -0
  21. data/examples/16_webhooks.rb +91 -0
  22. data/examples/README_sequential_agents.md +164 -0
  23. data/examples/advanced/auth/cookie_auth_tool.rb +146 -0
  24. data/examples/advanced/auth/custom_auth_flows_example.rb +626 -0
  25. data/examples/advanced/auth/excon_middleware.rb +317 -0
  26. data/examples/advanced/auth/excon_middleware_auth.rb +399 -0
  27. data/examples/advanced/auth/fiber_auth_example.rb +281 -0
  28. data/examples/advanced/auth/fiber_oidc_example.rb +403 -0
  29. data/examples/advanced/auth/httpbin_bearer_tool.rb +159 -0
  30. data/examples/advanced/auth/oauth2_auth.rb +419 -0
  31. data/examples/advanced/auth/oidc_auth.rb +514 -0
  32. data/examples/advanced/auth/openweather_api.rb +251 -0
  33. data/examples/advanced/auth/openweather_tool.rb +153 -0
  34. data/examples/advanced/auth/query_param_middleware_test.rb +138 -0
  35. data/examples/advanced/auth/service_account.rb +135 -0
  36. data/examples/advanced/auth/test_with_httpbin.rb +202 -0
  37. data/examples/advanced/auth/token_lifecycle_example.rb +428 -0
  38. data/examples/advanced/callback_monitoring.rb +679 -0
  39. data/examples/advanced/mas/fixed_delegation_example.rb +191 -0
  40. data/examples/advanced/mas/loop_workflow.rb +28 -0
  41. data/examples/advanced/mas/mock_planner.rb +77 -0
  42. data/examples/advanced/mas/proper_delegation_example.rb +276 -0
  43. data/examples/advanced/mcp/legate_mcp_server_resource_example.rb +182 -0
  44. data/examples/advanced/mcp/mcp_resource_server_example.rb +309 -0
  45. data/examples/advanced/mcp/mcp_server_async.rb +76 -0
  46. data/examples/advanced/mcp/mcp_server_async_tools.rb +122 -0
  47. data/examples/advanced/mcp/mcp_server_legate_agent.rb +95 -0
  48. data/examples/advanced/mcp/mcp_server_rack.rb +89 -0
  49. data/examples/advanced/random_calculator.rb +104 -0
  50. data/examples/advanced/sleep_agent.rb +153 -0
  51. data/examples/advanced/webhooks/webhook_e2e_runner.rb +110 -0
  52. data/examples/advanced/webhooks/webhook_receiver_agent.rb +58 -0
  53. data/examples/advanced/workflows/task_refinement_loop_agent.rb +278 -0
  54. data/examples/advanced/workflows/travel_planner_auto_sequential.rb +444 -0
  55. data/examples/advanced/workflows/travel_planner_parallel.rb +656 -0
  56. data/examples/advanced/workflows/travel_planner_sequential.rb +512 -0
  57. data/examples/tools/oauth2_example.rb +136 -0
  58. data/examples/tools/sleepy_tool.rb +42 -0
  59. data/lib/legate/activity_log.rb +71 -0
  60. data/lib/legate/agent.rb +959 -0
  61. data/lib/legate/agent_code_generator.rb +185 -0
  62. data/lib/legate/agent_definition.rb +812 -0
  63. data/lib/legate/agentic/decision.rb +49 -0
  64. data/lib/legate/agentic/loop.rb +134 -0
  65. data/lib/legate/agentic.rb +5 -0
  66. data/lib/legate/agents/loop_agent.rb +248 -0
  67. data/lib/legate/agents/parallel_agent.rb +163 -0
  68. data/lib/legate/agents/sequential_agent.rb +190 -0
  69. data/lib/legate/agents.rb +14 -0
  70. data/lib/legate/auth/config.rb +148 -0
  71. data/lib/legate/auth/coordinator.rb +218 -0
  72. data/lib/legate/auth/coordinators/oauth2_coordinator.rb +99 -0
  73. data/lib/legate/auth/coordinators/oidc_coordinator.rb +68 -0
  74. data/lib/legate/auth/coordinators/service_account_coordinator.rb +122 -0
  75. data/lib/legate/auth/credential.rb +157 -0
  76. data/lib/legate/auth/encryption.rb +108 -0
  77. data/lib/legate/auth/error.rb +94 -0
  78. data/lib/legate/auth/exchanged_credential.rb +180 -0
  79. data/lib/legate/auth/excon_middleware.rb +285 -0
  80. data/lib/legate/auth/http_client_utils.rb +364 -0
  81. data/lib/legate/auth/manager.rb +531 -0
  82. data/lib/legate/auth/manager_store.rb +394 -0
  83. data/lib/legate/auth/middleware_factory.rb +290 -0
  84. data/lib/legate/auth/runner.rb +279 -0
  85. data/lib/legate/auth/scheme.rb +125 -0
  86. data/lib/legate/auth/schemes/api_key.rb +212 -0
  87. data/lib/legate/auth/schemes/google_service_account.rb +108 -0
  88. data/lib/legate/auth/schemes/http_bearer.rb +98 -0
  89. data/lib/legate/auth/schemes/oauth2.rb +396 -0
  90. data/lib/legate/auth/schemes/openid_connect.rb +346 -0
  91. data/lib/legate/auth/schemes/service_account.rb +388 -0
  92. data/lib/legate/auth/schemes.rb +40 -0
  93. data/lib/legate/auth/token_manager.rb +362 -0
  94. data/lib/legate/auth/token_store.rb +86 -0
  95. data/lib/legate/auth/tool_context_extension.rb +97 -0
  96. data/lib/legate/auth/tool_integration.rb +188 -0
  97. data/lib/legate/auth/url_guard.rb +81 -0
  98. data/lib/legate/auth.rb +453 -0
  99. data/lib/legate/callbacks/callback_context.rb +71 -0
  100. data/lib/legate/cli/agent_commands.rb +950 -0
  101. data/lib/legate/cli/auth_commands.rb +520 -0
  102. data/lib/legate/cli/base_command.rb +24 -0
  103. data/lib/legate/cli/deployment_commands.rb +934 -0
  104. data/lib/legate/cli/output_helper.rb +108 -0
  105. data/lib/legate/cli/session_commands.rb +138 -0
  106. data/lib/legate/cli/skaffold_commands.rb +223 -0
  107. data/lib/legate/cli/tool_commands.rb +261 -0
  108. data/lib/legate/cli/web_commands.rb +182 -0
  109. data/lib/legate/cli.rb +40 -0
  110. data/lib/legate/configuration/webhooks.rb +113 -0
  111. data/lib/legate/configuration.rb +39 -0
  112. data/lib/legate/definition_store.rb +23 -0
  113. data/lib/legate/errors.rb +118 -0
  114. data/lib/legate/event.rb +161 -0
  115. data/lib/legate/gemini_ai_beta_patch.rb +39 -0
  116. data/lib/legate/generators/agent_generator.rb +412 -0
  117. data/lib/legate/generators/code_validator.rb +48 -0
  118. data/lib/legate/generators/legate/install_generator.rb +35 -0
  119. data/lib/legate/generators/legate/templates/create_legate_tables.rb.tt +36 -0
  120. data/lib/legate/generators/legate/templates/initializer.rb +18 -0
  121. data/lib/legate/generators/runtime_tool_loader.rb +76 -0
  122. data/lib/legate/generators/tool_generator.rb +408 -0
  123. data/lib/legate/generators.rb +11 -0
  124. data/lib/legate/global_definition_registry.rb +506 -0
  125. data/lib/legate/global_tool_manager.rb +135 -0
  126. data/lib/legate/llm/adapter.rb +69 -0
  127. data/lib/legate/llm/gemini.rb +172 -0
  128. data/lib/legate/llm/ollama.rb +80 -0
  129. data/lib/legate/llm.rb +34 -0
  130. data/lib/legate/mcp/client.rb +320 -0
  131. data/lib/legate/mcp/connection/sse.rb +292 -0
  132. data/lib/legate/mcp/connection/stdio.rb +273 -0
  133. data/lib/legate/mcp/connection_manager.rb +103 -0
  134. data/lib/legate/mcp/server/legate_agent_adapter.rb +170 -0
  135. data/lib/legate/mcp/server/legate_direct_agent_adapter.rb +140 -0
  136. data/lib/legate/mcp/server/legate_tool_adapter.rb +119 -0
  137. data/lib/legate/mcp/tool_wrapper.rb +138 -0
  138. data/lib/legate/mcp/util/schema_converter.rb +134 -0
  139. data/lib/legate/mcp.rb +23 -0
  140. data/lib/legate/plan_executor.rb +375 -0
  141. data/lib/legate/planner.rb +839 -0
  142. data/lib/legate/rails/railtie.rb +43 -0
  143. data/lib/legate/rails.rb +9 -0
  144. data/lib/legate/redaction.rb +32 -0
  145. data/lib/legate/session.rb +299 -0
  146. data/lib/legate/session_service/active_record.rb +300 -0
  147. data/lib/legate/session_service/base.rb +68 -0
  148. data/lib/legate/session_service/event_broadcast.rb +74 -0
  149. data/lib/legate/session_service/in_memory.rb +188 -0
  150. data/lib/legate/tool/metadata_dsl.rb +122 -0
  151. data/lib/legate/tool.rb +276 -0
  152. data/lib/legate/tool_code_generator.rb +103 -0
  153. data/lib/legate/tool_context.rb +350 -0
  154. data/lib/legate/tool_loader.rb +39 -0
  155. data/lib/legate/tool_registry.rb +73 -0
  156. data/lib/legate/tool_result.rb +61 -0
  157. data/lib/legate/tools/agent_tool.rb +187 -0
  158. data/lib/legate/tools/base/http_client.rb +319 -0
  159. data/lib/legate/tools/base/safe_url.rb +56 -0
  160. data/lib/legate/tools/base_async_job_tool.rb +91 -0
  161. data/lib/legate/tools/calculator.rb +89 -0
  162. data/lib/legate/tools/cat_facts.rb +81 -0
  163. data/lib/legate/tools/check_job_status_tool.rb +48 -0
  164. data/lib/legate/tools/current_time_tool.rb +64 -0
  165. data/lib/legate/tools/echo.rb +43 -0
  166. data/lib/legate/tools/http_request_tool.rb +105 -0
  167. data/lib/legate/tools/random_number_tool.rb +64 -0
  168. data/lib/legate/tools/read_webpage_tool.rb +92 -0
  169. data/lib/legate/tools/sleepy_tool.rb +74 -0
  170. data/lib/legate/tools/webhook_tool.rb +146 -0
  171. data/lib/legate/version.rb +5 -0
  172. data/lib/legate/web/app.rb +984 -0
  173. data/lib/legate/web/public/css/main.css +4980 -0
  174. data/lib/legate/web/public/images/favicon-256.png +0 -0
  175. data/lib/legate/web/public/images/favicon-32.png +0 -0
  176. data/lib/legate/web/public/images/legate-logo-dark.png +0 -0
  177. data/lib/legate/web/public/images/legate-logo-light.png +0 -0
  178. data/lib/legate/web/public/js/legate.js +616 -0
  179. data/lib/legate/web/public/styles/main.scss +4402 -0
  180. data/lib/legate/web/routes/agent_authentication_routes.rb +530 -0
  181. data/lib/legate/web/routes/agent_definition_routes.rb +803 -0
  182. data/lib/legate/web/routes/agent_generator_routes.rb +80 -0
  183. data/lib/legate/web/routes/agent_interaction_routes.rb +734 -0
  184. data/lib/legate/web/routes/agent_runtime_routes.rb +323 -0
  185. data/lib/legate/web/routes/api_routes.rb +56 -0
  186. data/lib/legate/web/routes/authentication_routes.rb +1541 -0
  187. data/lib/legate/web/routes/core_routes.rb +111 -0
  188. data/lib/legate/web/routes/documentation_routes.rb +220 -0
  189. data/lib/legate/web/routes/tool_generator_routes.rb +81 -0
  190. data/lib/legate/web/routes/tools_ui_routes.rb +207 -0
  191. data/lib/legate/web/sass_compiler.rb +73 -0
  192. data/lib/legate/web/views/_active_session_info.slim +25 -0
  193. data/lib/legate/web/views/_activity_list.slim +55 -0
  194. data/lib/legate/web/views/_agent_card.slim +56 -0
  195. data/lib/legate/web/views/_agent_generator_modal.slim +382 -0
  196. data/lib/legate/web/views/_agent_status_controls.slim +71 -0
  197. data/lib/legate/web/views/_agent_tool_table.slim +74 -0
  198. data/lib/legate/web/views/_chat_message.slim +95 -0
  199. data/lib/legate/web/views/_display_agent_configuration.slim +26 -0
  200. data/lib/legate/web/views/_display_agent_description.slim +11 -0
  201. data/lib/legate/web/views/_display_agent_fallback.slim +15 -0
  202. data/lib/legate/web/views/_display_agent_hierarchy.slim +93 -0
  203. data/lib/legate/web/views/_display_agent_instruction.slim +17 -0
  204. data/lib/legate/web/views/_display_agent_mcp.slim +13 -0
  205. data/lib/legate/web/views/_display_agent_model.slim +17 -0
  206. data/lib/legate/web/views/_display_agent_name.slim +42 -0
  207. data/lib/legate/web/views/_display_agent_output_key.slim +26 -0
  208. data/lib/legate/web/views/_display_agent_type.slim +65 -0
  209. data/lib/legate/web/views/_edit_agent_configuration.slim +74 -0
  210. data/lib/legate/web/views/_edit_agent_description.slim +16 -0
  211. data/lib/legate/web/views/_edit_agent_fallback.slim +25 -0
  212. data/lib/legate/web/views/_edit_agent_hierarchy.slim +98 -0
  213. data/lib/legate/web/views/_edit_agent_instruction.slim +49 -0
  214. data/lib/legate/web/views/_edit_agent_mcp.slim +33 -0
  215. data/lib/legate/web/views/_edit_agent_model.slim +23 -0
  216. data/lib/legate/web/views/_edit_agent_output_key.slim +36 -0
  217. data/lib/legate/web/views/_edit_agent_tools.slim +40 -0
  218. data/lib/legate/web/views/_edit_agent_type.slim +67 -0
  219. data/lib/legate/web/views/_session_error.slim +4 -0
  220. data/lib/legate/web/views/_skeleton.slim +69 -0
  221. data/lib/legate/web/views/_tool_card.slim +9 -0
  222. data/lib/legate/web/views/_tool_generator_modal.slim +311 -0
  223. data/lib/legate/web/views/agent.slim +436 -0
  224. data/lib/legate/web/views/agent_auth.slim +562 -0
  225. data/lib/legate/web/views/agents.slim +369 -0
  226. data/lib/legate/web/views/auth.slim +112 -0
  227. data/lib/legate/web/views/auth_credential_detail.slim +327 -0
  228. data/lib/legate/web/views/auth_credentials.slim +261 -0
  229. data/lib/legate/web/views/auth_debug.slim +94 -0
  230. data/lib/legate/web/views/auth_mapping_detail.slim +151 -0
  231. data/lib/legate/web/views/auth_mapping_new.slim +123 -0
  232. data/lib/legate/web/views/auth_mappings.slim +120 -0
  233. data/lib/legate/web/views/auth_scheme_detail.slim +274 -0
  234. data/lib/legate/web/views/auth_schemes.slim +259 -0
  235. data/lib/legate/web/views/auth_test.slim +418 -0
  236. data/lib/legate/web/views/chat.slim +192 -0
  237. data/lib/legate/web/views/docs_index.slim +105 -0
  238. data/lib/legate/web/views/docs_show.slim +105 -0
  239. data/lib/legate/web/views/error_404.slim +5 -0
  240. data/lib/legate/web/views/index.slim +148 -0
  241. data/lib/legate/web/views/layout.slim +144 -0
  242. data/lib/legate/web/views/tool_detail.slim +87 -0
  243. data/lib/legate/web/views/tools.slim +50 -0
  244. data/lib/legate/web/webhook_listener.rb +367 -0
  245. data/lib/legate/web.rb +9 -0
  246. data/lib/legate.rb +220 -0
  247. data/public/docs/advanced/callbacks.md +828 -0
  248. data/public/docs/advanced/mcp_schema_conversion.md +59 -0
  249. data/public/docs/authentication/api_reference/config.md +210 -0
  250. data/public/docs/authentication/api_reference/credential.md +246 -0
  251. data/public/docs/authentication/api_reference/encryption.md +218 -0
  252. data/public/docs/authentication/api_reference/exchanged_credential.md +271 -0
  253. data/public/docs/authentication/api_reference/excon_middleware.md +175 -0
  254. data/public/docs/authentication/api_reference/index.md +30 -0
  255. data/public/docs/authentication/api_reference/scheme.md +250 -0
  256. data/public/docs/authentication/api_reference/schemes/api_key.md +175 -0
  257. data/public/docs/authentication/api_reference/schemes/google_service_account.md +221 -0
  258. data/public/docs/authentication/api_reference/schemes/http_bearer.md +169 -0
  259. data/public/docs/authentication/api_reference/schemes/oauth2.md +343 -0
  260. data/public/docs/authentication/api_reference/schemes/oidc.md +73 -0
  261. data/public/docs/authentication/api_reference/schemes/openid_connect.md +311 -0
  262. data/public/docs/authentication/api_reference/schemes/service_account.md +287 -0
  263. data/public/docs/authentication/api_reference/token_manager.md +221 -0
  264. data/public/docs/authentication/api_reference/token_store.md +146 -0
  265. data/public/docs/authentication/api_reference/tool_context_extension.md +166 -0
  266. data/public/docs/authentication/guides/api_key.md +190 -0
  267. data/public/docs/authentication/guides/bearer.md +172 -0
  268. data/public/docs/authentication/guides/configuration.md +255 -0
  269. data/public/docs/authentication/guides/custom_flow.md +523 -0
  270. data/public/docs/authentication/guides/index.md +24 -0
  271. data/public/docs/authentication/guides/migration.md +435 -0
  272. data/public/docs/authentication/guides/oauth2.md +252 -0
  273. data/public/docs/authentication/guides/oidc.md +241 -0
  274. data/public/docs/authentication/guides/overview.md +155 -0
  275. data/public/docs/authentication/guides/secure_storage.md +301 -0
  276. data/public/docs/authentication/guides/service_account.md +228 -0
  277. data/public/docs/authentication/guides/token_lifecycle.md +295 -0
  278. data/public/docs/authentication/guides/web_ui_integration.md +504 -0
  279. data/public/docs/authentication/index.md +58 -0
  280. data/public/docs/authentication/troubleshooting/credential_storage.md +550 -0
  281. data/public/docs/authentication/troubleshooting/environment_variables.md +540 -0
  282. data/public/docs/authentication/troubleshooting/index.md +11 -0
  283. data/public/docs/authentication/troubleshooting/oauth2_issues.md +220 -0
  284. data/public/docs/authentication/troubleshooting/oidc_issues.md +412 -0
  285. data/public/docs/authentication/troubleshooting/token_refresh.md +338 -0
  286. data/public/docs/cli/legate_cli_usage.md +363 -0
  287. data/public/docs/core_concepts/legate_agent_lifecycle.md +124 -0
  288. data/public/docs/core_concepts/legate_architecture_overview.md +110 -0
  289. data/public/docs/core_concepts/legate_configuration.md +116 -0
  290. data/public/docs/core_concepts/legate_definition_store.md +102 -0
  291. data/public/docs/core_concepts/legate_planner.md +94 -0
  292. data/public/docs/core_concepts/legate_session_service.md +104 -0
  293. data/public/docs/error_handling/legate_error_handling.md +122 -0
  294. data/public/docs/examples.md +199 -0
  295. data/public/docs/getting_started.md +111 -0
  296. data/public/docs/guides/agentic_agents.md +137 -0
  297. data/public/docs/guides/ai_code_generators.md +437 -0
  298. data/public/docs/guides/auto_loading.md +326 -0
  299. data/public/docs/guides/configuring_agent_webhooks.md +219 -0
  300. data/public/docs/guides/http_client_usage.md +264 -0
  301. data/public/docs/guides/llm_providers.md +137 -0
  302. data/public/docs/guides/mcp_client_integration.md +232 -0
  303. data/public/docs/guides/mcp_server_exposure.md +206 -0
  304. data/public/docs/guides/rails_integration.md +128 -0
  305. data/public/docs/guides/sending_outbound_webhooks.md +227 -0
  306. data/public/docs/guides/streaming.md +112 -0
  307. data/public/docs/guides/webhooks.md +288 -0
  308. data/public/docs/introduction.md +51 -0
  309. data/public/docs/multi_agent_systems/advanced_features.md +57 -0
  310. data/public/docs/multi_agent_systems/agent_delegation.md +190 -0
  311. data/public/docs/multi_agent_systems/agent_hierarchy.md +49 -0
  312. data/public/docs/multi_agent_systems/state_management.md +47 -0
  313. data/public/docs/multi_agent_systems/workflow_agents.md +72 -0
  314. data/public/docs/tools/legate_built_in_tools.md +332 -0
  315. data/public/docs/tools/legate_tools_and_registry.md +263 -0
  316. data/public/docs/web_ui/legate_web_ui.md +137 -0
  317. metadata +823 -0
@@ -0,0 +1,338 @@
1
+ # Token Refresh Problems
2
+
3
+ This guide addresses common issues encountered when refreshing authentication tokens in the Legate Ruby library.
4
+
5
+ ## Common Token Refresh Issues
6
+
7
+ ### Token Expires Too Quickly
8
+
9
+ **Symptoms:**
10
+ - Tokens expire before their expected lifetime
11
+ - Frequent re-authentication prompts
12
+ - Log messages about token expiration
13
+
14
+ **Possible Causes and Solutions:**
15
+
16
+ 1. **Clock Skew**
17
+ ```ruby
18
+ # Problem: Your server's clock is out of sync with the provider's clock
19
+
20
+ # Solution: Sync your server time with NTP
21
+ # On Linux: sudo ntpdate time.google.com
22
+ # On macOS: sudo sntp -sS time.apple.com
23
+ ```
24
+
25
+ 2. **Incorrect Expiration Calculation**
26
+ ```ruby
27
+ # Problem: The token's expires_in value is misinterpreted
28
+
29
+ # Check how the token's expiration is calculated
30
+ token = Legate::Auth::ExchangedCredential.new(
31
+ auth_type: :oauth2,
32
+ access_token: 'access-token',
33
+ expires_in: 3600 # Seconds from creation time
34
+ )
35
+
36
+ # Verify the expected expiration time
37
+ puts "Token expires at: #{token.expires_at}"
38
+ ```
39
+
40
+ 3. **Buffer Too Large**
41
+ ```ruby
42
+ # Problem: The refresh buffer is too large, triggering refresh too early
43
+
44
+ # Solution: Adjust the refresh buffer to a smaller value
45
+ token_manager = Legate::Auth::TokenManager.new(token_store, {
46
+ refresh_buffer: 30 # Seconds (default is 60)
47
+ })
48
+ ```
49
+
50
+ ### Token Refresh Fails
51
+
52
+ **Symptoms:**
53
+ - "Invalid refresh token" errors
54
+ - Authentication errors after token expiration
55
+ - Failed API calls after some time period
56
+
57
+ **Possible Causes and Solutions:**
58
+
59
+ 1. **Expired Refresh Token**
60
+ ```ruby
61
+ # Problem: The refresh token itself has expired
62
+
63
+ # Solution: Request a new refresh token with offline access
64
+ scheme = Legate::Auth::Schemes::OAuth2.new(
65
+ authorization_url: 'https://auth.example.com/authorize',
66
+ token_url: 'https://auth.example.com/token',
67
+ scopes: ['profile', 'email'],
68
+ additional_params: {
69
+ 'access_type' => 'offline', # For Google
70
+ 'prompt' => 'consent' # Force a new refresh token
71
+ }
72
+ )
73
+ ```
74
+
75
+ 2. **Token Revoked by Provider**
76
+ ```ruby
77
+ # Problem: The provider has revoked the refresh token
78
+
79
+ # Solution: Check token revocation events in the provider's admin console
80
+ # Most providers have an audit log or token management interface
81
+ ```
82
+
83
+ 3. **Connection Issues**
84
+ ```ruby
85
+ # Problem: Network issues prevent reaching the token endpoint
86
+
87
+ # Solution: Add retry logic
88
+ token_manager = Legate::Auth::TokenManager.new(token_store, {
89
+ retry_max_attempts: 5, # Increase max retries (default: 3)
90
+ retry_delay: 3, # Seconds between retries (default: 2)
91
+ retry_backoff: 2.0 # Backoff multiplier (default: 1.5)
92
+ })
93
+ ```
94
+
95
+ 4. **Token Not Stored Correctly**
96
+ ```ruby
97
+ # Problem: The refresh token isn't being stored properly
98
+
99
+ # Solution: Verify the token store is working
100
+ token_store = Legate::Auth::TokenStore.new(session)
101
+ token_store.store(cache_key, token)
102
+ stored_token = token_store.get(cache_key)
103
+
104
+ # Check if the refresh token is present
105
+ puts "Refresh token preserved: #{stored_token[:refresh_token] == token[:refresh_token]}"
106
+ ```
107
+
108
+ ### OAuth2 Specific Refresh Issues
109
+
110
+ **Symptoms:**
111
+ - "Invalid grant" errors during refresh
112
+ - "Invalid client" errors
113
+ - Refresh succeeds but access_token doesn't work
114
+
115
+ **Possible Causes and Solutions:**
116
+
117
+ 1. **Incorrect Client Authentication**
118
+ ```ruby
119
+ # Problem: Client authentication method is incorrect
120
+
121
+ # Solution: Check if the provider expects client auth in header or body
122
+ credential = Legate::Auth::Credential.new(
123
+ auth_type: :oauth2,
124
+ client_id: ENV['CLIENT_ID'],
125
+ client_secret: ENV['CLIENT_SECRET'],
126
+ additional_params: {
127
+ 'client_authentication' => 'body' # Or 'header'
128
+ }
129
+ )
130
+ ```
131
+
132
+ 2. **Refresh Token Rotation**
133
+ ```ruby
134
+ # Problem: The provider issues a new refresh token with each use
135
+
136
+ # Solution: Update the stored token after each refresh
137
+ token_manager.on(:refresh_success) do |data|
138
+ # The TokenManager already stores the new token (callbacks receive a Hash)
139
+ puts "Token refreshed successfully with new refresh token"
140
+ end
141
+ ```
142
+
143
+ 3. **Scope Mismatch**
144
+ ```ruby
145
+ # Problem: Requested scopes don't match the original authorization
146
+
147
+ # Solution: Ensure consistency in scope requests
148
+ scheme = Legate::Auth::Schemes::OAuth2.new(
149
+ authorization_url: 'https://auth.example.com/authorize',
150
+ token_url: 'https://auth.example.com/token',
151
+ scopes: ['profile', 'email'] # Same scopes as original auth
152
+ )
153
+ ```
154
+
155
+ ### Service Account Refresh Issues
156
+
157
+ **Symptoms:**
158
+ - JWT creation or exchange failures
159
+ - Token refresh works initially but fails later
160
+ - Permission errors after successful token acquisition
161
+
162
+ **Possible Causes and Solutions:**
163
+
164
+ 1. **Service Account Key Rotation**
165
+ ```ruby
166
+ # Problem: The service account key has been rotated
167
+
168
+ # Solution: Update your stored service account key
169
+ credential = Legate::Auth::Credential.new(
170
+ auth_type: :service_account,
171
+ service_account_key: File.read('updated-service-account-key.json') # raw JSON string
172
+ )
173
+ ```
174
+
175
+ 2. **JWT Signing Issues**
176
+ ```ruby
177
+ # Problem: JWT signing failures due to algorithm mismatch
178
+
179
+ # Solution: Verify the key format and algorithm
180
+ # Most service accounts use RS256 algorithm by default
181
+ ```
182
+
183
+ 3. **Permission Changes**
184
+ ```ruby
185
+ # Problem: The service account permissions have been changed
186
+
187
+ # Solution: Check IAM permissions in your cloud provider
188
+ # Verify the service account still has access to requested scopes
189
+ ```
190
+
191
+ ## Debugging Techniques
192
+
193
+ ### Monitoring Token Lifecycle
194
+
195
+ Use callbacks to monitor the token lifecycle:
196
+
197
+ Each callback receives a single data Hash with keys such as `:event`, `:token`, `:scheme`, `:credential` (and `:error` for `:refresh_failure`).
198
+
199
+ ```ruby
200
+ # Register callbacks for token lifecycle events
201
+ token_manager.on(:refresh_success) do |data|
202
+ token = data[:token]
203
+ puts "Token refreshed successfully"
204
+ puts "New access token: #{token[:access_token].to_s[0..10]}... (truncated)"
205
+ puts "New expires_at: #{token[:expires_at]}"
206
+ end
207
+
208
+ token_manager.on(:refresh_failure) do |data|
209
+ puts "Token refresh failed: #{data[:error]&.message}"
210
+ puts "Token scheme: #{data[:scheme]&.scheme_type}"
211
+ # Log details for debugging
212
+ end
213
+
214
+ token_manager.on(:before_expiry) do |data|
215
+ token = data[:token]
216
+ puts "Token approaching expiration, expires at: #{token[:expires_at]}"
217
+ puts "Current time: #{Time.now}"
218
+ puts "Seconds until expiry: #{token[:expires_at] - Time.now}"
219
+ end
220
+ ```
221
+
222
+ ### Inspecting Token Contents
223
+
224
+ For debugging token contents:
225
+
226
+ ```ruby
227
+ # For JWT tokens (ID tokens, access tokens in some cases)
228
+ require 'jwt'
229
+
230
+ # Decode without verification (for debugging only!)
231
+ token_payload = JWT.decode(access_token, nil, false)[0]
232
+ puts "Token claims: #{token_payload.inspect}"
233
+
234
+ # Check critical fields
235
+ puts "Issued at: #{Time.at(token_payload['iat'])}"
236
+ puts "Expires at: #{Time.at(token_payload['exp'])}"
237
+ puts "Audience: #{token_payload['aud']}"
238
+ puts "Issuer: #{token_payload['iss']}"
239
+ ```
240
+
241
+ ### Testing Token Refresh Manually
242
+
243
+ To manually test token refresh:
244
+
245
+ ```ruby
246
+ # Force a token refresh
247
+ token = token_manager.get_token(scheme, credential, force_refresh: true)
248
+ if token
249
+ puts "Token refresh successful"
250
+ puts "New access token: #{token[:access_token].to_s[0..10]}... (truncated)"
251
+ puts "New expires_at: #{token.expires_at}"
252
+ else
253
+ puts "Token refresh failed"
254
+ end
255
+ ```
256
+
257
+ ## Provider-Specific Issues
258
+
259
+ ### Google OAuth2/Service Account
260
+
261
+ - **Refresh Token Expiration**: Google refresh tokens expire if unused for 6 months
262
+ - **Project Restrictions**: Check API quotas and restrictions in Google Cloud Console
263
+ - **Domain-Wide Delegation**: For service accounts, verify proper delegation is configured
264
+
265
+ ### Microsoft Azure
266
+
267
+ - **Token Lifetime Policies**: Check Azure AD token lifetime policy configurations
268
+ - **Conditional Access**: Verify if conditional access policies affect token refresh
269
+ - **App Registration Changes**: Check for changes in app registrations that might affect tokens
270
+
271
+ ### Auth0
272
+
273
+ - **Refresh Token Rotation**: Auth0 can be configured to rotate refresh tokens
274
+ - **Refresh Token Expiration**: Auth0 can set explicit refresh token expiry
275
+ - **Rate Limiting**: Check if you're hitting Auth0 rate limits during refresh
276
+
277
+ ## Advanced Solutions
278
+
279
+ ### Implementing Refresh Token Rotation
280
+
281
+ If your provider issues new refresh tokens on each refresh:
282
+
283
+ ```ruby
284
+ token_manager.on(:refresh_success) do |data|
285
+ # The new refresh token is already stored in the token
286
+ new_refresh_token = data[:token][:refresh_token]
287
+
288
+ # You can perform additional actions here if needed
289
+ log_refresh_token_rotation(data[:credential][:client_id], Time.now)
290
+ end
291
+ ```
292
+
293
+ ### Handling Multiple Auth Types
294
+
295
+ For applications with multiple authentication types:
296
+
297
+ ```ruby
298
+ # Create different token managers or use the same one
299
+ oauth_token_manager = Legate::Auth::TokenManager.new(token_store)
300
+ service_account_token_manager = Legate::Auth::TokenManager.new(token_store)
301
+
302
+ # Get tokens for different auth types
303
+ oauth_token = oauth_token_manager.get_token(oauth_scheme, oauth_credential)
304
+ sa_token = service_account_token_manager.get_token(sa_scheme, sa_credential)
305
+ ```
306
+
307
+ ### Fallback Authentication
308
+
309
+ Implement fallback authentication when refresh fails:
310
+
311
+ ```ruby
312
+ token = token_manager.get_token(scheme, credential)
313
+ if token.nil?
314
+ # Token refresh failed, trigger re-authentication
315
+ # For OAuth2/OIDC, this means restarting the authorization flow
316
+ initiate_oauth_flow(scheme, credential)
317
+ end
318
+ ```
319
+
320
+ ## When to Contact Support
321
+
322
+ If you've tried all the solutions and still encounter issues:
323
+
324
+ 1. **Provider Support**: Contact your OAuth provider's support with:
325
+ - Error messages and timestamps
326
+ - Client ID (but never share client secrets)
327
+ - Token response data (sanitized)
328
+
329
+ 2. **Legate Support**: File an issue with:
330
+ - Legate version information
331
+ - Reproduction steps
332
+ - Error logs
333
+ - Provider information
334
+
335
+ ## Next Steps
336
+
337
+ - [OAuth2 Troubleshooting](./oauth2_issues): For OAuth2-specific authentication issues
338
+ - [OpenID Connect Issues](./oidc_issues): For OIDC-specific authentication issues