Search code examples
authenticationbotframeworkcertificate-authentication

Bot met unauthorized access exception with using SNI certificate


I received the following unauthorized exception when using SNI certificate authentication with Teams.AI library in a Teams bot. The certificate has the 'app id' as the subject, which has been uploaded to the Azure KeyVault. The package version being used is 4.22.3.

Microsoft.Teams.AI.TeamsAdapter: Error: System.UnauthorizedAccessException: Invalid AppId passed on token: 2cf941ce-f641-47ba-b302-f5ad3e854f96
   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)

This is part of my code:

ConfigOptions config = builder.Configuration.Get<ConfigOptions>()!;

// Access key vault
CertificateClient client = new(vaultUri: new Uri(config.KeyVaultUrl), credential: new DefaultAzureCredential());
var certificate = client.DownloadCertificate(config.certificateName).Value;

// MSAL certificate auth.
builder.Services.AddSingleton(
    serviceProvider => ConfidentialClientApplicationBuilder.Create(config.BOT_ID)
        .WithCertificate(certificate, true)
        .Build());

// MSAL credential factory: regardless of secret, cert or custom auth, need to add the line below to enable MSAL.
builder.Services.AddSingleton<ServiceClientCredentialsFactory, MsalServiceClientCredentialsFactory>();

// 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>()!);
builder.Services.AddSingleton<IStorage, MemoryStorage>();

Solution

  • 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)