Adding custom client secret expiration to comply with Entra ID policies#427
Conversation
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
There was a problem hiding this comment.
Pull request overview
This PR adds support for customizing the expiration (lifetime in days) of client secrets created during a365 develop-mcp register-external-mcp-server, to better comply with Microsoft Entra ID tenant policies that cap secret lifetimes. It updates the Graph call payload to optionally include endDateTime, threads the new setting through CLI options/input JSON, and adds unit tests around payload shape and error messaging.
Changes:
- Add
--secret-lifetime-daysoption and propagate it through registration input resolution and app-secret creation. - Update
GraphApiService.AddAppPasswordAsyncto optionally sendpasswordCredential.endDateTime, and emit a more actionable error when a tenant policy rejects the requested/default lifetime. - Add tests covering payload behavior and policy-rejection classification/logging; update sample input JSON to include
secretLifetimeDays.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Tests/Microsoft.Agents.A365.DevTools.Cli.Tests/Services/GraphApiServiceAddAppPasswordTests.cs | New tests for optional lifetime payload and policy-rejection logging/classification. |
| src/Microsoft.Agents.A365.DevTools.Cli/Templates/register-external-mcp-server-sample.json | Adds secretLifetimeDays to the sample input schema. |
| src/Microsoft.Agents.A365.DevTools.Cli/Services/GraphApiService.cs | Extends AddAppPasswordAsync with optional lifetime and improved policy-rejection error handling. |
| src/Microsoft.Agents.A365.DevTools.Cli/Models/RegisterExternalMcpServerInput.cs | Adds SecretLifetimeDays field to input model. |
| src/Microsoft.Agents.A365.DevTools.Cli/Commands/RegisterCommandExecutor.cs | Reads/validates SecretLifetimeDays, prints it in summary, and passes it to secret creation. |
| src/Microsoft.Agents.A365.DevTools.Cli/Commands/DevelopMcpCommand.cs | Adds the new CLI option and wires it into the register-external-mcp-server argument bundle. |
Comments suppressed due to low confidence (1)
src/Microsoft.Agents.A365.DevTools.Cli/Commands/DevelopMcpCommand.cs:893
- This command handler never sets context.ExitCode on failure paths (the handler returns Task, so System.CommandLine will exit 0 even after logged errors). Consider having RegisterCommandExecutor return an exit code (or success bool) and set context.ExitCode=1 for validation/registration failures.
command.SetHandler(async (context) =>
{
var args = new RawRegisterArgs(
ServerName: context.ParseResult.GetValueForOption(serverNameOption),
ServerUrl: context.ParseResult.GetValueForOption(serverUrlOption),
AuthType: context.ParseResult.GetValueForOption(authTypeOption),
IdpAuthUrl: context.ParseResult.GetValueForOption(idpAuthUrlOption),
IdpTokenUrl: context.ParseResult.GetValueForOption(idpTokenUrlOption),
IdpScopes: context.ParseResult.GetValueForOption(idpScopesOption),
IdpClientId: context.ParseResult.GetValueForOption(idpClientIdOption),
IdpClientSecret: context.ParseResult.GetValueForOption(idpClientSecretOption),
ApiKeyLocation: context.ParseResult.GetValueForOption(apiKeyLocationOption),
ApiKeyName: context.ParseResult.GetValueForOption(apiKeyNameOption),
ToolsInput: context.ParseResult.GetValueForOption(toolsOption),
InputFile: context.ParseResult.GetValueForOption(inputFileOption),
RemoteScopes: context.ParseResult.GetValueForOption(remoteScopesOption),
TenantId: context.ParseResult.GetValueForOption(tenantIdOption),
ServiceTreeId: context.ParseResult.GetValueForOption(serviceTreeIdOption),
SecretLifetimeDays: context.ParseResult.GetValueForOption(secretLifetimeDaysOption),
PublisherName: context.ParseResult.GetValueForOption(publisherOption),
Description: context.ParseResult.GetValueForOption(descriptionOption),
DryRun: context.ParseResult.GetValueForOption(dryRunOption));
var executor = new RegisterCommandExecutor(logger, toolingService, graphApiService);
await executor.ExecuteAsync(args, context.GetCancellationToken());
});
|
can you add a oneliner to changes.md file for this change? |
2baa1a6 to
15f7a2b
Compare
When running a365 develop-mcp register-external-mcp-server, the command fails during app credential provisioning in tenants that enforce Microsoft Entra ID policies restricting maximum client secret lifetimes.
Currently, the CLI attempts to create a client secret with a lifetime of 2 years.