Allow colon (:) in URL on Azure Web App - azure

We are trying to expose a URL following the ARK standard (Archival Resource Key) from an ASP.NET website hosted on an Azure Web App. But it seems Azure Web Apps do not support colons (:) in URL path segments, as we are getting an HTTP 500 error code with message "The page cannot be displayed because an internal server error has occurred." when trying to type a URL like http://example.azurewebsites.net/ark:/123/456.
Note that we did update our web.config's RequestPathInvalidCharacters setting to allow colons in URIs, and it works locally. Also, colons in URIs may not be very frequent but are valid, even wikipedia uses them.
Edit:
Well after a few tests, it looks like the issue happens only when the colon is at the end of a path segment (e.g. : http://example.azurewebsites.net/ark:/123/456). Otherwise, the requestPathInvalidCharacters setting applies. No luck for us: the ARK standard specifies that the colon be placed at the end of a path segment.
Note that the error displayed in this case is different from the error when requestPathInvalidCharacters has its default value and a colon is placed in the middle of a path segment. Here the error seems to happen even before the request enters the IIS pipeline (maybe at the Azure level). You can test the above URL for a quick display of the problem.

Sorry for my origin reply. I try it with Azure MVC API. I configure the map route as following:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}:{id}",
defaults: new { id = RouteParameter.Optional }
);
And add the requestPathInvalidCharacters in web.config:
<httpRuntime targetFramework="4.5.2" requestPathInvalidCharacters=""/>
ValuesController:
// GET api/values/5
public string Get(int id)
{
return id.ToString();
}
After deploy to Azure I could get the result from the URL:http://.azurewebsites.net/api/values:5

Related

Problems authenticating with MSAL and Azure B2C in a Xamarin.Forms app

