feat: add support for OAuth 2.0 discovery, registration, resource indicators, and custom auth#2338
feat: add support for OAuth 2.0 discovery, registration, resource indicators, and custom auth#2338pavelgj wants to merge 23 commits into
Conversation
…icators, and custom auth
There was a problem hiding this comment.
Code Review
This pull request introduces substantial new features to package:oauth2, including support for OAuth 2.0 server discovery, dynamic client registration, resource indicators, and custom client authenticators. However, the implementation has critical security flaws. The discovery mechanism lacks mandatory issuer validation required by RFC 8414, which could allow for issuer spoofing. Additionally, the implementation of resource indicators (RFC 8707) is non-compliant as it incorrectly joins multiple resources into a single parameter, potentially leading to incorrect authorization behavior. Addressing these security issues is crucial. Furthermore, there is a minor suggestion to enhance code readability and null-safety practices.
…d include a test.
…rious OAuth2 flows
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces significant new features to package:oauth2, including support for OAuth 2.0 server discovery, dynamic client registration, resource indicators, and custom client authenticators. While the implementation is generally robust, a critical security issue was identified in the discovery of protected resource metadata. Specifically, the library fails to verify the resource field in the metadata against the resource identifier used for discovery, which is a requirement of RFC 9728 to prevent metadata spoofing. Additionally, my review noted a couple of instances of code duplication in the new logic that could be refactored to improve maintainability.
Package publishing
Documentation at https://github.com/dart-lang/ecosystem/wiki/Publishing-automation. |
PR Health
Coverage
|
| File | Coverage |
|---|---|
| pkgs/oauth2/lib/oauth2.dart | 💔 Not covered |
| pkgs/oauth2/lib/src/authorization_code_grant.dart | 💔 Not covered |
| pkgs/oauth2/lib/src/client.dart | 💔 Not covered |
| pkgs/oauth2/lib/src/client_authenticator.dart | 💔 Not covered |
| pkgs/oauth2/lib/src/client_credentials_grant.dart | 💔 Not covered |
| pkgs/oauth2/lib/src/credentials.dart | 💔 Not covered |
| pkgs/oauth2/lib/src/discovery.dart | 💔 Not covered |
| pkgs/oauth2/lib/src/registration.dart | 💔 Not covered |
| pkgs/oauth2/lib/src/utils.dart | 💔 Not covered |
This check for test coverage is informational (issues shown here will not fail the PR).
This check can be disabled by tagging the PR with skip-coverage-check.
Breaking changes ✔️
| Package | Change | Current Version | New Version | Needed Version | Looking good? |
|---|---|---|---|---|---|
| oauth2 | Non-Breaking | 2.0.5 | 2.1.0 | 2.1.0 | ✔️ |
This check can be disabled by tagging the PR with skip-breaking-check.
Unused Dependencies ✔️
| Package | Status |
|---|---|
| oauth2 | ✔️ All dependencies utilized correctly. |
For details on how to fix these, see dependency_validator.
This check can be disabled by tagging the PR with skip-unused-dependencies-check.
Changelog Entry ✔️
| Package | Changed Files |
|---|
Changes to files need to be accounted for in their respective changelogs.
This check can be disabled by tagging the PR with skip-changelog-check.
License Headers ⚠️
""
| Files |
|---|
| pkgs/oauth2/lib/oauth2.dart |
| pkgs/oauth2/lib/src/authorization_code_grant.dart |
| pkgs/oauth2/lib/src/client.dart |
| pkgs/oauth2/lib/src/client_authenticator.dart |
| pkgs/oauth2/lib/src/client_credentials_grant.dart |
| pkgs/oauth2/lib/src/credentials.dart |
| pkgs/oauth2/lib/src/discovery.dart |
| pkgs/oauth2/lib/src/registration.dart |
| pkgs/oauth2/lib/src/utils.dart |
| pkgs/oauth2/test/discovery_test.dart |
| pkgs/oauth2/test/registration_test.dart |
All source files should start with a license header.
Unrelated files missing license headers
| Files |
|---|
| pkgs/bazel_worker/benchmark/benchmark.dart |
| pkgs/bazel_worker/e2e_test/bin/async_worker.dart |
| pkgs/bazel_worker/e2e_test/bin/async_worker_in_isolate.dart |
| pkgs/bazel_worker/e2e_test/bin/sync_worker.dart |
| pkgs/bazel_worker/e2e_test/lib/async_worker.dart |
| pkgs/bazel_worker/e2e_test/lib/forwards_to_isolate_async_worker.dart |
| pkgs/bazel_worker/e2e_test/lib/sync_worker.dart |
| pkgs/bazel_worker/e2e_test/test/e2e_test.dart |
| pkgs/bazel_worker/example/client.dart |
| pkgs/bazel_worker/example/worker.dart |
| pkgs/bazel_worker/lib/bazel_worker.dart |
| pkgs/bazel_worker/lib/driver.dart |
| pkgs/bazel_worker/lib/src/async_message_grouper.dart |
| pkgs/bazel_worker/lib/src/constants.dart |
| pkgs/bazel_worker/lib/src/driver/driver.dart |
| pkgs/bazel_worker/lib/src/driver/driver_connection.dart |
| pkgs/bazel_worker/lib/src/message_grouper.dart |
| pkgs/bazel_worker/lib/src/message_grouper_state.dart |
| pkgs/bazel_worker/lib/src/sync_message_grouper.dart |
| pkgs/bazel_worker/lib/src/utils.dart |
| pkgs/bazel_worker/lib/src/worker/async_worker_loop.dart |
| pkgs/bazel_worker/lib/src/worker/sync_worker_loop.dart |
| pkgs/bazel_worker/lib/src/worker/worker_connection.dart |
| pkgs/bazel_worker/lib/src/worker/worker_loop.dart |
| pkgs/bazel_worker/lib/testing.dart |
| pkgs/bazel_worker/test/driver_connection_test.dart |
| pkgs/bazel_worker/test/driver_test.dart |
| pkgs/bazel_worker/test/message_grouper_test.dart |
| pkgs/bazel_worker/test/test_all.dart |
| pkgs/bazel_worker/test/worker_loop_test.dart |
| pkgs/benchmark_harness/bin/bench.dart |
| pkgs/benchmark_harness/example/template.dart |
| pkgs/benchmark_harness/integration_test/perf_benchmark_test.dart |
| pkgs/benchmark_harness/lib/benchmark_harness.dart |
| pkgs/benchmark_harness/lib/perf_benchmark_harness.dart |
| pkgs/benchmark_harness/lib/src/async_benchmark_base.dart |
| pkgs/benchmark_harness/lib/src/bench_command/bench_options.dart |
| pkgs/benchmark_harness/lib/src/bench_command/compile_and_run.dart |
| pkgs/benchmark_harness/lib/src/benchmark_base.dart |
| pkgs/benchmark_harness/lib/src/measurement.dart |
| pkgs/benchmark_harness/lib/src/perf_benchmark_base.dart |
| pkgs/benchmark_harness/lib/src/perf_benchmark_base_stub.dart |
| pkgs/benchmark_harness/lib/src/score_emitter.dart |
| pkgs/benchmark_harness/test/bench_command_test.dart |
| pkgs/benchmark_harness/test/benchmark_harness_test.dart |
| pkgs/benchmark_harness/test/result_emitter_test.dart |
| pkgs/boolean_selector/example/example.dart |
| pkgs/boolean_selector/lib/boolean_selector.dart |
| pkgs/boolean_selector/lib/src/all.dart |
| pkgs/boolean_selector/lib/src/ast.dart |
| pkgs/boolean_selector/lib/src/evaluator.dart |
| pkgs/boolean_selector/lib/src/impl.dart |
| pkgs/boolean_selector/lib/src/intersection_selector.dart |
| pkgs/boolean_selector/lib/src/none.dart |
| pkgs/boolean_selector/lib/src/parser.dart |
| pkgs/boolean_selector/lib/src/scanner.dart |
| pkgs/boolean_selector/lib/src/token.dart |
| pkgs/boolean_selector/lib/src/union_selector.dart |
| pkgs/boolean_selector/lib/src/validator.dart |
| pkgs/boolean_selector/lib/src/visitor.dart |
| pkgs/boolean_selector/test/equality_test.dart |
| pkgs/boolean_selector/test/evaluate_test.dart |
| pkgs/boolean_selector/test/parser_test.dart |
| pkgs/boolean_selector/test/scanner_test.dart |
| pkgs/boolean_selector/test/to_string_test.dart |
| pkgs/boolean_selector/test/validate_test.dart |
| pkgs/boolean_selector/test/variables_test.dart |
| pkgs/browser_launcher/example/main.dart |
| pkgs/browser_launcher/lib/browser_launcher.dart |
| pkgs/browser_launcher/lib/src/chrome.dart |
| pkgs/browser_launcher/test/chrome_test.dart |
| pkgs/cli_config/example/bin/cli_config_example.dart |
| pkgs/cli_config/lib/cli_config.dart |
| pkgs/cli_config/lib/src/cli_parser.dart |
| pkgs/cli_config/lib/src/cli_source.dart |
| pkgs/cli_config/lib/src/config.dart |
| pkgs/cli_config/lib/src/environment_parser.dart |
| pkgs/cli_config/lib/src/environment_source.dart |
| pkgs/cli_config/lib/src/file_parser.dart |
| pkgs/cli_config/lib/src/file_source.dart |
| pkgs/cli_config/lib/src/source.dart |
| pkgs/cli_config/test/cli_config_example_test.dart |
| pkgs/cli_config/test/cli_config_test.dart |
| pkgs/cli_config/test/cli_config_windows_test.dart |
| pkgs/cli_config/test/helpers.dart |
| pkgs/cli_util/example/main.dart |
| pkgs/cli_util/lib/cli_logging.dart |
| pkgs/cli_util/lib/cli_util.dart |
| pkgs/cli_util/lib/src/base_directories.dart |
| pkgs/cli_util/test/base_directories_test.dart |
| pkgs/cli_util/test/cli_util_test.dart |
| pkgs/clock/lib/clock.dart |
| pkgs/clock/lib/src/clock.dart |
| pkgs/clock/lib/src/default.dart |
| pkgs/clock/lib/src/stopwatch.dart |
| pkgs/clock/lib/src/utils.dart |
| pkgs/clock/test/clock_test.dart |
| pkgs/clock/test/default_test.dart |
| pkgs/clock/test/stopwatch_test.dart |
| pkgs/clock/test/utils.dart |
| pkgs/code_builder/example/example.dart |
| pkgs/code_builder/lib/code_builder.dart |
| pkgs/code_builder/lib/src/allocator.dart |
| pkgs/code_builder/lib/src/base.dart |
| pkgs/code_builder/lib/src/emitter.dart |
| pkgs/code_builder/lib/src/matchers.dart |
| pkgs/code_builder/lib/src/mixins/annotations.dart |
| pkgs/code_builder/lib/src/mixins/dartdoc.dart |
| pkgs/code_builder/lib/src/mixins/generics.dart |
| pkgs/code_builder/lib/src/specs/class.dart |
| pkgs/code_builder/lib/src/specs/code.dart |
| pkgs/code_builder/lib/src/specs/constructor.dart |
| pkgs/code_builder/lib/src/specs/directive.dart |
| pkgs/code_builder/lib/src/specs/enum.dart |
| pkgs/code_builder/lib/src/specs/expression.dart |
| pkgs/code_builder/lib/src/specs/expression/binary.dart |
| pkgs/code_builder/lib/src/specs/expression/closure.dart |
| pkgs/code_builder/lib/src/specs/expression/code.dart |
| pkgs/code_builder/lib/src/specs/expression/invoke.dart |
| pkgs/code_builder/lib/src/specs/expression/literal.dart |
| pkgs/code_builder/lib/src/specs/expression/parenthesized.dart |
| pkgs/code_builder/lib/src/specs/extension.dart |
| pkgs/code_builder/lib/src/specs/extension_type.dart |
| pkgs/code_builder/lib/src/specs/field.dart |
| pkgs/code_builder/lib/src/specs/library.dart |
| pkgs/code_builder/lib/src/specs/method.dart |
| pkgs/code_builder/lib/src/specs/mixin.dart |
| pkgs/code_builder/lib/src/specs/reference.dart |
| pkgs/code_builder/lib/src/specs/type_function.dart |
| pkgs/code_builder/lib/src/specs/type_record.dart |
| pkgs/code_builder/lib/src/specs/type_reference.dart |
| pkgs/code_builder/lib/src/specs/typedef.dart |
| pkgs/code_builder/lib/src/visitors.dart |
| pkgs/code_builder/test/allocator_test.dart |
| pkgs/code_builder/test/common.dart |
| pkgs/code_builder/test/const_test.dart |
| pkgs/code_builder/test/directive_test.dart |
| pkgs/code_builder/test/e2e/injection_test.dart |
| pkgs/code_builder/test/matcher_test.dart |
| pkgs/code_builder/test/specs/class_test.dart |
| pkgs/code_builder/test/specs/code/expression_test.dart |
| pkgs/code_builder/test/specs/code/statement_test.dart |
| pkgs/code_builder/test/specs/enum_test.dart |
| pkgs/code_builder/test/specs/extension_test.dart |
| pkgs/code_builder/test/specs/extension_type_test.dart |
| pkgs/code_builder/test/specs/field_test.dart |
| pkgs/code_builder/test/specs/library_test.dart |
| pkgs/code_builder/test/specs/method_test.dart |
| pkgs/code_builder/test/specs/mixin_test.dart |
| pkgs/code_builder/test/specs/record_type_test.dart |
| pkgs/code_builder/test/specs/type_reference_test.dart |
| pkgs/coverage/benchmark/many_isolates.dart |
| pkgs/coverage/bin/collect_coverage.dart |
| pkgs/coverage/bin/format_coverage.dart |
| pkgs/coverage/bin/run_and_collect.dart |
| pkgs/coverage/bin/test_with_coverage.dart |
| pkgs/coverage/lib/coverage.dart |
| pkgs/coverage/lib/src/chrome.dart |
| pkgs/coverage/lib/src/collect.dart |
| pkgs/coverage/lib/src/coverage_options.dart |
| pkgs/coverage/lib/src/coverage_percentage.dart |
| pkgs/coverage/lib/src/formatter.dart |
| pkgs/coverage/lib/src/hitmap.dart |
| pkgs/coverage/lib/src/isolate_paused_listener.dart |
| pkgs/coverage/lib/src/resolver.dart |
| pkgs/coverage/lib/src/run_and_collect.dart |
| pkgs/coverage/lib/src/util.dart |
| pkgs/coverage/test/chrome_test.dart |
| pkgs/coverage/test/collect_coverage_api_test.dart |
| pkgs/coverage/test/collect_coverage_config_test.dart |
| pkgs/coverage/test/collect_coverage_mock_test.dart |
| pkgs/coverage/test/collect_coverage_test.dart |
| pkgs/coverage/test/config_file_locator_test.dart |
| pkgs/coverage/test/coverage_percentage_test.dart |
| pkgs/coverage/test/filter_ignored_test.dart |
| pkgs/coverage/test/format_coverage_test.dart |
| pkgs/coverage/test/function_coverage_test.dart |
| pkgs/coverage/test/isolate_paused_listener_test.dart |
| pkgs/coverage/test/lcov_test.dart |
| pkgs/coverage/test/resolver_test.dart |
| pkgs/coverage/test/run_and_collect_test.dart |
| pkgs/coverage/test/test_files/function_coverage_app.dart |
| pkgs/coverage/test/test_files/test_app.dart |
| pkgs/coverage/test/test_files/test_app_isolate.dart |
| pkgs/coverage/test/test_files/test_library.dart |
| pkgs/coverage/test/test_files/test_library_part.dart |
| pkgs/coverage/test/test_util.dart |
| pkgs/coverage/test/test_with_coverage_package/lib/validate_lib.dart |
| pkgs/coverage/test/test_with_coverage_package/test/evaluate_test.dart |
| pkgs/coverage/test/test_with_coverage_package/test/product_test.dart |
| pkgs/coverage/test/test_with_coverage_package/test/sum_test.dart |
| pkgs/coverage/test/test_with_coverage_test.dart |
| pkgs/coverage/test/util_test.dart |
| pkgs/csslib/example/main.dart |
| pkgs/csslib/lib/src/analyzer.dart |
| pkgs/csslib/lib/src/css_printer.dart |
| pkgs/csslib/lib/src/messages.dart |
| pkgs/csslib/lib/src/polyfill.dart |
| pkgs/csslib/lib/src/preprocessor_options.dart |
| pkgs/csslib/lib/src/property.dart |
| pkgs/csslib/lib/src/token.dart |
| pkgs/csslib/lib/src/token_kind.dart |
| pkgs/csslib/lib/src/tokenizer.dart |
| pkgs/csslib/lib/src/tree.dart |
| pkgs/csslib/lib/src/tree_base.dart |
| pkgs/csslib/lib/src/tree_printer.dart |
| pkgs/csslib/lib/src/validate.dart |
| pkgs/csslib/lib/visitor.dart |
| pkgs/csslib/test/big_1_test.dart |
| pkgs/csslib/test/color_test.dart |
| pkgs/csslib/test/debug_test.dart |
| pkgs/csslib/test/declaration_test.dart |
| pkgs/csslib/test/error_test.dart |
| pkgs/csslib/test/escape_codes_test.dart |
| pkgs/csslib/test/extend_test.dart |
| pkgs/csslib/test/keyframes_test.dart |
| pkgs/csslib/test/mixin_test.dart |
| pkgs/csslib/test/nested_test.dart |
| pkgs/csslib/test/repros_test.dart |
| pkgs/csslib/test/selector_test.dart |
| pkgs/csslib/test/testing.dart |
| pkgs/csslib/test/third_party_samples_test.dart |
| pkgs/csslib/test/var_test.dart |
| pkgs/csslib/test/visitor_test.dart |
| pkgs/extension_discovery/example/hello_world/lib/hello_world.dart |
| pkgs/extension_discovery/example/hello_world_app/bin/hello.dart |
| pkgs/extension_discovery/lib/extension_discovery.dart |
| pkgs/extension_discovery/lib/src/expect_json.dart |
| pkgs/extension_discovery/lib/src/io.dart |
| pkgs/extension_discovery/lib/src/package_config.dart |
| pkgs/extension_discovery/lib/src/registry.dart |
| pkgs/extension_discovery/lib/src/yaml_config_format.dart |
| pkgs/extension_discovery/test/find_extensions_test.dart |
| pkgs/extension_discovery/test/integration_test.dart |
| pkgs/extension_discovery/test/package_config_test.dart |
| pkgs/extension_discovery/test/test_descriptor.dart |
| pkgs/extension_discovery/test/yaml_config_format_test.dart |
| pkgs/file/example/main.dart |
| pkgs/file/lib/chroot.dart |
| pkgs/file/lib/file.dart |
| pkgs/file/lib/local.dart |
| pkgs/file/lib/memory.dart |
| pkgs/file/lib/src/backends/chroot.dart |
| pkgs/file/lib/src/backends/chroot/chroot_directory.dart |
| pkgs/file/lib/src/backends/chroot/chroot_file.dart |
| pkgs/file/lib/src/backends/chroot/chroot_file_system.dart |
| pkgs/file/lib/src/backends/chroot/chroot_file_system_entity.dart |
| pkgs/file/lib/src/backends/chroot/chroot_link.dart |
| pkgs/file/lib/src/backends/chroot/chroot_random_access_file.dart |
| pkgs/file/lib/src/backends/local.dart |
| pkgs/file/lib/src/backends/local/local_directory.dart |
| pkgs/file/lib/src/backends/local/local_file.dart |
| pkgs/file/lib/src/backends/local/local_file_system.dart |
| pkgs/file/lib/src/backends/local/local_file_system_entity.dart |
| pkgs/file/lib/src/backends/local/local_link.dart |
| pkgs/file/lib/src/backends/memory.dart |
| pkgs/file/lib/src/backends/memory/clock.dart |
| pkgs/file/lib/src/backends/memory/common.dart |
| pkgs/file/lib/src/backends/memory/memory_directory.dart |
| pkgs/file/lib/src/backends/memory/memory_file.dart |
| pkgs/file/lib/src/backends/memory/memory_file_stat.dart |
| pkgs/file/lib/src/backends/memory/memory_file_system.dart |
| pkgs/file/lib/src/backends/memory/memory_file_system_entity.dart |
| pkgs/file/lib/src/backends/memory/memory_link.dart |
| pkgs/file/lib/src/backends/memory/memory_random_access_file.dart |
| pkgs/file/lib/src/backends/memory/node.dart |
| pkgs/file/lib/src/backends/memory/operations.dart |
| pkgs/file/lib/src/backends/memory/style.dart |
| pkgs/file/lib/src/backends/memory/utils.dart |
| pkgs/file/lib/src/common.dart |
| pkgs/file/lib/src/forwarding.dart |
| pkgs/file/lib/src/forwarding/forwarding_directory.dart |
| pkgs/file/lib/src/forwarding/forwarding_file.dart |
| pkgs/file/lib/src/forwarding/forwarding_file_system.dart |
| pkgs/file/lib/src/forwarding/forwarding_file_system_entity.dart |
| pkgs/file/lib/src/forwarding/forwarding_link.dart |
| pkgs/file/lib/src/forwarding/forwarding_random_access_file.dart |
| pkgs/file/lib/src/interface.dart |
| pkgs/file/lib/src/interface/directory.dart |
| pkgs/file/lib/src/interface/error_codes.dart |
| pkgs/file/lib/src/interface/error_codes_dart_io.dart |
| pkgs/file/lib/src/interface/error_codes_internal.dart |
| pkgs/file/lib/src/interface/file.dart |
| pkgs/file/lib/src/interface/file_system.dart |
| pkgs/file/lib/src/interface/file_system_entity.dart |
| pkgs/file/lib/src/interface/link.dart |
| pkgs/file/lib/src/io.dart |
| pkgs/file/test/chroot_test.dart |
| pkgs/file/test/common_tests.dart |
| pkgs/file/test/local_test.dart |
| pkgs/file/test/memory_operations_test.dart |
| pkgs/file/test/memory_test.dart |
| pkgs/file/test/utils.dart |
| pkgs/file/test/utils_test.dart |
| pkgs/file_testing/lib/file_testing.dart |
| pkgs/file_testing/lib/src/testing/core_matchers.dart |
| pkgs/file_testing/lib/src/testing/internal.dart |
| pkgs/glob/lib/glob.dart |
| pkgs/glob/lib/list_local_fs.dart |
| pkgs/glob/lib/src/ast.dart |
| pkgs/glob/lib/src/list_tree.dart |
| pkgs/glob/lib/src/parser.dart |
| pkgs/glob/lib/src/stream_pool.dart |
| pkgs/glob/lib/src/utils.dart |
| pkgs/glob/test/glob_test.dart |
| pkgs/glob/test/list_test.dart |
| pkgs/glob/test/match_test.dart |
| pkgs/glob/test/parse_test.dart |
| pkgs/graphs/benchmark/connected_components_benchmark.dart |
| pkgs/graphs/benchmark/shortest_path_benchmark.dart |
| pkgs/graphs/benchmark/shortest_path_worst_case_benchmark.dart |
| pkgs/graphs/example/crawl_async_example.dart |
| pkgs/graphs/example/example.dart |
| pkgs/graphs/lib/graphs.dart |
| pkgs/graphs/lib/src/crawl_async.dart |
| pkgs/graphs/lib/src/cycle_exception.dart |
| pkgs/graphs/lib/src/shortest_path.dart |
| pkgs/graphs/lib/src/strongly_connected_components.dart |
| pkgs/graphs/lib/src/topological_sort.dart |
| pkgs/graphs/lib/src/transitive_closure.dart |
| pkgs/graphs/test/crawl_async_test.dart |
| pkgs/graphs/test/shortest_path_test.dart |
| pkgs/graphs/test/strongly_connected_components_test.dart |
| pkgs/graphs/test/topological_sort_test.dart |
| pkgs/graphs/test/transitive_closure_test.dart |
| pkgs/graphs/test/utils/graph.dart |
| pkgs/graphs/test/utils/utils.dart |
| pkgs/html/example/main.dart |
| pkgs/html/lib/dom.dart |
| pkgs/html/lib/dom_parsing.dart |
| pkgs/html/lib/html_escape.dart |
| pkgs/html/lib/parser.dart |
| pkgs/html/lib/src/constants.dart |
| pkgs/html/lib/src/css_class_set.dart |
| pkgs/html/lib/src/encoding_parser.dart |
| pkgs/html/lib/src/html_input_stream.dart |
| pkgs/html/lib/src/list_proxy.dart |
| pkgs/html/lib/src/query_selector.dart |
| pkgs/html/lib/src/token.dart |
| pkgs/html/lib/src/tokenizer.dart |
| pkgs/html/lib/src/treebuilder.dart |
| pkgs/html/lib/src/utils.dart |
| pkgs/html/test/dom_test.dart |
| pkgs/html/test/parser_feature_test.dart |
| pkgs/html/test/parser_test.dart |
| pkgs/html/test/query_selector_test.dart |
| pkgs/html/test/selectors/level1_baseline_test.dart |
| pkgs/html/test/selectors/level1_lib.dart |
| pkgs/html/test/support.dart |
| pkgs/html/test/tokenizer_test.dart |
| pkgs/html/test/trie_test.dart |
| pkgs/html/tool/generate_trie.dart |
| pkgs/io/example/example.dart |
| pkgs/io/example/spawn_process_example.dart |
| pkgs/io/lib/ansi.dart |
| pkgs/io/lib/io.dart |
| pkgs/io/lib/src/ansi_code.dart |
| pkgs/io/lib/src/copy_path.dart |
| pkgs/io/lib/src/exit_code.dart |
| pkgs/io/lib/src/permissions.dart |
| pkgs/io/lib/src/process_manager.dart |
| pkgs/io/lib/src/shared_stdin.dart |
| pkgs/io/test/_files/stderr_hello.dart |
| pkgs/io/test/_files/stdin_echo.dart |
| pkgs/io/test/_files/stdout_hello.dart |
| pkgs/io/test/ansi_code_test.dart |
| pkgs/io/test/copy_path_test.dart |
| pkgs/io/test/permissions_test.dart |
| pkgs/io/test/process_manager_test.dart |
| pkgs/io/test/shared_stdin_test.dart |
| pkgs/json_rpc_2/example/client.dart |
| pkgs/json_rpc_2/example/main.dart |
| pkgs/json_rpc_2/lib/error_code.dart |
| pkgs/json_rpc_2/lib/json_rpc_2.dart |
| pkgs/json_rpc_2/lib/src/client.dart |
| pkgs/json_rpc_2/lib/src/exception.dart |
| pkgs/json_rpc_2/lib/src/parameters.dart |
| pkgs/json_rpc_2/lib/src/peer.dart |
| pkgs/json_rpc_2/lib/src/server.dart |
| pkgs/json_rpc_2/lib/src/utils.dart |
| pkgs/json_rpc_2/test/client/client_test.dart |
| pkgs/json_rpc_2/test/client/stream_test.dart |
| pkgs/json_rpc_2/test/client/utils.dart |
| pkgs/json_rpc_2/test/peer_test.dart |
| pkgs/json_rpc_2/test/server/batch_test.dart |
| pkgs/json_rpc_2/test/server/invalid_request_test.dart |
| pkgs/json_rpc_2/test/server/parameters_test.dart |
| pkgs/json_rpc_2/test/server/server_test.dart |
| pkgs/json_rpc_2/test/server/stream_test.dart |
| pkgs/json_rpc_2/test/server/utils.dart |
| pkgs/mime/example/example.dart |
| pkgs/mime/lib/mime.dart |
| pkgs/mime/lib/src/bound_multipart_stream.dart |
| pkgs/mime/lib/src/char_code.dart |
| pkgs/mime/lib/src/default_extension_map.dart |
| pkgs/mime/lib/src/extension.dart |
| pkgs/mime/lib/src/magic_number.dart |
| pkgs/mime/lib/src/mime_shared.dart |
| pkgs/mime/lib/src/mime_type.dart |
| pkgs/mime/lib/src/multipart_transformer.dart |
| pkgs/mime/test/default_extension_map_test.dart |
| pkgs/mime/test/extension_test.dart |
| pkgs/mime/test/mime_multipart_transformer_test.dart |
| pkgs/mime/test/mime_type_test.dart |
| pkgs/mime/tool/download_mime_info.dart |
| pkgs/mime/tool/regenerate_tables.dart |
| pkgs/oauth2/example/main.dart |
| pkgs/oauth2/lib/src/authorization_exception.dart |
| pkgs/oauth2/lib/src/expiration_exception.dart |
| pkgs/oauth2/lib/src/handle_access_token_response.dart |
| pkgs/oauth2/lib/src/parameters.dart |
| pkgs/oauth2/lib/src/resource_owner_password_grant.dart |
| pkgs/oauth2/test/authorization_code_grant_test.dart |
| pkgs/oauth2/test/client_credentials_grant_test.dart |
| pkgs/oauth2/test/client_test.dart |
| pkgs/oauth2/test/credentials_test.dart |
| pkgs/oauth2/test/handle_access_token_response_test.dart |
| pkgs/oauth2/test/resource_owner_password_grant_test.dart |
| pkgs/oauth2/test/utils.dart |
| pkgs/package_config/bin/package_config_of.dart |
| pkgs/package_config/example/main.dart |
| pkgs/package_config/lib/package_config.dart |
| pkgs/package_config/lib/package_config_types.dart |
| pkgs/package_config/lib/src/discovery.dart |
| pkgs/package_config/lib/src/errors.dart |
| pkgs/package_config/lib/src/package_config.dart |
| pkgs/package_config/lib/src/package_config_io.dart |
| pkgs/package_config/lib/src/util.dart |
| pkgs/package_config/lib/src/util_io.dart |
| pkgs/package_config/test/bench.dart |
| pkgs/package_config/test/discovery_test.dart |
| pkgs/package_config/test/discovery_uri_test.dart |
| pkgs/package_config/test/package_config_impl_test.dart |
| pkgs/package_config/test/src/util_io.dart |
| pkgs/pool/benchmark/for_each_benchmark.dart |
| pkgs/pool/lib/pool.dart |
| pkgs/pool/test/pool_test.dart |
| pkgs/process/example/main.dart |
| pkgs/process/lib/process.dart |
| pkgs/process/lib/src/interface/common.dart |
| pkgs/process/lib/src/interface/exceptions.dart |
| pkgs/process/lib/src/interface/local_process_manager.dart |
| pkgs/process/lib/src/interface/process_manager.dart |
| pkgs/process/lib/src/interface/process_wrapper.dart |
| pkgs/process/test/src/interface/common_test.dart |
| pkgs/process/test/src/interface/process_wrapper_test.dart |
| pkgs/process/test/utils.dart |
| pkgs/pub_semver/example/example.dart |
| pkgs/pub_semver/lib/pub_semver.dart |
| pkgs/pub_semver/lib/src/patterns.dart |
| pkgs/pub_semver/lib/src/utils.dart |
| pkgs/pub_semver/lib/src/version.dart |
| pkgs/pub_semver/lib/src/version_constraint.dart |
| pkgs/pub_semver/lib/src/version_range.dart |
| pkgs/pub_semver/lib/src/version_union.dart |
| pkgs/pub_semver/test/utils.dart |
| pkgs/pub_semver/test/version_constraint_test.dart |
| pkgs/pub_semver/test/version_range_test.dart |
| pkgs/pub_semver/test/version_test.dart |
| pkgs/pub_semver/test/version_union_test.dart |
| pkgs/pubspec_parse/lib/pubspec_parse.dart |
| pkgs/pubspec_parse/lib/src/dependency.dart |
| pkgs/pubspec_parse/lib/src/pubspec.dart |
| pkgs/pubspec_parse/lib/src/screenshot.dart |
| pkgs/pubspec_parse/test/dependency_test.dart |
| pkgs/pubspec_parse/test/ensure_build_test.dart |
| pkgs/pubspec_parse/test/git_uri_test.dart |
| pkgs/pubspec_parse/test/pub_utils.dart |
| pkgs/pubspec_parse/test/test_utils.dart |
| pkgs/pubspec_parse/test/tojson_test.dart |
| pkgs/source_map_stack_trace/lib/source_map_stack_trace.dart |
| pkgs/source_map_stack_trace/test/source_map_stack_trace_test.dart |
| pkgs/source_maps/lib/builder.dart |
| pkgs/source_maps/lib/parser.dart |
| pkgs/source_maps/lib/refactor.dart |
| pkgs/source_maps/lib/source_maps.dart |
| pkgs/source_maps/lib/src/source_map_span.dart |
| pkgs/source_maps/lib/src/utils.dart |
| pkgs/source_maps/lib/src/vlq.dart |
| pkgs/source_maps/test/builder_test.dart |
| pkgs/source_maps/test/common.dart |
| pkgs/source_maps/test/continued_region_test.dart |
| pkgs/source_maps/test/end2end_test.dart |
| pkgs/source_maps/test/parser_test.dart |
| pkgs/source_maps/test/printer_test.dart |
| pkgs/source_maps/test/refactor_test.dart |
| pkgs/source_maps/test/utils_test.dart |
| pkgs/source_maps/test/vlq_test.dart |
| pkgs/source_span/example/main.dart |
| pkgs/source_span/lib/source_span.dart |
| pkgs/source_span/lib/src/charcode.dart |
| pkgs/source_span/lib/src/colors.dart |
| pkgs/source_span/lib/src/file.dart |
| pkgs/source_span/lib/src/highlighter.dart |
| pkgs/source_span/lib/src/location.dart |
| pkgs/source_span/lib/src/location_mixin.dart |
| pkgs/source_span/lib/src/span.dart |
| pkgs/source_span/lib/src/span_exception.dart |
| pkgs/source_span/lib/src/span_mixin.dart |
| pkgs/source_span/lib/src/span_with_context.dart |
| pkgs/source_span/lib/src/utils.dart |
| pkgs/source_span/test/file_benchmark.dart |
| pkgs/source_span/test/file_test.dart |
| pkgs/source_span/test/location_test.dart |
| pkgs/source_span/test/utils_test.dart |
| pkgs/sse/example/index.dart |
| pkgs/sse/example/server.dart |
| pkgs/sse/lib/client/sse_client.dart |
| pkgs/sse/lib/server/sse_handler.dart |
| pkgs/sse/lib/src/server/sse_handler.dart |
| pkgs/sse/lib/src/util/id.dart |
| pkgs/sse/test/sse_test.dart |
| pkgs/sse/test/sse_unit_test.dart |
| pkgs/sse/test/web/index.dart |
| pkgs/stack_trace/example/example.dart |
| pkgs/stack_trace/lib/src/chain.dart |
| pkgs/stack_trace/lib/src/frame.dart |
| pkgs/stack_trace/lib/src/lazy_chain.dart |
| pkgs/stack_trace/lib/src/lazy_trace.dart |
| pkgs/stack_trace/lib/src/stack_zone_specification.dart |
| pkgs/stack_trace/lib/src/trace.dart |
| pkgs/stack_trace/lib/src/unparsed_frame.dart |
| pkgs/stack_trace/lib/src/utils.dart |
| pkgs/stack_trace/lib/src/vm_trace.dart |
| pkgs/stack_trace/lib/stack_trace.dart |
| pkgs/stack_trace/test/chain/chain_test.dart |
| pkgs/stack_trace/test/chain/dart2js_test.dart |
| pkgs/stack_trace/test/chain/utils.dart |
| pkgs/stack_trace/test/chain/vm_test.dart |
| pkgs/stack_trace/test/frame_test.dart |
| pkgs/stack_trace/test/trace_test.dart |
| pkgs/stack_trace/test/utils.dart |
| pkgs/stack_trace/test/vm_test.dart |
| pkgs/stream_channel/example/example.dart |
| pkgs/stream_channel/lib/isolate_channel.dart |
| pkgs/stream_channel/lib/src/close_guarantee_channel.dart |
| pkgs/stream_channel/lib/src/delegating_stream_channel.dart |
| pkgs/stream_channel/lib/src/disconnector.dart |
| pkgs/stream_channel/lib/src/guarantee_channel.dart |
| pkgs/stream_channel/lib/src/isolate_channel.dart |
| pkgs/stream_channel/lib/src/json_document_transformer.dart |
| pkgs/stream_channel/lib/src/multi_channel.dart |
| pkgs/stream_channel/lib/src/stream_channel_completer.dart |
| pkgs/stream_channel/lib/src/stream_channel_controller.dart |
| pkgs/stream_channel/lib/src/stream_channel_transformer.dart |
| pkgs/stream_channel/lib/stream_channel.dart |
| pkgs/stream_channel/test/disconnector_test.dart |
| pkgs/stream_channel/test/isolate_channel_test.dart |
| pkgs/stream_channel/test/json_document_transformer_test.dart |
| pkgs/stream_channel/test/multi_channel_test.dart |
| pkgs/stream_channel/test/stream_channel_completer_test.dart |
| pkgs/stream_channel/test/stream_channel_controller_test.dart |
| pkgs/stream_channel/test/stream_channel_test.dart |
| pkgs/stream_channel/test/with_close_guarantee_test.dart |
| pkgs/stream_channel/test/with_guarantees_test.dart |
| pkgs/stream_transform/example/main.dart |
| pkgs/stream_transform/lib/src/aggregate_sample.dart |
| pkgs/stream_transform/lib/src/async_expand.dart |
| pkgs/stream_transform/lib/src/async_map.dart |
| pkgs/stream_transform/lib/src/combine_latest.dart |
| pkgs/stream_transform/lib/src/common_callbacks.dart |
| pkgs/stream_transform/lib/src/concatenate.dart |
| pkgs/stream_transform/lib/src/from_handlers.dart |
| pkgs/stream_transform/lib/src/merge.dart |
| pkgs/stream_transform/lib/src/rate_limit.dart |
| pkgs/stream_transform/lib/src/scan.dart |
| pkgs/stream_transform/lib/src/switch.dart |
| pkgs/stream_transform/lib/src/take_until.dart |
| pkgs/stream_transform/lib/src/tap.dart |
| pkgs/stream_transform/lib/src/where.dart |
| pkgs/stream_transform/lib/stream_transform.dart |
| pkgs/stream_transform/test/async_expand_test.dart |
| pkgs/stream_transform/test/async_map_buffer_test.dart |
| pkgs/stream_transform/test/async_map_sample_test.dart |
| pkgs/stream_transform/test/async_where_test.dart |
| pkgs/stream_transform/test/audit_test.dart |
| pkgs/stream_transform/test/buffer_test.dart |
| pkgs/stream_transform/test/combine_latest_all_test.dart |
| pkgs/stream_transform/test/combine_latest_test.dart |
| pkgs/stream_transform/test/concurrent_async_map_test.dart |
| pkgs/stream_transform/test/debounce_test.dart |
| pkgs/stream_transform/test/followd_by_test.dart |
| pkgs/stream_transform/test/from_handlers_test.dart |
| pkgs/stream_transform/test/merge_test.dart |
| pkgs/stream_transform/test/sample_test.dart |
| pkgs/stream_transform/test/scan_test.dart |
| pkgs/stream_transform/test/start_with_test.dart |
| pkgs/stream_transform/test/switch_test.dart |
| pkgs/stream_transform/test/take_until_test.dart |
| pkgs/stream_transform/test/tap_test.dart |
| pkgs/stream_transform/test/throttle_test.dart |
| pkgs/stream_transform/test/utils.dart |
| pkgs/stream_transform/test/where_not_null_test.dart |
| pkgs/stream_transform/test/where_type_test.dart |
| pkgs/string_scanner/example/example.dart |
| pkgs/string_scanner/lib/src/charcode.dart |
| pkgs/string_scanner/lib/src/eager_span_scanner.dart |
| pkgs/string_scanner/lib/src/exception.dart |
| pkgs/string_scanner/lib/src/line_scanner.dart |
| pkgs/string_scanner/lib/src/relative_span_scanner.dart |
| pkgs/string_scanner/lib/src/span_scanner.dart |
| pkgs/string_scanner/lib/src/utils.dart |
| pkgs/string_scanner/lib/string_scanner.dart |
| pkgs/string_scanner/test/error_test.dart |
| pkgs/string_scanner/test/line_scanner_test.dart |
| pkgs/string_scanner/test/span_scanner_test.dart |
| pkgs/string_scanner/test/string_scanner_test.dart |
| pkgs/string_scanner/test/utils.dart |
| pkgs/term_glyph/lib/term_glyph.dart |
| pkgs/term_glyph/test/symbol_test.dart |
| pkgs/term_glyph/tool/generate.dart |
| pkgs/test_reflective_loader/lib/test_reflective_loader.dart |
| pkgs/test_reflective_loader/test/hierarchy_test.dart |
| pkgs/test_reflective_loader/test/hierarchy_test.data.dart |
| pkgs/test_reflective_loader/test/location_test.dart |
| pkgs/test_reflective_loader/test/test_reflective_loader_test.dart |
| pkgs/timing/lib/src/clock.dart |
| pkgs/timing/lib/src/timing.dart |
| pkgs/timing/lib/timing.dart |
| pkgs/timing/test/timing_test.dart |
| pkgs/unified_analytics/example/log_stats.dart |
| pkgs/unified_analytics/example/sample_rate.dart |
| pkgs/unified_analytics/example/serving_surveys.dart |
| pkgs/unified_analytics/example/unified_analytics_example.dart |
| pkgs/unified_analytics/lib/src/analytics.dart |
| pkgs/unified_analytics/lib/src/asserts.dart |
| pkgs/unified_analytics/lib/src/config_handler.dart |
| pkgs/unified_analytics/lib/src/constants.dart |
| pkgs/unified_analytics/lib/src/enums.dart |
| pkgs/unified_analytics/lib/src/event.dart |
| pkgs/unified_analytics/lib/src/ga_client.dart |
| pkgs/unified_analytics/lib/src/initializer.dart |
| pkgs/unified_analytics/lib/src/log_handler.dart |
| pkgs/unified_analytics/lib/src/survey_handler.dart |
| pkgs/unified_analytics/lib/src/user_property.dart |
| pkgs/unified_analytics/lib/src/utils.dart |
| pkgs/unified_analytics/lib/testing.dart |
| pkgs/unified_analytics/lib/unified_analytics.dart |
| pkgs/unified_analytics/test/asserts_test.dart |
| pkgs/unified_analytics/test/error_handler_test.dart |
| pkgs/unified_analytics/test/event_test.dart |
| pkgs/unified_analytics/test/events_with_fake_test.dart |
| pkgs/unified_analytics/test/legacy_analytics_test.dart |
| pkgs/unified_analytics/test/log_handler_test.dart |
| pkgs/unified_analytics/test/no_op_analytics_test.dart |
| pkgs/unified_analytics/test/suppression_test.dart |
| pkgs/unified_analytics/test/survey_handler_test.dart |
| pkgs/unified_analytics/test/unified_analytics_test.dart |
| pkgs/unified_analytics/test/workflow_test.dart |
| pkgs/watcher/example/watch.dart |
| pkgs/watcher/lib/src/async_queue.dart |
| pkgs/watcher/lib/src/custom_watcher_factory.dart |
| pkgs/watcher/lib/src/directory_watcher.dart |
| pkgs/watcher/lib/src/directory_watcher/linux/linux_directory_watcher.dart |
| pkgs/watcher/lib/src/directory_watcher/linux/native_watch.dart |
| pkgs/watcher/lib/src/directory_watcher/linux/watch_tree.dart |
| pkgs/watcher/lib/src/directory_watcher/linux/watch_tree_root.dart |
| pkgs/watcher/lib/src/directory_watcher/polling/directory_list.dart |
| pkgs/watcher/lib/src/directory_watcher/polling/polling_directory_watcher.dart |
| pkgs/watcher/lib/src/directory_watcher/recursive/directory_tree.dart |
| pkgs/watcher/lib/src/directory_watcher/recursive/event_tree.dart |
| pkgs/watcher/lib/src/directory_watcher/recursive/isolate_recursive_directory_watcher.dart |
| pkgs/watcher/lib/src/directory_watcher/recursive/recursive_directory_watcher.dart |
| pkgs/watcher/lib/src/directory_watcher/recursive/recursive_native_watch.dart |
| pkgs/watcher/lib/src/directory_watcher/recursive/watched_directory_tree.dart |
| pkgs/watcher/lib/src/event.dart |
| pkgs/watcher/lib/src/event_batching.dart |
| pkgs/watcher/lib/src/file_watcher.dart |
| pkgs/watcher/lib/src/file_watcher/native.dart |
| pkgs/watcher/lib/src/file_watcher/polling.dart |
| pkgs/watcher/lib/src/paths.dart |
| pkgs/watcher/lib/src/polling.dart |
| pkgs/watcher/lib/src/resubscribable.dart |
| pkgs/watcher/lib/src/testing.dart |
| pkgs/watcher/lib/src/watch_event.dart |
| pkgs/watcher/lib/watcher.dart |
| pkgs/watcher/test/custom_watcher_factory_test.dart |
| pkgs/watcher/test/directory_watcher/client_simulator.dart |
| pkgs/watcher/test/directory_watcher/end_to_end_test_runner.dart |
| pkgs/watcher/test/directory_watcher/end_to_end_tests.dart |
| pkgs/watcher/test/directory_watcher/file_changer.dart |
| pkgs/watcher/test/directory_watcher/file_tests.dart |
| pkgs/watcher/test/directory_watcher/link_tests.dart |
| pkgs/watcher/test/directory_watcher/linux_test.dart |
| pkgs/watcher/test/directory_watcher/macos_test.dart |
| pkgs/watcher/test/directory_watcher/polling/directory_list_test.dart |
| pkgs/watcher/test/directory_watcher/polling_test.dart |
| pkgs/watcher/test/directory_watcher/recursive/event_tree_test.dart |
| pkgs/watcher/test/directory_watcher/relative_directory_test.dart |
| pkgs/watcher/test/directory_watcher/windows_isolate_test.dart |
| pkgs/watcher/test/directory_watcher/windows_test.dart |
| pkgs/watcher/test/event_batching_test.dart |
| pkgs/watcher/test/file_watcher/file_tests.dart |
| pkgs/watcher/test/file_watcher/link_tests.dart |
| pkgs/watcher/test/file_watcher/native_test.dart |
| pkgs/watcher/test/file_watcher/polling_test.dart |
| pkgs/watcher/test/file_watcher/startup_race_tests.dart |
| pkgs/watcher/test/no_subscription/linux_test.dart |
| pkgs/watcher/test/no_subscription/macos_test.dart |
| pkgs/watcher/test/no_subscription/polling_test.dart |
| pkgs/watcher/test/no_subscription/shared.dart |
| pkgs/watcher/test/no_subscription/windows_test.dart |
| pkgs/watcher/test/paths_test.dart |
| pkgs/watcher/test/ready/linux_test.dart |
| pkgs/watcher/test/ready/macos_test.dart |
| pkgs/watcher/test/ready/polling_test.dart |
| pkgs/watcher/test/ready/shared.dart |
| pkgs/watcher/test/ready/windows_test.dart |
| pkgs/watcher/test/utils.dart |
| pkgs/yaml/benchmark/benchmark.dart |
| pkgs/yaml/example/example.dart |
| pkgs/yaml/lib/src/charcodes.dart |
| pkgs/yaml/lib/src/equality.dart |
| pkgs/yaml/lib/src/error_listener.dart |
| pkgs/yaml/lib/src/event.dart |
| pkgs/yaml/lib/src/loader.dart |
| pkgs/yaml/lib/src/null_span.dart |
| pkgs/yaml/lib/src/parser.dart |
| pkgs/yaml/lib/src/scanner.dart |
| pkgs/yaml/lib/src/style.dart |
| pkgs/yaml/lib/src/token.dart |
| pkgs/yaml/lib/src/utils.dart |
| pkgs/yaml/lib/src/yaml_document.dart |
| pkgs/yaml/lib/src/yaml_exception.dart |
| pkgs/yaml/lib/src/yaml_node.dart |
| pkgs/yaml/lib/src/yaml_node_wrapper.dart |
| pkgs/yaml/lib/yaml.dart |
| pkgs/yaml/test/span_test.dart |
| pkgs/yaml/test/utils.dart |
| pkgs/yaml/test/yaml_node_wrapper_test.dart |
| pkgs/yaml_edit/example/example.dart |
| pkgs/yaml_edit/example/json2yaml.dart |
| pkgs/yaml_edit/lib/src/editor.dart |
| pkgs/yaml_edit/lib/src/equality.dart |
| pkgs/yaml_edit/lib/src/errors.dart |
| pkgs/yaml_edit/lib/src/list_mutations.dart |
| pkgs/yaml_edit/lib/src/map_mutations.dart |
| pkgs/yaml_edit/lib/src/source_edit.dart |
| pkgs/yaml_edit/lib/src/strings.dart |
| pkgs/yaml_edit/lib/src/utils.dart |
| pkgs/yaml_edit/lib/src/wrap.dart |
| pkgs/yaml_edit/lib/yaml_edit.dart |
| pkgs/yaml_edit/test/alias_test.dart |
| pkgs/yaml_edit/test/append_test.dart |
| pkgs/yaml_edit/test/crash_test/crash_test.dart |
| pkgs/yaml_edit/test/editor_test.dart |
| pkgs/yaml_edit/test/golden_test.dart |
| pkgs/yaml_edit/test/insert_test.dart |
| pkgs/yaml_edit/test/naughty_test.dart |
| pkgs/yaml_edit/test/parse_test.dart |
| pkgs/yaml_edit/test/prepend_test.dart |
| pkgs/yaml_edit/test/preservation_test.dart |
| pkgs/yaml_edit/test/problem_strings.dart |
| pkgs/yaml_edit/test/random_test.dart |
| pkgs/yaml_edit/test/remove_test.dart |
| pkgs/yaml_edit/test/source_edit_test.dart |
| pkgs/yaml_edit/test/special_test.dart |
| pkgs/yaml_edit/test/splice_test.dart |
| pkgs/yaml_edit/test/string_test.dart |
| pkgs/yaml_edit/test/test_case.dart |
| pkgs/yaml_edit/test/test_utils.dart |
| pkgs/yaml_edit/test/update_test.dart |
| pkgs/yaml_edit/test/windows_test.dart |
| pkgs/yaml_edit/test/wrap_test.dart |
| tool/readme_update.dart |
This check can be disabled by tagging the PR with skip-license-check.
API leaks ✔️
The following packages contain symbols visible in the public API, but not exported by the library. Export these symbols or remove them from your publicly visible API.
| Package | Leaked API symbol | Leaking sources |
|---|
This check can be disabled by tagging the PR with skip-leaking-check.
…discovery and include a test for it.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces several valuable OAuth 2.0 features, including server discovery, dynamic client registration, resource indicators, and custom client authenticators. A critical security vulnerability has been identified due to a lack of HTTPS enforcement for the discovery and registration endpoints, which is mandated by RFC 8414, RFC 9728, and RFC 7591 to prevent Man-in-the-Middle attacks. It is recommended to add checks to ensure these URLs use the https scheme. Furthermore, there are opportunities to improve maintainability by refactoring duplicated code blocks.
…d corresponding tests.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces significant new features to the oauth2 package, including support for OAuth 2.0 discovery, dynamic client registration, resource indicators, and custom client authenticators. A comprehensive security audit found no vulnerabilities, and the changes adhere to OAuth 2.0 security best practices. My review focuses on improving code maintainability by reducing duplication and ensuring adherence to the repository's style guide regarding documentation for public members.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces significant new functionality to the oauth2 package, including support for OAuth 2.0 discovery, dynamic client registration, resource indicators, and custom authenticators. A critical security weakness was identified in the discoverProtectedResourceMetadata function, where an optional metadata URL is not checked for the https scheme, potentially allowing SSRF to internal http endpoints. This must be addressed to comply with RFC 9728 and improve security. Furthermore, general feedback includes improving code maintainability by reducing duplication, fixing a minor bug in the discovery logic, and enhancing documentation for the new public APIs to align with the repository's style guide.
…iscovery and registration function documentation.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces significant new functionality to package:oauth2, including support for OAuth 2.0 discovery, dynamic client registration, resource indicators, and custom client authenticators. The changes are well-structured and include comprehensive tests for the new features.
My review has identified a couple of areas for improvement:
- A bug in the URL comparison logic for issuer and resource validation in the discovery mechanism, which could lead to incorrect spoofing detection.
- Opportunities to refactor duplicated code in
client_credentials_grant.dartandcredentials.dartto improve maintainability.
Overall, this is a great contribution that significantly enhances the capabilities of the package. Addressing the points above will make the implementation more robust and maintainable.
…before comparison to prevent spoofing detection issues.
Co-authored-by: Jonas Finnemann Jensen <jopsen@gmail.com>
Co-authored-by: Jonas Finnemann Jensen <jopsen@gmail.com>
Co-authored-by: Jonas Finnemann Jensen <jopsen@gmail.com>
Co-authored-by: Jonas Finnemann Jensen <jopsen@gmail.com>
Co-authored-by: Jonas Finnemann Jensen <jopsen@gmail.com>
Co-authored-by: Jonas Finnemann Jensen <jopsen@gmail.com>
Co-authored-by: Jonas Finnemann Jensen <jopsen@gmail.com>
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces significant new features to the oauth2 package, including support for OAuth 2.0 discovery, dynamic client registration, resource indicators, and custom client authenticators. The changes are well-structured and include comprehensive tests for the new functionality. My review focuses on improving code maintainability by reducing duplication and enhancing documentation to align with the repository's style guide.
…ions for `discoverAuthorizationServerMetadata`.
…a more concise syntax.
…ta fields for improved clarity.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces significant new features to the oauth2 package, including support for OAuth 2.0 discovery, dynamic client registration, resource indicators, and custom client authenticators. The changes are extensive and well-tested. My review focuses on improving code maintainability by reducing duplication in the new logic for handling resource indicators, and ensuring the documentation for the new discovery feature accurately reflects its behavior and adheres to DartDoc style guidelines.
…y error handling and fallback behavior for invalid responses.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces significant new features to package:oauth2, including support for server discovery, dynamic client registration, resource indicators, and custom client authenticators. The implementation is generally of high quality and includes comprehensive tests for the new functionality.
My review focuses on a few areas for improvement:
- Documentation: Several new public parameters (
resources) are missing DartDoc comments, which is required by the repository's style guide. - Code Duplication: There are opportunities to refactor duplicated logic in
credentials.dartandclient_credentials_grant.dartto improve maintainability. - Bug Fix: There is a bug in the server discovery logic where it doesn't correctly fall back to other discovery URLs upon certain errors, which contradicts the documented behavior.
Overall, this is a great contribution. Addressing these points will further improve the code quality.
| if (e is DiscoveryException) rethrow; | ||
| continue; |
There was a problem hiding this comment.
The rethrow statement for DiscoveryException will cause the discovery process to terminate immediately instead of trying the next fallback URL. This contradicts the function's documentation, which states: "If a metadata endpoint is found but returns an invalid response (e.g., malformed JSON or issuer spoofing is detected), the function will catch the resulting exception and automatically try the next fallback URL."
An issuer spoofing check throws a DiscoveryException, and invalid JSON throws a FormatException. Both should be caught and allow the loop to continue to the next discovery URL. To fix this and align with the documentation, you should allow the catch block to always continue.
| if (e is DiscoveryException) rethrow; | |
| continue; | |
| continue; |
| Uri getAuthorizationUrl(Uri redirect, | ||
| {Iterable<String>? scopes, String? state}) { | ||
| {Iterable<String>? scopes, String? state, Iterable<Uri>? resources}) { |
There was a problem hiding this comment.
The new resources parameter in getAuthorizationUrl is not documented. According to the repository's style guide, all public members should be documented. Please add documentation for this new parameter to explain its purpose, which is for RFC 8707 Resource Indicators.
References
- At least all public members should have documentation, answering the why. (link)
| Future<Client> clientCredentialsGrant( | ||
| Uri authorizationEndpoint, String? identifier, String? secret, | ||
| {Iterable<String>? scopes, | ||
| bool basicAuth = true, | ||
| http.Client? httpClient, | ||
| String? delimiter, | ||
| ClientAuthenticator? customAuth, | ||
| Iterable<Uri>? resources, | ||
| Map<String, dynamic> Function(MediaType? contentType, String body)? | ||
| getParameters}) async { |
There was a problem hiding this comment.
The new resources parameter in clientCredentialsGrant is not documented. The repository style guide requires all public members to be documented. Please add documentation for this parameter to explain its purpose, which is for RFC 8707 Resource Indicators.
References
- At least all public members should have documentation, answering the why. (link)
| if (resources != null && resources.isNotEmpty) { | ||
| // http.post doesn't support Map<String, Iterable> for x-www-form-urlencoded | ||
| // bodies, so we construct the body string manually to allow | ||
| // multiple 'resource' parameters per RFC 8707. | ||
| final encodedBody = body.entries | ||
| .map((e) => '${Uri.encodeQueryComponent(e.key)}=' | ||
| '${Uri.encodeQueryComponent(e.value)}') | ||
| .toList(); | ||
| for (final r in resources) { | ||
| encodedBody.add('resource=${Uri.encodeQueryComponent(r.toString())}'); | ||
| } | ||
|
|
||
| httpClient ??= http.Client(); | ||
| var response = await httpClient.post(authorizationEndpoint, | ||
| headers: headers | ||
| ..['content-type'] = 'application/x-www-form-urlencoded', | ||
| body: encodedBody.join('&')); | ||
|
|
||
| var credentials = handleAccessTokenResponse(response, authorizationEndpoint, | ||
| startTime, scopes?.toList() ?? [], delimiter, | ||
| getParameters: getParameters); | ||
| return Client(credentials, | ||
| identifier: identifier, | ||
| secret: secret, | ||
| httpClient: httpClient, | ||
| customAuth: customAuth); | ||
| } |
There was a problem hiding this comment.
This if block for handling resources duplicates a lot of logic from the code that follows it (lines 111-123). Both branches make an HTTP POST request, handle the access token response, and create a Client. This duplication can lead to maintenance issues.
Please consider refactoring to remove the duplication. You could, for instance, determine the request body and content-type first, and then have a single path for making the request and processing the response.
| if (resources != null && resources.isNotEmpty) { | ||
| final encodedBody = body.entries | ||
| .map((e) => '${Uri.encodeQueryComponent(e.key)}=' | ||
| '${Uri.encodeQueryComponent(e.value)}') | ||
| .toList(); | ||
| for (final r in resources) { | ||
| encodedBody.add('resource=${Uri.encodeQueryComponent(r.toString())}'); | ||
| } | ||
| headers['content-type'] = 'application/x-www-form-urlencoded'; | ||
| var response = await httpClient.post(tokenEndpoint, | ||
| headers: headers, body: encodedBody.join('&')); | ||
| var credentials = handleAccessTokenResponse( | ||
| response, tokenEndpoint, startTime, scopes, _delimiter, | ||
| getParameters: _getParameters); | ||
| if (credentials.refreshToken != null) return credentials; | ||
| return Credentials(credentials.accessToken, | ||
| refreshToken: refreshToken, | ||
| idToken: credentials.idToken, | ||
| tokenEndpoint: credentials.tokenEndpoint, | ||
| scopes: credentials.scopes, | ||
| expiration: credentials.expiration); | ||
| } |
There was a problem hiding this comment.
There is significant code duplication between this block that handles requests with resources and the following code that handles requests without them. Both branches perform an HTTP POST, handle the response, and construct a Credentials object. This duplication makes the code harder to maintain.
Consider refactoring to unify the logic. For example, you could prepare the request body (either as a Map<String, String> or an encoded String) and then have a single httpClient.post call and a single block for response handling.
There was a problem hiding this comment.
But is this code really that complicated.. we're implementing a spec, this won't be touched much. And abstractions might just make everything weirder..
Straight lines of code is awesome.. too many fancy private methods trying to share trivial logic doesn't make the world better.
| /// Adds additional query parameters to [url], overwriting the original | ||
| /// parameters if a name conflict occurs. | ||
| Uri addQueryParameters(Uri url, Map<String, String> parameters) => url.replace( | ||
| Uri addQueryParameters(Uri url, Map<String, dynamic> parameters) => url.replace( |
|
please comment/resolve the gemini comments, too. I've found they are solid at least 3/4 of the time |
|
@pavelgj – wanna run with the remaining comments? |
This PR implements several advanced OAuth 2.0 and OpenID Connect features into
package:oauth2to support more complex enterprise and OIDC flows without breaking existing logic.Features Added
discoverAuthorizationServerMetadataanddiscoverProtectedResourceMetadatafunctions in the newlib/src/discovery.dartfile./.well-known/oauth-authorization-serverand OpenID Connect discovery endpoints, complete with standard robust fallbacks.registerClientin the newlib/src/registration.dartfile for dynamic client provisioning scenarios.Iterable<Uri>? resourcesoptional parameters toAuthorizationCodeGrant.getAuthorizationUrl,ClientCredentialsGrant.clientCredentialsGrant, andCredentials.refresh().ClientAuthenticatortypedef for injecting custom client assertions (e.g., JWTs for RFC 7523) during token exchange.AuthorizationCodeGrant,ClientCredentialsGrant, andClient.refreshCredentials(), which is propagated during token refresh.Testing
test/discovery_test.dartandtest/registration_test.dartsimulating server endpoints usingExpectClient.