I have a apiapp in azure that the webapp is calling. I have the apiapp setting cookies on the webapp for state, this all works fine when its the same domain but im moving to Azure App Services and the cookies are coming back in the headers with the domain set but nothing is being displayed on the cookies tab in chromium. Both sites are Https ... is it perhaps that CORS is setup wrong. I am using Node for the api if that means anything and right now i have the domains in the below screen shots hard coded.
The api app has the CORS origin set to https://ep-webapp.azurewebsites.net in app services.
The locale cookie is being set by the webapp
So... is this even possible .. is there a better way to do this
I was able to route the calls in Azure using a reverse proxy...
https://ruslany.net/2014/05/using-azure-web-site-as-a-reverse-proxy/
WEBSITE_PRIVATE_EXTENSIONS set to 1 in the App Settings for the site.
<rule name="Proxy" stopProcessing="true">
<match url="^api/?(.*)"/>
<action type="Rewrite" url="https://apiapp.azurewebsites.net/{R:1}"/>
</rule>
Related
We have an Angular web application running on Azure. The backend is Dot Net Core 3.1. The Authentication is done through Azure AD. What is happening is the following steps
User logs into the web site and navigates to a page. Everything is working as expected
The user logs out, but does not close the tab. The Logout screen is shown as expected
The user opens a new tab and navigates to the web site
The user is NOT prompted for a login and when the user navigates to page they get error
Access to XMLHttpRequest at 'https://login.microsoftonline.com/2aa666ca-a53c-4274-bfcc-41b83867d22a/oauth2/authorize?client_id=794424bb-0ad2-41f8-b007-b71ed576b793&redirect_uri=https%3A%2F%2Fmydomain.azurewebsites.net%2Fsignin-oidc&response_type=id_token&scope=openid%20profile&response_mode=form_post&nonce=637782164067215548.NzQ4MWQxNjgtYjdlZS00OTlmLWIwYzctM2NhZWRkZjdhMTZiYzdmNjljOTEtNTk3OS00NDlhLWEzZjgtODZkN2YyZDZmYzlh&state=CfDJ8IE9b1M0cDdJqtQPg1_KxRR0vlYAN1zOfKzhpzhdzqvcX_XGygV8nincOzoVYDPPyZWnbh5SrGMDZhQfmUDlO4wQ41v_7Q_gJCUHftetejZZQZTS7Uhn-IVBRysh36hvldRY2pxcZBKCQHLYkKMnR2my9R0TqsaqEAI4gGNUUHwa8fJnv4xj0lkMJq_DORhJS4AwLMhtQWGvuIp0gzQ_cGR0gjGZvMRMTaBZunGBDexThOzzbAyQJTCJuNxUUB_tvAm0cFEVWb3lTPYRgk1ARnagmg7a6GDFrCnXT7vT_3VJjUyMzrazbt1xeRtrs1AdlUIX1fnnFsGZPGUBA3kYvzTyEgVkm97FGBTPgeGZAP3W&x-client-SKU=ID_NETSTANDARD2_0&x-client-ver=5.5.0.0' (redirected from 'https://mydomain.azurewebsites.net/api/profileTypes?_=1642619606751') from origin 'https://mydomain.azurewebsites.net' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
If the user refreshes the page, then they are forced to login and everything begins working again
I have tried adding in CORS as directed on other questions and other websites as follows
In the ConfigureService function of the startup.cs The following code is present
services.AddCors(o => o.AddPolicy("CorsPolicy", builder =>
{
builder
.WithOrigins(new[] { "http://YOUR_FRONTEND_ORIGIN" })
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
}));
In the Configure function of the startup.cs is the following code
app.UseCors("CorsPolicy");
I am confused as to why CORs would even come into play as everything is on the same Azure subscription, but I added the above code and it does not change anything. Searching the internet give mainly the same or similar implementations as above.
I am not sure how to proceed or even what questions to ask, so any help would be appreciated
Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism which basically allows server to indicate any origins other than its original url or scheme or domain or port .But cors settings may also vary from different browsers which may cause this error.
In case of Azure App Service it sets “AppServiceAuthSession” cookie for authenticated session with browser. The web application may use XMLHttpRequest / AJAX request inside the app and the request sent may contain the AppServiceAuthSession cookie. When this cookie is still present in the browser and the web page pointing to the page of app may not be the original url and which might be the possible cause of error.When this cookie is not present in the request, Azure App Service will redirect the request to Azure AD for login that is why when you referesh it, it works.
If the browser is enabled with cors ,it makes a pre-flight cors check to the specified url and gets the access-control-allow-origin headers, we can modify this headers accordingly,if origin restriction is not required.
Try to insert the http protocol present in the asp.net Web Api backend, in the Web.config between the <system.webServer> </ system.webServer> tags,
Example:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>
</system.webServer>
and you can try enable access to all origins from browser settings .
Please check this reference access to xmlhttprequest has been blocked by cors policy Code Example (codegrepper.com) if you can enable credentails to true and by using cors variable to use in app.use(cors).
References:
Cross-origin XMLHttpRequest - Chrome Developers
express - Angular CORS request blocked - Stack Overflow
I have website that is Hosted in a Azure App Service. are there any options in azure so that I can put a password on the website. Ideally without changing the websites code.
Just a basic password or user name and password, doesn't need to be google or facebook login or AD login.
It is a .net based website and I have seen a few options to do this, but it means I have to change the code of the website in someway or another.
Surely with all that sophisticated cloud technology, I can go in to the portal and set a password at a server level? - Or is the only way to make some kind of change to the application?
It is possible to enable Basic Authentication for Azure Web Apps with some settings in the applicationHost.xdt. You can load some modules in this file on the start of your Web App.
Steps:
Navigate to your WebApp in the Azure Portal
In the left menu, search for the header Development Tools an select Advanced Tools (Kudu)
Use the Debug Console > CMD tool, to navigate to the WebApp directory: \home\site
Create a file named: applicationHost.xdt
Paste the following:
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<location path="%XDT_SITENAME%" xdt:Locator="Match(path)">
<system.webServer>
<rewrite xdt:Transform="InsertIfMissing">
<allowedServerVariables xdt:Transform="InsertIfMissing">
<add name="RESPONSE_WWW_AUTHENTICATE" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
</allowedServerVariables>
<rules xdt:Transform="InsertIfMissing">
<rule name="BasicAuthentication" stopProcessing="true" xdt:Transform="InsertIfMissing" xdt:Locator="Match(name)">
<match url=".*" />
<conditions>
<add input="{HTTP_AUTHORIZATION}" pattern="^Basic dXNlcjpwYXNzd29yZA==" ignoreCase="false" negate="true" />
</conditions>
<action type="CustomResponse" statusCode="401" statusReason="Unauthorized" statusDescription="Unauthorized" />
<serverVariables>
<set name="RESPONSE_WWW_AUTHENTICATE" value="Basic realm=Project" />
</serverVariables>
</rule>
</rules>
</rewrite>
</system.webServer>
</location>
</configuration>
Change the Basic Auth to your liking (default in example is: user:password)
Make sure the web.config rewrite rules don't contain <clear /> as this wil remove the effects from the applicationHost.xdt file
Save the file and Stop and Start your WebApp (a simple Restart will not suffice)
Notes:
Not sure if this works on Linux based WebApps..
You can add this step to you're deployment pipelines by using FTP
Update: I've noticed issues with applicationHost.xdt while using it on secondary Web App slots. Only the primary slot seems to work.
PS: Cross-post from my answer here.
You can use Authentication and authorization in Azure App Service.
Authentication/Authorization was previously known as Easy Auth.
Azure App Service provides built-in authentication and authorization support, so you can sign in users and access data by writing minimal or no code in your web app, RESTful API, and mobile back end, and also Azure Functions. This article describes how App Service helps simplify authentication and authorization for your app.
Source: Authentication and authorization in Azure App Service and Azure Functions.
EDIT:
The above is a solution to have a password protected App Service without changing any code whatsoever. At this point there is no alternative, as you can see in the open feedback issue Allow HTTP Basic authentication on basic apps
Hi everyone, we understand the demand for this feature, but we do not plan to support authentication at this level. We suggest using EasyAuth for this scenario.
https://learn.microsoft.com/en-us/azure/app-service/overview-authentication-authorization
EDIT 2:
This method forces the user to use google or facebook, etc...
This is not true. You can also create a user in your Azure Active Directory and use that one with Easy Auth. The username would be something like username#<YOUR-TENANT>.onmicrosoft.com
I am building a new common Authentication module for my application. For this, I need to intercept requests coming to API layer, route to the common Authentication service and continue with regular flow only if Authentication service returned success. When invoking Authentication service, parameters are passed to it, via query string, based on which it returns true/false as response.
Flow of events:
Browser invokes http://localhost/SampleService/api/Home?param=data i.e Site1
Reverse proxy rule on Site1 makes the call go to Site2 which is http://localhost/ValidateAuthN
Site2 checks the value of param and returns a JSON response - true or false
Browser gets the response back.
I am using IIS as reverse proxy with url rewrite module and ARR configured. "Enable proxy setting" has been checked for ARR on root node in IIS. On API site in IIS, I have configured rewrite rule as below:
<rewrite>
<rules>
<rule name="ReverseProxyInboundRule1" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="http://localhost/ValidateAuthN" />
</rule>
</rules>
</rewrite>
I see that the request is redirected to Authentication service with query strings values and the true/false response returned by Authentication service is received directly in calling application. However, request is not reaching the actual API layer for further processing. What I want is that at step 4 above, the request should go back to site1 with JSON response of true/false.
Please suggest what could I be missing in this configuration.
Maybe you need an exception rule for the reply? Your match rule (.*) catches everything, so the true/false reply might be getting re-routed itself?
My marketing team accidentally created materials with an additional 'www' sub domain and I need to see if I can remove it using Azure traffic manager.
Marketing domain (incorrect) HTTPS://www.my.site.com
Desired domain HTTPS://my.site.com
I only have a wildcard cert for *.site.com so at this time I cannot support the 'www'.
If the user enters the 'www' site over HTTP I can successfully redirect to the correct site. If they enter the HTTPS, or use Firefox that defaults to HTTPS, they will see a certificate error for HTTPS://www.my.site.com.
Would a second wildcart cert for *.my.site.com help? I am not sure where I would configure it.
Any help would be appreciated, thanks.
The certificate you have should be enough since its a wildcard cert, no need to buy another one.
I think this can be fixed by adding another host-name to your app and creating another SSL binding.
That means you need to add the www.my.site.com host-name (make sure to assign it to the traffic manager url):
And then do the binding:
Once that is done both URLs will work through SSL.
If you want to then have all traffic from going to you can then add a URL re-write rule:
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="SPA">
<match url="OLDURL" />
<action type="Rewrite" url="NEWURL" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
You can look at this other answer to get more data: Rewriting a URL in an Azure web app
I'm new to Azure and I'm working on a project that uses the new Websites model as opposed to Cloud Services. I want to set up a continuous delivery process like this one: http://www.windowsazure.com/en-us/develop/net/common-tasks/publishing-with-tfs/
However, I don't want my site to be publicly addressable after each continuous deployment. Instead, I want my continuous deployments to be accessible only by my team for testing purposes. How can this best be achieved?
Thoughts so far:
Wrap the whole site in forms authentication - but I don't like the fact that this means I will be deploying a different version of my site to production than that which I deploy to testing.
IP address restrictions - but I don't know if this can be done with Azure Websites and whether this is a good solution?
The Azure Websites Authentication / Authorization feature was designed to support this exact scenario. Basically, you create a site slot, add AAD authentication to it using a few clicks, and from then on your staging slot will always require a valid login, even after you do a swap operation.
Blog Post: http://azure.microsoft.com/blog/2014/11/13/azure-websites-authentication-authorization/
Demo Video: http://azure.microsoft.com/en-us/documentation/videos/azure-websites-easy-authentication-and-authorization-with-chris-gillum/
You can add IP restrictions using the URL Rewrite Module, which Azure web sites seem to have enabled by default.
Your web.config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="SayNoToZombies" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{REMOTE_ADDR}" pattern="::1" negate="true" />
</conditions>
<action type="CustomResponse" statusCode="403" statusReason="Forbidden: Access is denied." statusDescription="Sorry, you're not allowed" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
You can replace pattern="::1" (localhost in IPv6) with a suitable regex to match your permitted IP, e.g., pattern="87.236.134.47" or if more than one:
pattern="(62\.231\.142\.233)|(87\.236\.134\.47)|(::1)|(127\.0\.0\.1)"
I had to do something similar for a client, but couldn't find a way to restrict access to the site from the Azure portal itself. I went with the IP address restriction option, but did it through code in the application itself. My application was already using forms authentication, so I could perform the IP address check in the sign in action.
In your case I would suggest a custom action filter. Perform the check in the filter and if the IP address is not allowed, return a http 401 (unauthorised) status code.
Create an app setting called AllowedIpAddresses or some such, in which you can add a comma separated list of allowed IP addresses. When you perform the check, you can set your site to allow all traffic if AllowedIpAddresses is empty or doesn't exist. That way, you can ignore this setting in production and all traffic will be allowed by default. You can set up custom app settings for each site within the Azure portal.
Here's what a custom filter might look like. I haven't tested this!
public class AccessRestrictionFilterAttribute : ActionFilterAttribute
{
// simple wrapper around ConfigurationManager.AppSettings for testability
private readonly IAppSettingsHandler appSettingsHandler;
public AccessRestrictionFilterAttribute(IAppSettingsHandler appSettingsHandler)
{
this.appSettingsHandler = appSettingsHandler;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var isAllowed = false;
var userIpAddress = filterContext.HttpContext.Request.UserHostAddress;
if (appSettingsHandler.AllowedIpAddresses.Split(new[] { ',' }).Any(x => x == userIpAddress))
{
isAllowed = true;
}
if (!isAllowed)
{
filterContext.Result = new HttpUnauthorizedResult();
}
base.OnActionExecuting(filterContext);
}
}