I'm having some difficulty getting one of the sample Xamarin.Forms/Azure applications to work with my own Azure B2C tenant, specifically active-directory-b2c-xamarin-native.
I was able to get the sample to work out of the box, my only change being to update all the XF NuGet packages. At this point both the Android (on my Google Pixel) and UWP versions worked perfectly; on iOS I was able to log in/out and edit the profile (it still has the known issue that iPhoneSimulator doesn't properly save tokens in the keychain, so the API and caching doesn't work, but i'm ignoring that for now until i can get an actual iPhone). The problems started when I tried to set up and use my own B2C tenant, according to the instructions in the readme file. Since the original sample works, it's safe to assume that the code is ok; the only changes I made were to the magic strings at the top of App.cs, and the redirect URI's stored in AndroidManifest.xml and Info.plist. So the working theory is that I either entered one of those strings wrong, or the B2C setup is wrong. I've gone over this multiple times now and I can't find the issue. I'm willing to bet these are all caused by the same mistake on my part, though.
Problem 1 (solved). UWP app does not allow login. Instead when the embedded browser opens I get the message "We can't connect to the service you need right now. Check your network connection or try this again later", followed by an "MsalException: WAB authentication failed" dialog once I dismiss the browser.
This was the only issue I was able to fix so far, either by commenting out this line in the UWP.MainPage constructor:
UserDetailsClient.Core.App.PCA.RedirectUri = WebAuthenticationBroker.GetCurrentApplicationCallbackUri().ToString();
or by adding the value returned by that GetCurrentApplicationCallbackUri() call (which is something like "ms-app://s-1-15-2-900855338....") to the Custom Redirect URI list of the UI app in B2C. I would prefer simply removing the line of code, but that begs the question as to why that line of code was needed in the first place. Perhaps someone can suggest why using the ms-app:// redirect on the backend might be preferable to the msalXXXX://auth used by the other platforms. I have no idea why the original sample worked with the ms-app:// redirect; perhaps that string is actually constant across all apps and is already defined in the sample's B2C tenant.
Problem 2. Having gotten past the UWP login issue now everything works on that platform EXCEPT for the API call. I get a 401 Unauthorized.
The API code is taken straight from the tutorial Develop Cloud Connected Mobile Apps with Xamarin and Microsoft Azure; it's just the backend from Chapter 1, with the [Authorize] attribute added to the TodoItemController. (All of the Chapter 1 code works, btw) App Service Authentication is still turned off on the API itself (not the B2C tenant) in Azure. If I remove the Authorize attribute from the TodoItemController, it works, provided I also pass in the additional header ZUMO-API-VERSION=2.0.0. Adding the header does not help with the 401, though.
Since I'm able to login, I'm guessing I have a valid access token, it's just not what the backend is expecting. Again, this works on the sample, so I don't know how my app differs. I suspect this issue also affects iOS and Android, but I'm not sure because unable to complete the login on those platforms. Which brings me to...
Problem 3. On Android & iOS, on clicking SIGN IN the app opens the system browser and I'm able to login in, but the subsequent redirect doesn't happen and the app remains in it's initial state. When debugging, the line after the call to App.PCA.AcquireTokenAsync() is never reached. No exception is raised.
From what I understand this is generally due to either the redirect URI being improperly formed or forgetting to add the platform-specific redirect code (intent-filter on Android, or OpenUrl on iOS). I've double-checked the URI a half-dozen times, and the code has to be correct since the sample worked. I did notice the ActivityManager START entry in the Android logcat, so the browser is sending the redirect, but the app isn't responding to it for whatever reason. Note also that the UWP client DOES work using that same msalXXXX://auth URI (this is why I bothered to explain problem 1 above)
Visual Studio 2017 15.8.6
Xamarin.Forms 3.2.0.871581
Microsoft.Identity.Client 1.1.4-preview
Below is the list of strings from App.cs, as well as screenshots from my B2C setup. Any help would be greatly appreciated!
public static string Tenant = "myapp.onmicrosoft.com";
public static string ClientID = "d43c8xxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
public static string PolicySignUpSignIn = "B2C_1_emailPolicy";
public static string PolicyEditProfile = "B2C_1_profileEditPolicy";
public static string PolicyResetPassword = "B2C_1_passwordResetPolicy";
public static string[] Scopes = { "https://myapp.onmicrosoft.com/api/read" };
public static string ApiEndpoint = "https://myapp.azurewebsites.net/tables/todoItem";
public static string AuthorityBase = $"https://login.microsoftonline.com/tfp/{Tenant}/";
public static string Authority = $"{AuthorityBase}{PolicySignUpSignIn}";
public static string AuthorityEditProfile = $"{AuthorityBase}{PolicyEditProfile}";
public static string AuthorityPasswordReset = $"{AuthorityBase}{PolicyResetPassword}";

ASP.NET MVC routes with "." not working in Azure

I have simple route map like:
routes.MapRoute("Test", "test/{action}/{id}", new {controller = "Test", action = "Index", id = ""});
My route paths are like:
"/test/do-something/1.0.1"
Which works completely fine in local testing and self hosted .NET 4.5 on IIS7+
However, when I host it in Azure, it seems to have issues with the ID containing two ".", telling me that "The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.".
When I change the path to "/test/do-something/1" it works on Azure as well.
Why does Azure seem to prohibit ID's with "." and what can I do about it?
I would recommend using '-' in your id as opposed to '.' (periods), it's more friendly in terms of SEO.
If you really want to get it working with periods, you could use a tool called URLScan.
What is URLScan?
There is an option to configure:
AllowDotInPath=0
By default, this option is set to 0. If this option is set to 0,
URLScan rejects any request that contains multiple periods (.). This
prevents attempts to disguise requests for dangerous file name
extensions by putting a safe file name extension in the path
information or query string portion of the URL. For example, if this
option...
Here is a link to the configuration.

Deployed my Breeze app to Azure Web Sites and Metadata query fails

Just starting off with Breeze and Azure. I downloaded the sample app and added my own controllers. On my local machine it works just fine. When I deploy to my Azure site, I keep getting the following error in the logging section of the page: Query failed: Metadata query failed for: api/CoreData/Metadata; An error has occurred.
I have a controller named Products that simply returns a view. The view contains the js calls to my CoreData ApiController. Follows the sample.
The only thing logged on the server is the following:
At first I was using EF to access data, but have changed to just creating an in-memory object and returning it so as to eliminate db issues.
The URL is http://acapella.azurewebsites.net/products. I've spent quite a bit of time trying to diagnose and research, but feel that I'm overlooking something simple.
Any help or suggestions would be appreciated.
An Azure web site is a free, relatively easy way to deploy a Breeze application where you can test it on a variety of mobile devices and experience your app's responsiveness (or lack thereof).
I have had good success pushing a Breeze app to an Azure web site but there were many stumbles including some that looked like yours.
Two thoughts. First, you'll want to turn "Custom errors off" in your Web.config.
<configuration>
<system.web>
<customErrors mode="Off"/>
</system.web>
</configuration>
My second recommendation: take a look at John Papa's post on deploying an MVC Web API app to an Azure web site. It is excellent. And I know it works.
I hope to have a video on the process very soon.
The first thing you can do is return the exception. In your Breeze controller do this:
[HttpGet]
public string Metadata()
{
try
{
return _contextProvider.Metadata();
}
catch (Exception e)
{
return e.Message + Environment.NewLine + Environment.NewLine + e.StackTrace;
}
}
That made it clear to me something was wrong with my connection string. The exception I got was:
Format of the initialization string does not conform to specification starting at index 0.
My connection string locally seemed ok, but the problem was on Azure. My web.release.config had a correct transform, but when publishing, Visual Studio would add another connection string. You can check this by connecting with FTP to your Azure site and looking at your web.config. I fixed it by selecting the correct connection string when publishing:
After that, there still seem to be two connection strings in my uploaded web.config, but at least it works.

Disabling request validation on Azure Websites

My node.js application runs nicely on my own machine, however, after pushing it up to an Azure WebSite using Git, I'm getting request validation problems.
Some of my requests are trapped by the IIS validation process. The fix is to add this to the web.config:
<httpRuntime requestPathInvalidCharacters=""/>
I downloaded the web.config from the site\wwwroot folder of my website using FTP, added it to the repo, added the new element in the XML, and pushed it back up to Azure.
My web.config file seems to have been overridden by the default.
Is there a way of changing this behaviour? Or another way of turning off request validation? Or am I just being thick?
UPDATE
I take it all back, it seems to be express which is blocking the request. However, the question still stands as 'how do I customise my web.config?'
Could you try setting a custom validation type? Like this:
<httpRuntime requestPathInvalidCharacters=""
requestValidationType="MyValidator, MyAssembly"/>
And the class:
public class MyValidator : RequestValidator
{
protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
{
validationFailureIndex = 0;
return true;
}
}

This controller won't show up in Web Api on Azure

namespace StorageRoleMVC4.Controllers
{
public class SearchController : ApiController
{
public Dictionary<string, string> Get([FromUri] string searchString, [FromUri] string searchObject)
{
var searchHelper = new SearchStorageHelper();
var objectList = searchHelper.Retrieve(searchString, searchObject);
return objectList;
}
}
}
Is there anything about this controller that makes it unreachable once it's deployed (to an Azure web role)? I just get a 404 error when I try to reach it. It works great on the local emulator.
The last 2 times I've deployed my project, all the controllers in my web service have returned 404 errors for several hours, until the project seems to fix itself. I'm not sure why, but it might be related.
UPDATE
There is a WARNING in the event log on the web role VM after I publish:
The application '/' belonging to site '1273337584' has an invalid AppPoolId 'ea7a2e15-9390-49e1-a16b-67ff1cdb7dcb' set. Therefore, the application will be ignored.
This is the id of my site, but the AppPoolId is not correct. Changing the app pool turns the 404 into a 502.
Also, after publishing, the World Wide Web Publishing Service is turned off. When I turn it on and do an IIS reset, after the reset it's turned off again.
When I reboot the web role VM, most of the controllers work again, and the World Wide Web Publishing Service is turned on. But still, this SearchController doesn't work. Or any other new controllers I've created since this problem started happening.
Well, after a ridiculous amount of unsuccessful troubleshooting, I just rolled back to an earlier version of the code and found that it didn't read the web service when I deployed it. So I started over with that version and re-built the delta.
This involved removing a few web.config entries and removing some libraries, creating a few classes and referencing them in the global.asax (I think that's where it was) in order to override te Authorize attribute...
If anyone has a better answer, I will switch the answer to what you post.

Resources