Microsoft.Agents.Hosting.AspNetCore 0.2.153-alpha

Prefix Reserved
This is a prerelease version of Microsoft.Agents.Hosting.AspNetCore.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package Microsoft.Agents.Hosting.AspNetCore --version 0.2.153-alpha
                    
NuGet\Install-Package Microsoft.Agents.Hosting.AspNetCore -Version 0.2.153-alpha
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Microsoft.Agents.Hosting.AspNetCore" Version="0.2.153-alpha" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Microsoft.Agents.Hosting.AspNetCore" Version="0.2.153-alpha" />
                    
Directory.Packages.props
<PackageReference Include="Microsoft.Agents.Hosting.AspNetCore" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Microsoft.Agents.Hosting.AspNetCore --version 0.2.153-alpha
                    
#r "nuget: Microsoft.Agents.Hosting.AspNetCore, 0.2.153-alpha"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#addin nuget:?package=Microsoft.Agents.Hosting.AspNetCore&version=0.2.153-alpha&prerelease
                    
Install Microsoft.Agents.Hosting.AspNetCore as a Cake Addin
#tool nuget:?package=Microsoft.Agents.Hosting.AspNetCore&version=0.2.153-alpha&prerelease
                    
Install Microsoft.Agents.Hosting.AspNetCore as a Cake Tool

Microsoft.Agents.Hosting.AspNetCore

  • Required package for a bot implementing a full ABS or stand-alone Agent.
  • Provides extension methods to configure the CloudAdapter using ASP.Net DI.

How-to use

builder.Services.AddCloudAdapter();

Basic JWT Token Authentication

AspNet.Core should have Authentication setup to validate incoming tokens. This can be used as an example to perform basic validation for a typical Agent.

public static class AspNetExtensions
{
    private static readonly ConcurrentDictionary<string, ConfigurationManager<OpenIdConnectConfiguration>> _openIdMetadataCache = new();

