3
votes

I am hosting my BOT Framework V4 BOT on IIS. Server Configuration is as below

  1. Windows Server 2012 R2
  2. IIS 8.5

I have also installed dotnet-hosting-2.2.1-win.exe which is essential in order to host BOT V4. I have set application pool as No Managed Code. I have set the path of the folder where Startup.cs file resides. Also Please find the attachment of logs generated by BOT. Still, it is not working the error is as below

HTTP Error 403.14 - Forbidden The Web server is configured to not list the contents of this directory.

Detailed Error Information:
Module     DirectoryListingModule
Notification       ExecuteRequestHandler
Handler    StaticFile
Error Code     0x00000000
Requested URL      https://myServer/ConfRoomBOT/
Physical Path      ProjectPath
Logon Method       Anonymous
Logon User     Anonymous
Request Tracing Directory      C:\inetpub\logs\FailedReqLogFiles

Below is the web.config code

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <handlers>
        <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
      </handlers>
      <aspNetCore processPath="dotnet" arguments=".\ConfRoom.dll" stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" />
    </system.webServer>
  </location>
  <system.net>
     <defaultProxy useDefaultCredentials="false">
        <proxy usesystemdefault="False" proxyaddress="http://xx.xxx.xx.xxx:8080" bypassonlocal="True" />
      </defaultProxy>
  </system.net>
</configuration>

Below are the logs generated by BOT

Hosting environment: Production Content root path: E:\Project\DotNetCoreApps\ConfRoomPub\WithPII\publish Now listening on: http://127.0.0.1:41826 Application started. Press Ctrl+C to shut down. info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1] Request starting HTTP/1.1 GET http://example.com/ConfRoom/ info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1] Request starting HTTP/1.1 GET http://example.com/ConfRoom/ info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[2] Sending file. Request path: '/default.htm'. Physical path: 'E:\Project\DotNetCoreApps\ConfRoomPub\WithPII\publish\wwwroot\default.htm' info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[6] The file /default.htm was not modified info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2] Request finished in 184.4402ms 304 text/html info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2] Request finished in 188.1919ms 200 text/html info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1] Request starting HTTP/1.1 POST http://example.com/ConfRoom/api/messages application/json; charset=utf-8 373 info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1] Request starting HTTP/1.1 POST http://example.com/ConfRoom/api/messages application/json; charset=utf-8 359 fail: Microsoft.AspNetCore.Server.Kestrel[13] Connection id "0HLJNNKCOIPS7", Request id "0HLJNNKCOIPS7:00000002": An unhandled exception was thrown by the application. System.InvalidOperationException: IDX20803: Unable to obtain configuration from: 'https://login.botframework.com/v1/.well-known/openidconfiguration'. ---> System.IO.IOException: IDX20804: Unable to retrieve document from: 'https://login.botframework.com/v1/.well-known/openidconfiguration'. ---> System.Net.Http.HttpRequestException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond ---> System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken) --- End of inner exception stack trace --- at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken) at System.Threading.Tasks.ValueTask1.get_Result() at System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken) at System.Threading.Tasks.ValueTask1.get_Result() at System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask1 creationTask) at System.Threading.Tasks.ValueTask1.get_Result()
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts) at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String address, CancellationToken cancel) --- End of inner exception stack trace --- at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String address, CancellationToken cancel) at Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfigurationRetriever.GetAsync(String address, IDocumentRetriever retriever, CancellationToken cancel) at Microsoft.IdentityModel.Protocols.ConfigurationManager1.GetConfigurationAsync(CancellationToken cancel) --- End of inner exception stack trace --- at Microsoft.IdentityModel.Protocols.ConfigurationManager1.GetConfigurationAsync(CancellationToken cancel) at Microsoft.IdentityModel.Protocols.ConfigurationManager1.GetConfigurationAsync() at Microsoft.Bot.Connector.Authentication.JwtTokenExtractor.ValidateTokenAsync(String jwtToken, String channelId) at Microsoft.Bot.Connector.Authentication.JwtTokenExtractor.GetIdentityAsync(String scheme, String parameter, String channelId) at Microsoft.Bot.Connector.Authentication.JwtTokenExtractor.GetIdentityAsync(String authorizationHeader, String channelId) at Microsoft.Bot.Connector.Authentication.ChannelValidation.AuthenticateChannelToken(String authHeader, ICredentialProvider credentials, HttpClient httpClient, String channelId) at Microsoft.Bot.Connector.Authentication.ChannelValidation.AuthenticateChannelToken(String authHeader, ICredentialProvider credentials, String serviceUrl, HttpClient httpClient, String channelId) at Microsoft.Bot.Connector.Authentication.JwtTokenValidation.ValidateAuthHeader(String authHeader, ICredentialProvider credentials, IChannelProvider channelProvider, String channelId, String serviceUrl, HttpClient httpClient) at Microsoft.Bot.Connector.Authentication.JwtTokenValidation.AuthenticateRequest(IActivity activity, String authHeader, ICredentialProvider credentials, IChannelProvider provider, HttpClient httpClient) at Microsoft.Bot.Builder.BotFrameworkAdapter.ProcessActivityAsync(String authHeader, Activity activity, BotCallbackHandler callback, CancellationToken cancellationToken) at Microsoft.Bot.Builder.Integration.AspNet.Core.Handlers.BotMessageHandler.ProcessMessageRequestAsync(HttpRequest request, IAdapterIntegration adapter, BotCallbackHandler botCallbackHandler, CancellationToken cancellationToken) at Microsoft.Bot.Builder.Integration.AspNet.Core.Handlers.BotMessageHandlerBase.HandleAsync(HttpContext httpContext) at Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Server.IISIntegration.IISMiddleware.Invoke(HttpContext httpContext) at Microsoft.AspNetCore.Builder.Extensions.UsePathBaseMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication1 application) fail: Microsoft.AspNetCore.Server.Kestrel[13] Connection id "0HLJNNKCOIPS6", Request id "0HLJNNKCOIPS6:00000002": An unhandled exception was thrown by the application. System.InvalidOperationException: IDX20803: Unable to obtain configuration from: 'https://login.botframework.com/v1/.well-known/openidconfiguration'.
at Microsoft.IdentityModel.Protocols.ConfigurationManager
1.GetConfigurationAsync(CancellationToken cancel) at Microsoft.IdentityModel.Protocols.ConfigurationManager1.GetConfigurationAsync() at Microsoft.Bot.Connector.Authentication.JwtTokenExtractor.ValidateTokenAsync(String jwtToken, String channelId) at Microsoft.Bot.Connector.Authentication.JwtTokenExtractor.GetIdentityAsync(String scheme, String parameter, String channelId) at Microsoft.Bot.Connector.Authentication.JwtTokenExtractor.GetIdentityAsync(String authorizationHeader, String channelId) at Microsoft.Bot.Connector.Authentication.ChannelValidation.AuthenticateChannelToken(String authHeader, ICredentialProvider credentials, HttpClient httpClient, String channelId) at Microsoft.Bot.Connector.Authentication.ChannelValidation.AuthenticateChannelToken(String authHeader, ICredentialProvider credentials, String serviceUrl, HttpClient httpClient, String channelId) at Microsoft.Bot.Connector.Authentication.JwtTokenValidation.ValidateAuthHeader(String authHeader, ICredentialProvider credentials, IChannelProvider channelProvider, String channelId, String serviceUrl, HttpClient httpClient) at Microsoft.Bot.Connector.Authentication.JwtTokenValidation.AuthenticateRequest(IActivity activity, String authHeader, ICredentialProvider credentials, IChannelProvider provider, HttpClient httpClient) at Microsoft.Bot.Builder.BotFrameworkAdapter.ProcessActivityAsync(String authHeader, Activity activity, BotCallbackHandler callback, CancellationToken cancellationToken) at Microsoft.Bot.Builder.Integration.AspNet.Core.Handlers.BotMessageHandler.ProcessMessageRequestAsync(HttpRequest request, IAdapterIntegration adapter, BotCallbackHandler botCallbackHandler, CancellationToken cancellationToken) at Microsoft.Bot.Builder.Integration.AspNet.Core.Handlers.BotMessageHandlerBase.HandleAsync(HttpContext httpContext) at Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Server.IISIntegration.IISMiddleware.Invoke(HttpContext httpContext) at Microsoft.AspNetCore.Builder.Extensions.UsePathBaseMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication1 application) info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2] Request finished in 21679.9889ms 500 info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2] Request finished in 14958.2414ms 500 info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1] Request starting HTTP/1.1 POST http://127.0.0.1:41826/CONFROOM/iisintegration 0 info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2] Request finished in 0.373ms 202 Application is shutting down...

