feat: Replace hardcoded Graph CLI app ID with user-configurable cusom client app#72
Merged
sellakumaran merged 8 commits intomainfrom Dec 8, 2025
Merged
feat: Replace hardcoded Graph CLI app ID with user-configurable cusom client app#72sellakumaran merged 8 commits intomainfrom
sellakumaran merged 8 commits intomainfrom
Conversation
…m client app BREAKING CHANGE: Users must create a custom client app registration with 5 required delegated permissions before using a365 CLI. ## What Changed - Added required `clientAppId` field to a365.config.json - Replaced all references to Microsoft Graph Command Line Tools app ID (14d82eec...) with config.ClientAppId - Added ClientAppValidator service to validate app existence, permissions, and admin consent - Configuration wizard now validates client app during `a365 config init` (3 retry attempts) - Setup commands validate prerequisites upfront before execution ## Required Permissions (Delegated, not Application) 1. Application.ReadWrite.All 2. AgentIdentityBlueprint.ReadWrite.All 3. AgentIdentityBlueprint.UpdateAuthProperties.All 4. DelegatedPermissionGrant.ReadWrite.All 5. Directory.Read.All ## Migration for Existing Users 1. Create app registration in Azure Portal 2. Add 5 delegated permissions + grant admin consent 3. Run `a365 config init` to configure clientAppId 4. See: docs/guides/custom-client-app-registration.md ## Bug Fixes - Fixed critical parameter swap bug in BlueprintSubcommand causing "tenant not found" error - Fixed emoji violations in ConfigurationWizardService - Removed misleading authentication log messages ## Testing - 417/423 tests passing (6 skipped) - Added 153 new tests for validation logic - All existing tests updated to use clientAppId
Contributor
There was a problem hiding this comment.
Pull request overview
This PR implements a major breaking change that replaces the hardcoded Microsoft Graph Command Line Tools app ID with a user-configurable custom client app registration. Users must now create their own Entra ID app registration with 5 required delegated permissions before using the a365 CLI. The PR also fixes a critical parameter swap bug in BlueprintSubcommand that was causing "tenant not found" errors.
Key Changes:
- Added
clientAppIdfield to a365.config.json (required, validated during config init) - Replaced all references to hardcoded app ID (14d82eec...) with config.ClientAppId
- Introduced ClientAppValidator service with comprehensive validation (app existence, permissions, admin consent)
- Configuration wizard now validates client app with 3 retry attempts during
a365 config init - Added 153 new tests covering validation logic
Reviewed changes
Copilot reviewed 31 out of 31 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Tests/Microsoft.Agents.A365.DevTools.Cli.Tests/Services/ClientAppValidatorTests.cs | New comprehensive test suite (570 lines) for ClientAppValidator with token acquisition, app existence, permission, and admin consent validation tests |
| src/Tests/Microsoft.Agents.A365.DevTools.Cli.Tests/Services/Agent365ConfigServiceTests.cs | Updated to use AuthenticationConstants.MicrosoftGraphResourceAppId constant |
| src/Tests/Microsoft.Agents.A365.DevTools.Cli.Tests/Models/Agent365ConfigTests.cs | Added ClientAppId validation tests covering null, empty, whitespace, invalid format, and valid GUID scenarios |
| src/Tests/Microsoft.Agents.A365.DevTools.Cli.Tests/Exceptions/ClientAppValidationExceptionTests.cs | New test suite (267 lines) for ClientAppValidationException factory methods and error messaging |
| src/Tests/Microsoft.Agents.A365.DevTools.Cli.Tests/Commands/SubcommandValidationTests.cs | New validation tests (304 lines) for Infrastructure, Blueprint, and Permissions subcommands |
| src/Tests/Microsoft.Agents.A365.DevTools.Cli.Tests/Commands/ConfigCommandStaticDynamicSeparationTests.cs | Updated tests to use constant and include clientAppId in test configurations |
| src/Tests/Microsoft.Agents.A365.DevTools.Cli.Tests/Commands/BlueprintSubcommandTests.cs | Added documentation test to prevent future parameter order bugs (clientAppId before tenantId) |
| src/Microsoft.Agents.A365.DevTools.Cli/Services/InteractiveGraphAuthService.cs | Updated constructor to require clientAppId parameter, added client caching, replaced hardcoded app ID |
| src/Microsoft.Agents.A365.DevTools.Cli/Services/ISubCommand.cs | New interface defining validation contract for subcommands |
| src/Microsoft.Agents.A365.DevTools.Cli/Services/GraphApiService.cs | Replaced hardcoded Graph app ID with AuthenticationConstants constant |
| src/Microsoft.Agents.A365.DevTools.Cli/Services/DelegatedConsentService.cs | Updated comments and replaced hardcoded constant with AuthenticationConstants |
| src/Microsoft.Agents.A365.DevTools.Cli/Services/ConfigurationWizardService.cs | Added ClientAppId prompt with validation (3 retry attempts) using ClientAppValidator |
| src/Microsoft.Agents.A365.DevTools.Cli/Services/ClientAppValidator.cs | New service (517 lines) implementing comprehensive client app validation with Graph API queries |
| src/Microsoft.Agents.A365.DevTools.Cli/Services/AuthenticationService.cs | Cleaned up misleading environment-specific log messages |
| src/Microsoft.Agents.A365.DevTools.Cli/Models/Agent365Config.cs | Added ClientAppId property with validation and GUID format checking |
| src/Microsoft.Agents.A365.DevTools.Cli/Exceptions/GraphTokenScopeException.cs | Updated error messages to reference custom client app instead of hardcoded app |
| src/Microsoft.Agents.A365.DevTools.Cli/Exceptions/ClientAppValidationException.cs | New exception class (135 lines) with factory methods for different validation failure types |
| src/Microsoft.Agents.A365.DevTools.Cli/Constants/ErrorCodes.cs | Added ClientAppValidationFailed error code |
| src/Microsoft.Agents.A365.DevTools.Cli/Constants/AuthenticationConstants.cs | Added MicrosoftGraphResourceAppId, RequiredClientAppPermissions, and updated LocalhostRedirectUri |
| src/Microsoft.Agents.A365.DevTools.Cli/Commands/SetupSubcommands/SetupHelpers.cs | Updated permission requirements to include AgentIdentityBlueprint.UpdateAuthProperties.All |
| src/Microsoft.Agents.A365.DevTools.Cli/Commands/SetupSubcommands/PermissionsSubcommand.cs | Added ValidateMcpAsync and ValidateBotAsync validation methods |
| src/Microsoft.Agents.A365.DevTools.Cli/Commands/SetupSubcommands/InfrastructureSubcommand.cs | Added ValidateAsync method for infrastructure prerequisite checking |
| src/Microsoft.Agents.A365.DevTools.Cli/Commands/SetupSubcommands/BlueprintSubcommand.cs | Fixed critical parameter swap bug (clientAppId before tenantId), added ValidateAsync method |
| src/Microsoft.Agents.A365.DevTools.Cli/Commands/SetupSubcommands/AllSubcommand.cs | Added upfront validation phase for all prerequisites before execution |
| src/Microsoft.Agents.A365.DevTools.Cli/Commands/QueryEntraCommand.cs | Replaced hardcoded GUID with AuthenticationConstants constant |
| src/Microsoft.Agents.A365.DevTools.Cli/Commands/DeployCommand.cs | Updated permission requirements and error messaging |
| src/DEVELOPER.md | Added documentation about permission configuration layers and retry logic |
| scripts/cli/install-cli.ps1 | Improved installation script with old package cleanup and version-specific install |
| docs/guides/custom-client-app-registration.md | New comprehensive guide (126 lines) for creating custom client app with security best practices |
| docs/commands/config-init.md | Updated configuration wizard documentation to include client app validation steps |
| README.md | Added prerequisites section explaining custom client app requirement |
src/Microsoft.Agents.A365.DevTools.Cli/Models/Agent365Config.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Agents.A365.DevTools.Cli/Services/ConfigurationWizardService.cs
Show resolved
Hide resolved
src/Microsoft.Agents.A365.DevTools.Cli/Services/InteractiveGraphAuthService.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Agents.A365.DevTools.Cli/Services/ClientAppValidator.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Agents.A365.DevTools.Cli/Services/ClientAppValidator.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Agents.A365.DevTools.Cli/Services/ClientAppValidator.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Agents.A365.DevTools.Cli/Services/ClientAppValidator.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Agents.A365.DevTools.Cli/Commands/SetupSubcommands/AllSubcommand.cs
Outdated
Show resolved
Hide resolved
Josina20
reviewed
Dec 5, 2025
Fixes AADSTS65001 error where agent instances couldn't access Microsoft Graph resources. Root cause: Blueprint was granting Graph admin consent but never setting inheritable permissions. Additionally, BlueprintSubcommand was creating a new GraphApiService without the MicrosoftGraphTokenProvider, causing 403 authorization errors when trying to configure permissions. Changes: - Use DI-provided GraphApiService in BlueprintSubcommand (matches MCP/Bot/Observability pattern) - Add Graph inheritable permissions configuration after admin consent - Add scopes parameter to GraphGetAsync/VerifyInheritablePermissionsAsync for custom client app auth - Fix undefined variable in SetupHelpers.EnsureResourcePermissionsAsync - Update all tests to pass mock GraphApiService All 4 permission groups (Graph, MCP, Bot, Observability) now use identical DI pattern.
mengyimicro
previously approved these changes
Dec 5, 2025
…ntation consistency - Refactor imperative foreach loops to functional LINQ patterns in ClientAppValidator * Graph resource lookup: .Select().FirstOrDefault() * Permission ID mapping: .Select().Where().ToDictionary() * Admin consent validation: .Select().Where().Any() * Configured permission extraction: .Select().Where().ToHashSet() - Remove redundant conditional check in AllSubcommand after exception throw - Consolidate duplicate permission architecture documentation in DEVELOPER.md - Enhance custom-client-app-registration.md with comprehensive API-based setup * Add prerequisites section (Azure role, Azure CLI) * Provide two clear paths: Portal UI vs Microsoft Graph API * Include complete API workflow with permission IDs and verification steps * Document beta permission behavior and Portal consent limitations - Fix test assertions to validate Microsoft Learn URLs - Fix missing GraphApiService parameter in BlueprintSubcommand test calls - Added Agent365CliDocumentationUrl No behavioral changes or breaking changes introduced.
src/Microsoft.Agents.A365.DevTools.Cli/Constants/AuthenticationConstants.cs
Show resolved
Hide resolved
Streamlined and clarified the custom client app registration guide: - Emphasized the use of Delegated permissions over Application. - Added a Quick Setup section with step-by-step instructions. - Updated Prerequisites to address common mistakes and clarify roles. - Restructured Configure API Permissions with detailed guidance. - Replaced Azure CLI instructions with Graph Explorer for beta APIs. - Added Troubleshooting for permission type errors and beta issues. - Highlighted security and compliance benefits of Delegated permissions. These changes improve clarity, reduce redundancy, and enhance usability.
Introduced a `--verbose` option to `CleanupCommand` for detailed logging, ensuring consistent behavior across all subcommands. Renamed `EnsureAgentApplicationCreateConsentAsync` to `EnsureBlueprintPermissionGrantAsync` and updated it to use the `AgentIdentityBlueprint.ReadWrite.All` permission, replacing the deprecated `AgentApplication.Create` permission. Enhanced `CleanConsoleFormatter` to support `Debug` and `Trace` log levels, aligning with Azure CLI patterns. Updated error handling and logging for better clarity and context. Refactored retry logic and test cases to use the new method. Updated documentation and examples to reflect these changes, including adding a `clientAppId` field to the example config file. These changes improve functionality, user experience, and maintainability.
Improve documentation for granting admin consent for beta permissions (`AgentIdentityBlueprint.*`) using the Microsoft Graph API. Add warnings to avoid using Azure Portal's "Grant admin consent" button after API usage, as it can overwrite and delete beta permissions. Update Graph Explorer instructions to include steps for handling permissions errors and clarify the process for retrieving `SP_OBJECT_ID` and `GRAPH_RESOURCE_ID`. Provide guidance on verifying permissions via the `oauth2PermissionGrants` endpoint. Add a detailed explanation of the root cause and solution for disappearing beta permissions when using Azure Portal. Highlight that the API method (`consentType: "AllPrincipals"`) already grants tenant-wide admin consent. Include CLI validation details to ensure proper permissions setup.
mengyimicro
previously approved these changes
Dec 8, 2025
Josina20
reviewed
Dec 8, 2025
Josina20
previously approved these changes
Dec 8, 2025
Updated documentation to include detailed steps for granting admin consent via Microsoft Graph API, including handling beta permissions. Enhanced PowerShell script to clear NuGet cache and ensure a clean build. Improved `ClientAppValidator` with fallback logic for consented permissions via `oauth2PermissionGrants`, added a new method `GetConsentedPermissionsAsync`, and refined validation error handling. Added critical warnings about Azure Portal overwriting API-granted permissions and provided solutions for restoring beta permissions. Enhanced logging and troubleshooting guidance for better user experience and security.
f76e08c
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 36 out of 36 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
src/a365.config.example.json:1
- Corrected spelling of 'cusom' to 'custom' in the PR title.
src/Tests/Microsoft.Agents.A365.DevTools.Cli.Tests/Commands/BlueprintSubcommandTests.cs
Show resolved
Hide resolved
src/Microsoft.Agents.A365.DevTools.Cli/Commands/SetupSubcommands/AllSubcommand.cs
Show resolved
Hide resolved
Josina20
approved these changes
Dec 8, 2025
mengyimicro
approved these changes
Dec 8, 2025
sellakumaran
added a commit
that referenced
this pull request
Feb 27, 2026
… client app (#72) * feat: Replace hardcoded Graph CLI app ID with user-configurable custom client app BREAKING CHANGE: Users must create a custom client app registration with 5 required delegated permissions before using a365 CLI. ## What Changed - Added required `clientAppId` field to a365.config.json - Replaced all references to Microsoft Graph Command Line Tools app ID (14d82eec...) with config.ClientAppId - Added ClientAppValidator service to validate app existence, permissions, and admin consent - Configuration wizard now validates client app during `a365 config init` (3 retry attempts) - Setup commands validate prerequisites upfront before execution ## Required Permissions (Delegated, not Application) 1. Application.ReadWrite.All 2. AgentIdentityBlueprint.ReadWrite.All 3. AgentIdentityBlueprint.UpdateAuthProperties.All 4. DelegatedPermissionGrant.ReadWrite.All 5. Directory.Read.All ## Migration for Existing Users 1. Create app registration in Azure Portal 2. Add 5 delegated permissions + grant admin consent 3. Run `a365 config init` to configure clientAppId 4. See: docs/guides/custom-client-app-registration.md ## Bug Fixes - Fixed critical parameter swap bug in BlueprintSubcommand causing "tenant not found" error - Fixed emoji violations in ConfigurationWizardService - Removed misleading authentication log messages ## Testing - 417/423 tests passing (6 skipped) - Added 153 new tests for validation logic - All existing tests updated to use clientAppId * fix: Configure Graph inheritable permissions in blueprint creation Fixes AADSTS65001 error where agent instances couldn't access Microsoft Graph resources. Root cause: Blueprint was granting Graph admin consent but never setting inheritable permissions. Additionally, BlueprintSubcommand was creating a new GraphApiService without the MicrosoftGraphTokenProvider, causing 403 authorization errors when trying to configure permissions. Changes: - Use DI-provided GraphApiService in BlueprintSubcommand (matches MCP/Bot/Observability pattern) - Add Graph inheritable permissions configuration after admin consent - Add scopes parameter to GraphGetAsync/VerifyInheritablePermissionsAsync for custom client app auth - Fix undefined variable in SetupHelpers.EnsureResourcePermissionsAsync - Update all tests to pass mock GraphApiService All 4 permission groups (Graph, MCP, Bot, Observability) now use identical DI pattern. * fix: Address PR #72 review comments - improve code quality and documentation consistency - Refactor imperative foreach loops to functional LINQ patterns in ClientAppValidator * Graph resource lookup: .Select().FirstOrDefault() * Permission ID mapping: .Select().Where().ToDictionary() * Admin consent validation: .Select().Where().Any() * Configured permission extraction: .Select().Where().ToHashSet() - Remove redundant conditional check in AllSubcommand after exception throw - Consolidate duplicate permission architecture documentation in DEVELOPER.md - Enhance custom-client-app-registration.md with comprehensive API-based setup * Add prerequisites section (Azure role, Azure CLI) * Provide two clear paths: Portal UI vs Microsoft Graph API * Include complete API workflow with permission IDs and verification steps * Document beta permission behavior and Portal consent limitations - Fix test assertions to validate Microsoft Learn URLs - Fix missing GraphApiService parameter in BlueprintSubcommand test calls - Added Agent365CliDocumentationUrl No behavioral changes or breaking changes introduced. * Refactor Agent365 app registration guide Streamlined and clarified the custom client app registration guide: - Emphasized the use of Delegated permissions over Application. - Added a Quick Setup section with step-by-step instructions. - Updated Prerequisites to address common mistakes and clarify roles. - Restructured Configure API Permissions with detailed guidance. - Replaced Azure CLI instructions with Graph Explorer for beta APIs. - Added Troubleshooting for permission type errors and beta issues. - Highlighted security and compliance benefits of Delegated permissions. These changes improve clarity, reduce redundancy, and enhance usability. * Add verbose logging, update permissions, and enhance UX Introduced a `--verbose` option to `CleanupCommand` for detailed logging, ensuring consistent behavior across all subcommands. Renamed `EnsureAgentApplicationCreateConsentAsync` to `EnsureBlueprintPermissionGrantAsync` and updated it to use the `AgentIdentityBlueprint.ReadWrite.All` permission, replacing the deprecated `AgentApplication.Create` permission. Enhanced `CleanConsoleFormatter` to support `Debug` and `Trace` log levels, aligning with Azure CLI patterns. Updated error handling and logging for better clarity and context. Refactored retry logic and test cases to use the new method. Updated documentation and examples to reflect these changes, including adding a `clientAppId` field to the example config file. These changes improve functionality, user experience, and maintainability. * Clarify beta permissions setup with Graph API Improve documentation for granting admin consent for beta permissions (`AgentIdentityBlueprint.*`) using the Microsoft Graph API. Add warnings to avoid using Azure Portal's "Grant admin consent" button after API usage, as it can overwrite and delete beta permissions. Update Graph Explorer instructions to include steps for handling permissions errors and clarify the process for retrieving `SP_OBJECT_ID` and `GRAPH_RESOURCE_ID`. Provide guidance on verifying permissions via the `oauth2PermissionGrants` endpoint. Add a detailed explanation of the root cause and solution for disappearing beta permissions when using Azure Portal. Highlight that the API method (`consentType: "AllPrincipals"`) already grants tenant-wide admin consent. Include CLI validation details to ensure proper permissions setup. * Improve Agent365 CLI setup and validation process Updated documentation to include detailed steps for granting admin consent via Microsoft Graph API, including handling beta permissions. Enhanced PowerShell script to clear NuGet cache and ensure a clean build. Improved `ClientAppValidator` with fallback logic for consented permissions via `oauth2PermissionGrants`, added a new method `GetConsentedPermissionsAsync`, and refined validation error handling. Added critical warnings about Azure Portal overwriting API-granted permissions and provided solutions for restoring beta permissions. Enhanced logging and troubleshooting guidance for better user experience and security.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
BREAKING CHANGE: Users must create a custom client app registration with 5 required delegated permissions before using a365 CLI.
What Changed
clientAppIdfield to a365.config.jsona365 config init(3 retry attempts)Required Permissions (Delegated, not Application)
Migration for Existing Users
a365 config initto configure clientAppIdBug Fixes
Testing