    /// <summary>
    /// Adds token validation typical for ABS/SMBA and Bot-to-bot.
    /// default to Azure Public Cloud.
    /// </summary>
    /// <param name="services"></param>
    /// <param name="configuration"></param>
    /// <param name="authenticationSection">Name of the config section to read.</param>
    /// <param name="logger">Optional logger to use for authentication event logging.</param>
    /// <remarks>
    /// Configuration:
    /// <code>
    ///   "TokenValidation": {
    ///     "Audiences": [
    ///       "{required:bot-appid}"
    ///     ],
    ///     "TenantId": "{recommended:tenant-id}",
    ///     "ValidIssuers": [
    ///       "{default:Public-AzureBotService}"
    ///     ],
    ///     "IsGov": {optional:false},
    ///     "AzureBotServiceOpenIdMetadataUrl": optional,
    ///     "OpenIdMetadataUrl": optional,
    ///     "AzureBotServiceTokenHandling": "{optional:true}"
    ///     "OpenIdMetadataRefresh": "optional-12:00:00"
    ///   }
    /// </code>
    /// 
    /// `IsGov` can be omitted, in which case public Azure Bot Service and Azure Cloud metadata urls are used.
    /// `ValidIssuers` can be omitted, in which case the Public Azure Bot Service issuers are used.
    /// `TenantId` can be omitted if the Agent is not being called by another Agent.  Otherwise it is used to add other known issuers.  Only when `ValidIssuers` is omitted.
    /// `AzureBotServiceOpenIdMetadataUrl` can be omitted.  In which case default values in combination with `IsGov` is used.
    /// `OpenIdMetadataUrl` can be omitted.  In which case default values in combination with `IsGov` is used.
    /// `AzureBotServiceTokenHandling` defaults to true and should always be true until Azure Bot Service sends Entra ID token.
    /// </remarks>
    public static void AddBotAspNetAuthentication(this IServiceCollection services, IConfiguration configuration, string authenticationSection = "TokenValidation", ILogger logger = null)
    {
        IConfigurationSection tokenValidationSection = configuration.GetSection("TokenValidation");

        List<string> validTokenIssuers = tokenValidationSection.GetSection("ValidIssuers").Get<List<string>>();

        // If ValidIssuers is empty, default for ABS Public Cloud
        if (validTokenIssuers == null || validTokenIssuers.Count == 0)
        {
            validTokenIssuers =
            [
                "https://api.botframework.com",
                "https://sts.windows.net/d6d49420-f39b-4df7-a1dc-d59a935871db/",
                "https://login.microsoftonline.com/d6d49420-f39b-4df7-a1dc-d59a935871db/v2.0",
                "https://sts.windows.net/f8cdef31-a31e-4b4a-93e4-5f571e91255a/",
                "https://login.microsoftonline.com/f8cdef31-a31e-4b4a-93e4-5f571e91255a/v2.0",
            ];

            string tenantId = tokenValidationSection["TenantId"];
            if (!string.IsNullOrEmpty(tenantId))
            {
                validTokenIssuers.Add(string.Format(CultureInfo.InvariantCulture, AuthenticationConstants.ValidTokenIssuerUrlTemplateV1, tenantId));
                validTokenIssuers.Add(string.Format(CultureInfo.InvariantCulture, AuthenticationConstants.ValidTokenIssuerUrlTemplateV2, tenantId));
            }
        }

        List<string> audiences = tokenValidationSection.GetSection("Audiences").Get<List<string>>();
        if (audiences == null || audiences.Count == 0)
        {
            throw new ArgumentException($"{authenticationSection}:Audiences requires at least one value");
        }

        bool isGov = tokenValidationSection.GetValue<bool>("IsGov", false);
        var azureBotServiceTokenHandling = tokenValidationSection.GetValue<bool>("AzureBotServiceTokenHandling", true);

        // If the `AzureBotServiceOpenIdMetadataUrl` setting is not specified, use the default based on `IsGov`.  This is what is used to authenticate ABS tokens.
        var azureBotServiceOpenIdMetadataUrl = tokenValidationSection["AzureBotServiceOpenIdMetadataUrl"];
        if (string.IsNullOrEmpty(azureBotServiceOpenIdMetadataUrl))
        {
            azureBotServiceOpenIdMetadataUrl = isGov ? AuthenticationConstants.GovAzureBotServiceOpenIdMetadataUrl : AuthenticationConstants.PublicAzureBotServiceOpenIdMetadataUrl;
        }

        // If the `OpenIdMetadataUrl` setting is not specified, use the default based on `IsGov`.  This is what is used to authenticate Entra ID tokens.
        var openIdMetadataUrl = tokenValidationSection["OpenIdMetadataUrl"];
        if (string.IsNullOrEmpty(openIdMetadataUrl))
        {
            openIdMetadataUrl = isGov ? AuthenticationConstants.GovOpenIdMetadataUrl : AuthenticationConstants.PublicOpenIdMetadataUrl;
        }

        var openIdRefreshInterval = tokenValidationSection.GetValue<TimeSpan>("OpenIdMetadataRefresh", BaseConfigurationManager.DefaultAutomaticRefreshInterval);

        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(options =>
        {
            options.SaveToken = true;
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ClockSkew = TimeSpan.FromMinutes(5),
                ValidIssuers = validTokenIssuers,
                ValidAudiences = audiences,
                ValidateIssuerSigningKey = true,
                RequireSignedTokens = true,
            };

            // Using Microsoft.IdentityModel.Validators
            options.TokenValidationParameters.EnableAadSigningKeyIssuerValidation();

            options.Events = new JwtBearerEvents
            {
                // Create a ConfigurationManager based on the requestor.  This is to handle ABS non-Entra tokens.
                OnMessageReceived = async context =>
                {
                    var authorizationHeader = context.Request.Headers.Authorization.ToString();

                    if (string.IsNullOrEmpty(authorizationHeader))
                    {
                        // Default to AadTokenValidation handling
                        context.Options.TokenValidationParameters.ConfigurationManager ??= options.ConfigurationManager as BaseConfigurationManager;
                        await Task.CompletedTask.ConfigureAwait(false);
                        return;
                    }

                    string[] parts = authorizationHeader?.Split(' ');
                    if (parts.Length != 2 || parts[0] != "Bearer")
                    {
                        // Default to AadTokenValidation handling
                        context.Options.TokenValidationParameters.ConfigurationManager ??= options.ConfigurationManager as BaseConfigurationManager;
                        await Task.CompletedTask.ConfigureAwait(false);
                        return;
                    }

                    JwtSecurityToken token = new(parts[1]);
                    var issuer = token.Claims.FirstOrDefault(claim => claim.Type == AuthenticationConstants.IssuerClaim)?.Value;

                    if (azureBotServiceTokenHandling && AuthenticationConstants.BotFrameworkTokenIssuer.Equals(issuer))
                    {
                        // Use the Bot Framework authority for this configuration manager
                        context.Options.TokenValidationParameters.ConfigurationManager = _openIdMetadataCache.GetOrAdd(azureBotServiceOpenIdMetadataUrl, key =>
                        {
                            return new ConfigurationManager<OpenIdConnectConfiguration>(azureBotServiceOpenIdMetadataUrl, new OpenIdConnectConfigurationRetriever(), new HttpClient())
                            {
                                AutomaticRefreshInterval = openIdRefreshInterval
                            };
                        });
                    }
                    else
                    {
                        context.Options.TokenValidationParameters.ConfigurationManager = _openIdMetadataCache.GetOrAdd(openIdMetadataUrl, key =>
                        {
                            return new ConfigurationManager<OpenIdConnectConfiguration>(openIdMetadataUrl, new OpenIdConnectConfigurationRetriever(), new HttpClient())
                            {
                                AutomaticRefreshInterval = openIdRefreshInterval
                            };
                        });
                    }

                    await Task.CompletedTask.ConfigureAwait(false);
                },

                OnTokenValidated = context =>
                {
                    logger?.LogDebug("TOKEN Validated");
                    return Task.CompletedTask;
                },
                OnForbidden = context =>
                {
                    logger?.LogWarning(context.Result.ToString());
                    return Task.CompletedTask;
                },
                OnAuthenticationFailed = context =>
                {
                    logger?.LogWarning(context.Exception.ToString());
                    return Task.CompletedTask;
                }
            };
        });
    }
}
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Microsoft.Agents.Hosting.AspNetCore:

Package Downloads
Microsoft.TeamsFx

This package aims to reduce the developer tasks of implementing identity and access to cloud resources down to single-line statements with "zero configuration".

GitHub repositories (1)

Showing the top 1 popular GitHub repositories that depend on Microsoft.Agents.Hosting.AspNetCore:

Repository Stars
microsoft/Agents
The Microsoft 365 Agent SDK simplifies building full stack, multichannel, trusted agents for platforms including M365, Teams, Copilot Studio, and Webchat.
Version Downloads Last updated
0.2.286-alpha 0 4/4/2025
0.2.282-alpha 83 4/3/2025
0.2.277-alpha 107 4/1/2025
0.2.271-alpha 92 3/29/2025
0.2.267-alpha 122 3/28/2025
0.2.257-alpha 127 3/27/2025
0.2.180-alpha 456 3/26/2025
0.2.171-alpha 618 3/21/2025
0.2.162-alpha 162 3/19/2025
0.2.154-alpha 250 3/18/2025
0.2.153-alpha 84 3/15/2025
0.2.151-alpha 106 3/14/2025
0.2.146-alpha 240 3/12/2025
0.2.141-alpha 177 3/8/2025
0.2.137-alpha 254 3/7/2025
0.1.26 1,269 11/18/2024