Kindly help. Thank you.

3
Can you please update your question to include your web.config file?Drew Marsh
This is a BOT Framework V4 application which runs on .NET core 2.0, so there is no web.config file, it have appsettings.json file.Amol Pawar
Are you sure it's not working? By default you cannot access the directory, thus the 403.14. Did you try to post to the /api/messages endpoint using the emulator?Sotiris Koukios-Panopoulos
I also came to know and as suggested by Drew, BOT itself generate the web.config file at the time of publishing. Sorry for the late reply, but my issue still exists. I have added web.config code and logs generated by BOT.Amol Pawar
@drew-marsh Any help is appreciated.Amol Pawar

3 Answers

0
votes

I think Drew Marsh found the problem in his reply, this is probably a web.config issue.

If you are going to be hosting a .net core app in IIS, IIS will still require a a web.config in the application directory which will alteast have a handler mapping and a aspNetCore path.

Basically, IIS has to know that the application is a .net core app and what code to run.

I might be wrong, but that looks like its treating everything like a static file.

I get this error if I remove the web.config from a working .net core app hosted in IIS.

Looks nearly identical to your error, and I made a similar mistake.

I've generally had good luck with publishing my project as a IIS Web Deploy Package. That tends to create all the necessary bits.

A working web.confg may look something like this.

<configuration>
      <system.webServer>
        <handlers>
          <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
        </handlers>
        <aspNetCore processPath="dotnet" arguments=".\blagh.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" />
      </system.webServer>
</configuration>
0
votes

According to the exception details you added to your question, this is the root problem:

An unhandled exception was thrown by the application. System.InvalidOperationException: IDX20803: Unable to obtain configuration from: 'https://login.botframework.com/v1/.well-known/openidconfiguration'. ---> System.IO.IOException: IDX20804: Unable to retrieve document from: 'https://login.botframework.com/v1/.well-known/openidconfiguration'. ---> System.Net.Http.HttpRequestException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond

Now, if you just go navigate to that with your browser, you should see there's no problem getting a response that includes this JSON metadata document describing the OpenID configuration:

{
  "issuer": "https://api.botframework.com",
  "authorization_endpoint": "https://invalid.botframework.com",
  "jwks_uri": "https://login.botframework.com/v1/.well-known/keys",
  "id_token_signing_alg_values_supported": [
    "RS256"
  ],
  "token_endpoint_auth_methods_supported": [
    "private_key_jwt"
  ]
}

The good news is your bot seems to be executing fine. This actually indicates that the bot ran and got far enough that it was authenticating the request, so that's a good sign. What this exception smells like to me is that wherever your bot is hosted may not have the abillity to make outbound requests to the internet. Is that possible? It needs that to be able to verify the authenticity of the JWT token coming from bot framework and, ultimately, will need it to send responses back to clients through the bot framework. You may need to work to whitelist HTTP requests to the botframework.com domain.

0
votes

It was an authentication issue of IIS. We had to use user account which has all privileges i.e administrator to configure below things

  1. Application Pool Identity
  2. IIS authentication and authorization of Hosted application (Connect as).

I removed all the code which I wrote for authentication like OAuth etc.

Thanks all for your time.