Skip to content

feat: Replace hardcoded Graph CLI app ID with user-configurable cusom client app#72

Merged
sellakumaran merged 8 commits intomainfrom
users/sellak/appid
Dec 8, 2025
Merged

feat: Replace hardcoded Graph CLI app ID with user-configurable cusom client app#72
sellakumaran merged 8 commits intomainfrom
users/sellak/appid

Conversation

@sellakumaran
Copy link
Contributor

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

…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
@sellakumaran sellakumaran requested a review from a team as a code owner December 5, 2025 02:32
Copilot AI review requested due to automatic review settings December 5, 2025 02:32
@sellakumaran sellakumaran requested a review from a team as a code owner December 5, 2025 02:32
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 clientAppId field 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

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
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.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 33 out of 33 changed files in this pull request and generated 7 comments.

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.
Copilot AI review requested due to automatic review settings December 6, 2025 02:44
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 36 out of 36 changed files in this pull request and generated 1 comment.

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
mengyimicro previously approved these changes Dec 8, 2025
Josina20
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.
Copilot AI review requested due to automatic review settings December 8, 2025 19:55
@sellakumaran sellakumaran dismissed stale reviews from Josina20 and mengyimicro via f76e08c December 8, 2025 19:55
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@sellakumaran sellakumaran enabled auto-merge (squash) December 8, 2025 20:14
@sellakumaran sellakumaran disabled auto-merge December 8, 2025 20:38
@sellakumaran sellakumaran merged commit 720b576 into main Dec 8, 2025
11 checks passed
@sellakumaran sellakumaran deleted the users/sellak/appid branch December 8, 2025 22:38
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants