Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R Shiny app on Azure App Services with Active Directory Integration

I am currently deploying an R Shiny app to Azure App Service, and restricting access via Active Directory integration (which seems to use the Azure easyauth proxy under the hood).

When I deploy the rocker/shiny:3.6.0 or rocker/shiny:4.0.0 container to simply see the "hello world" page the deployment is successful.

When I turn on Active Directory Authentication, the website hangs, then returns a 500.

I have attached the error log at the bottom of this message, but I don't think it has any useful information with respect to things I have control over.

Further investigation shows that if I deploy rocker:shiny:3.5.2 or below, everything works as expected. If I deploy rocker/shiny:3.6.0 or above, I get a 500 and the website hangs.

Deploying rocker/shiny:3.5.3 results in the symptoms reported in these questions:

  • How do I get Shiny-server to working with Azure Active Directory
  • How to disable websocket on Shiny?

So I am fairly sure the root cause is different.

To me this indicates changes in the rocker/shiny:3.6.0 packages and above which is stopping the authentication from working, but I am afraid this is where my debugging ability stops!

My questions are - am I actually just doing something wrong, is this a known issue, and how do I report it (and to who?!).

Thanks for any help,

Akhil

App Service Error Message

fail: Middleware[0]
      Unhandled exception in request pipeline: System.Net.Http.HttpRequestException: An error occurred while sending the request.
       ---> System.IO.IOException: The response ended prematurely.
         at System.Net.Http.HttpConnection.FillAsync()
         at System.Net.Http.HttpConnection.ReadNextResponseHeaderLineAsync(Boolean foldedHeadersAllowed)
         at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
         --- End of inner exception stack trace ---
         at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
         at System.Net.Http.HttpConnectionPool.SendWithNtConnectionAuthAsync(HttpConnection connection, HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
         at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
         at System.Net.Http.DiagnosticsHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
         at Microsoft.Azure.AppService.MiddlewareShim.Startup.ForwardRequestAsync(HttpContext context) in /EasyAuth/Middleware.Host/Startup.cs:line 197
         at Microsoft.Azure.AppService.MiddlewareShim.Startup.OnRequest(HttpContext context) in /EasyAuth/Middleware.Host/Startup.cs:line 151
fail: Microsoft.AspNetCore.Server.Kestrel[13]
      Connection id "...", Request id "...": An unhandled exception was thrown by the application.
System.Net.Http.HttpRequestException: An error occurred while sending the request.
 ---> System.IO.IOException: The response ended prematurely.
   at System.Net.Http.HttpConnection.FillAsync()
   at System.Net.Http.HttpConnection.ReadNextResponseHeaderLineAsync(Boolean foldedHeadersAllowed)
   at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithNtConnectionAuthAsync(HttpConnection connection, HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.DiagnosticsHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
   at Microsoft.Azure.AppService.MiddlewareShim.Startup.ForwardRequestAsync(HttpContext context) in /EasyAuth/Middleware.Host/Startup.cs:line 197
   at Microsoft.Azure.AppService.MiddlewareShim.Startup.OnRequest(HttpContext context) in /EasyAuth/Middleware.Host/Startup.cs:line 151
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application
like image 464
Akhil Nair Avatar asked Dec 04 '20 15:12

Akhil Nair


People also ask

What is R-shiny/app?

r-shiny/ ├── App │ ├── global.R │ ├── server.R │ └── ui.R └── Dockerfile Within the r-shiny directory, we have a Dockerfile, and a sub-directory called App, which contains the actual Shiny application. 1. A globals.R file defines libraries, our database connection details and some dynamic SQL queries based on slider values.

Why do I have to register microsoft365r inside a shiny app?

The default Microsoft365R app registration only works when the package is used on a local machine; it does not support running in a remote server. Because of this, when you use Microsoft365R inside a Shiny app, you (or your friendly local sysadmin) must register that app in AAD.

What is the client secret for a shiny app?

It’s recommended to use a webapp redirect for a Shiny app, as the client secret helps prevent third parties from hijacking your app registration. The client secret is also set as part of the app registration. The intended audience of your app, ie, who is allowed to use it.

What are the benefits of integrating RStudio connect with Azure AD?

Integrating RStudio Connect with Azure AD provides you with the following benefits: You can control in Azure AD who has access to RStudio Connect. You can enable your users to be automatically signed-in to RStudio Connect (Single Sign-On) with their Azure AD accounts. You can manage your accounts in one central location - the Azure portal.


1 Answers

There is a known issue where some recent versions of node (or some other webservers) has a maximum capacity of 8KB for headers.

When you enable EasyAuth, it adds some large headers to the request.

To overcome this, you can use on of the 2 solutions:

1. Use WEBSITE_AUTH_DISABLE_IDENTITY_FLOW App Settings

When this variable is set to true it disables assigning the thread principal identity, which will remove one of the largest headers added to the request X-MS-CLIENT-PRINCIPAL, which is generally used by .NET Framework and Function apps.

However, it contains the same claims as the id_token. A Base64-encoded JSON object that we can decode to get the information. If you want access to the id_token JWT directly, you can use X-MS-TOKEN-AAD-ID-TOKEN header.

Reference: https://github.com/cgillum/easyauth/wiki/Advanced-Application-Settings

2. Raise the limit of the header size

This can be done using the NODE_OPTIONS variable, as described in the following github issue here.

Example: NODE_OPTIONS=--max-http-header-size=16384

like image 173
Saif Badran Avatar answered Oct 22 '22 11:10

Saif Badran