microsoft / botbuilder-dotnet

Welcome to the Bot Framework SDK for .NET repository, which is the home for the libraries and packages that enable developers to build sophisticated bot applications using .NET.
https://github.com/Microsoft/botframework
MIT License
864 stars 480 forks source link

[SNI Certificate Authentication] System.UnauthorizedAccessException: Invalid AppId passed on token: xxx #6799

Closed raych1 closed 2 weeks ago

raych1 commented 3 weeks ago

Version

Microsoft.Bot.Connector.dll: 4.22.3

Describe the bug

Created CertificateServiceClientCredentialsFactory instance as type of ServiceClientCredentialsFactory but PasswordServiceClientCredentialFactory is called to validate the AppId from the claim. The AppId in PasswordServiceClientCredentialFactory is null, which caused this error 'invalid AppId passed on token:xxx'.

Microsoft.Teams.AI.TeamsAdapter: Error: System.UnauthorizedAccessException: Invalid AppId passed on token: xxx
   at Microsoft.Bot.Connector.Authentication.ChannelValidation.AuthenticateChannelToken(String authHeader, ICredentialProvider credentials, HttpClient httpClient, String channelId, AuthenticationConfiguration authConfig)
   at Microsoft.Bot.Connector.Authentication.ChannelValidation.AuthenticateChannelToken(String authHeader, ICredentialProvider credentials, String serviceUrl, HttpClient httpClient, String channelId, AuthenticationConfiguration authConfig)
   at Microsoft.Bot.Connector.Authentication.JwtTokenValidation.AuthenticateTokenAsync(String authHeader, ICredentialProvider credentials, IChannelProvider channelProvider, String channelId, AuthenticationConfiguration authConfig, String serviceUrl, HttpClient httpClient)
   at Microsoft.Bot.Connector.Authentication.JwtTokenValidation.ValidateAuthHeader(String authHeader, ICredentialProvider credentials, IChannelProvider channelProvider, String channelId, AuthenticationConfiguration authConfig, String serviceUrl, HttpClient httpClient)
   at Microsoft.Bot.Connector.Authentication.JwtTokenValidation.AuthenticateRequest(IActivity activity, String authHeader, ICredentialProvider credentials, IChannelProvider provider, AuthenticationConfiguration authConfig, HttpClient httpClient)
   at Microsoft.Bot.Connector.Authentication.BuiltinBotFrameworkAuthentication.AuthenticateRequestAsync(Activity activity, String authHeader, CancellationToken cancellationToken)
   at Microsoft.Bot.Builder.CloudAdapterBase.ProcessActivityAsync(String authHeader, Activity activity, BotCallbackHandler callback, CancellationToken cancellationToken)
   at Microsoft.Bot.Builder.Integration.AspNet.Core.CloudAdapter.ProcessAsync(HttpRequest httpRequest, HttpResponse httpResponse, IBot bot, CancellationToken cancellationToken)

To Reproduce

This is part of my code in program.cs:

ConfigOptions config = builder.Configuration.Get<ConfigOptions>()!;
CertificateClient client = new(vaultUri: new Uri(config.KeyVaultUrl), credential: new DefaultAzureCredential());
var certificate = client.DownloadCertificate(config.certificateName).Value;

// Create the CertificateServiceClientCredentialsFactory to use SNI certificate authentication
builder.Services.AddSingleton<ServiceClientCredentialsFactory>((e) => new CertificateServiceClientCredentialsFactory(certificate, config.BOT_ID, null, null, null, true));

// Create the Bot Framework Authentication to be used with the Bot Adapter.
builder.Services.AddSingleton<BotFrameworkAuthentication, ConfigurationBotFrameworkAuthentication>();

// Create the Cloud Adapter with error handling enabled.
// Note: some classes expect a BotAdapter and some expect a BotFrameworkHttpAdapter, so
// register the same adapter instance for all types.
builder.Services.AddSingleton<TeamsAdapter, AdapterWithErrorHandler>();
builder.Services.AddSingleton<IBotFrameworkHttpAdapter>(sp => sp.GetService<TeamsAdapter>()!);
builder.Services.AddSingleton<BotAdapter>(sp => sp.GetService<TeamsAdapter>()!);

I also use the code from this sample, which would meet the same error mentioned above.

Expected behavior

SNI certificate authentication should work.

Screenshots

Referenced packages: image

raych1 commented 2 weeks ago

It's due to the TeamsAdapter class doesn't provide a constructor like the following signature, which would use PasswordServiceClientCredentialFactory as default credential provider. I have to use CloudAdapter class instead to resolve this issue.

CloudAdapter(BotFrameworkAuthentication botFrameworkAuthentication, ILogger logger = null)