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:
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
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
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.
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.
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With