MVC 5 SQL Network Interfaces, error: 26 - Error, with [Authorize] - asp.net-mvc-5

I'm having trouble setting up Authorization in MVC 5. I have a brand new MVC 5 website with Individual User Accounts and an SQL Server database with the five aspNet... tables.
I can login locally, it all works fine on my local server and I can even login the production database from my local website when I point my local connection string at the production server but I can't login from the website on the production server,
I get the following error:
A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 - Error Locating Server/Instance Specified)
The error only happens when I use [Authorize] on an Action where I then have to login, if I remove [Authorize] the Action and database work fine.
Any ideas
Edit
Just for clarity, the SQL Server is on one of Arvixe servers, and the website is at Godaddy here is my connection string
<add name="mysiteEntities"
connectionString="metadata =
res://*/Models.mysite.csdl|res://*/Models.mysite.ssdl|res://*/Models.mysite.msl;
provider = System.Data.SqlClient;
provider connection string ='
data source = xxxxx.arvixe.com;
Initial Catalog = mysite;
User ID = xxxxxx;
Password = xxxxxxx'"
providerName="System.Data.EntityClient" />
I am unable to login from Godaddy with this string but if I use this string on my local computer I can login.
I also have a number of websites set up with the same configuration in MVC 4 which work fine.

I had a similar issue; however, I wrongly assumed it to be that I was not using EF and SQL Server, but Telerik Data Access around Oracle 11g. What fixed it for me was to remove the RoleManager module in the config file, as per this article (http://blog.luppes.com/2013/12/08/mvc5-authentication-roles-failure/)
So, to paraphrase that link for posterity, it was:
<system.webServer>
<modules>
<remove name="RoleManager" />
</modules>
</system.webServer>

I worked this out but it let me to a new question that I wave a work around for. For this question I had the wrong base connection referenced in here.
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
The problem now is I need two connection strings to connect. One for Authorisation as MVC5 wants a Code First connection string but the rest of my code is Database First

Related

Requests to third party API from .NET Core app timeout in IIS

I have a .NET Core Web API app running in IIS that can receive and respond to requests, but it needs to make requests to a third party API (Twilio). Those requests succeed when hosted locally but they time out when hosted in IIS.
The .NET Core Web API app is targeting v2.1 and running on Windows Server and IIS 7. I setup a dedicated app pool for the site following guidelines in this article.
App pool settings:
I'm using Postman to make GET and POST requests to the app.
GET and POST requests to a test controller work fine. All I'm doing with these test endpoints is returning the parameters that are received.
[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
[HttpGet]
public string Get(int id)
{
return $"response to GET; id:{id}";
}
[HttpPost]
public string Post([FromBody] int id)
{
return $"response to POST; foo:{id}";
}
}
The above endpoints work locally running debug mode in VS2019 using IISExpress, and they also work when deployed to the web server and hosted with IIS7.
The trouble starts when I try to call out to a third party API (Twilio). Again these calls succeed when the app runs locally. There's almost no delay. I post to the SMSController's post endpoint, the request is triggered, and I get a text message within seconds. However, GET and POST requests to these endpoints fails from the web server and IIS.
[Route("api/[controller]")]
[ApiController]
public class SMSController : ControllerBase
{
private string twilioSID = "xxxxxx";
private string twilioAuthToken = "xxxxxx";
private string twilioPhoneNumber = "+15555555555";
[HttpGet]
public string Get(string phoneNumber)
{
TwilioClient.Init(twilioSID, twilioAuthToken);
var message = MessageResource.Create(
body: $"TEST message via Twilio",
from: new Twilio.Types.PhoneNumber(twilioPhoneNumber),
to: new Twilio.Types.PhoneNumber(phoneNumber)
);
return message.Status.ToString();
}
[HttpPost]
public string Post([FromBody] GeoEvent geoEvent)
{
TwilioClient.Init(twilioSID, twilioAuthToken);
var message = MessageResource.Create(
body: $"TEST message via Twilio",
from: new Twilio.Types.PhoneNumber(twilioPhoneNumber),
to: new Twilio.Types.PhoneNumber(geoEvent.PhoneNumber)
);
return message.Status.ToString();
}
}
GET and POST requests to the above endpoints get a 500 response when hosted in IIS. The following exception is thrown:
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
Lastly, here is the web.config that the SDK generated for me when I published the app in VS2019.
<?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=".\TwilioService.exe" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" />
</system.webServer>
</location>
</configuration>
Neither my local machine nor the web server running IIS are behind a corporate proxy.
Am I missing an IIS or web.config setting that will allow .NET Core to make requests through IIS to a third party?
UPDATE:
I have now reproduced the same issue on a different web server running Windows Server 2016. This machine is setup with .NET 5, IIS 10, and the hosting bundle for .NET 5. I also installed VS2019 and recreated the web api project to run locally on the server. Here are the results:
Running locally in IIS Express, the api controller can successfully
make a request to the Twilio api and gets a response. The SMS
message is sent successfully. No errors.
Running locally in IIS 10, the api controller calls Twilio but
fails to get a response. The following error occurs:
Twilio.Exceptions.ApiConnectionException: Connection Error: POSThttps://api.twilio.com/2010-04-01/Accounts//Messages.json
---> 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. (api.twilio.com:443)
To reiterate, both of the above scenarios are running on the same machine. The only difference is IIS Express vs IIS 10. Is this an SSL cert issue? Because IIS 10 works as a reverse proxy for .NET core apps, could there be a problem with a cert getting recognized or forwarded from the .net core app through IIS?
Try to ping the third-party service URL from your machine command prompt.
Make sure the firewall port is set to allow. check the antivirus is now blocking the connection.
try to add the defaultProxy section to my web.config in order to get my website to connect to a web service.
https://learn.microsoft.com/en-US/troubleshoot/dotnet/framework/cannot-consume-web-service-via-http-proxy
Solved. It turned out to be a corporate proxy after all. I had bad information that the web server was not behind a proxy but it was. Twilio has a solution for this exact scenario in their documentation involving the use of a custom proxied rest client class. It's a wrapper around System.Net.HttpClient. The service can now make calls to Twilio through the proxy using this class with the proxy server url set.

Login failed for User when using Database connection in Owin Startup class

I am using Hangfire in my sharepoint provider hosted app. I have Owin Startup class.
public class Startup
{
public void Configuration(IAppBuilder app)
{
GlobalConfiguration.Configuration.UseSqlServerStorage("DefaultConnection");
RecurringJob.AddOrUpdate(() => Console.WriteLine("Recurring!"), Cron.Minutely);
app.UseHangfireDashboard();
app.UseHangfireServer();
}
}
I have initialised defaultConnection in my web.config file. Everytime i run, i get error saying Login failed for Domain\MachineName, I tried passing user id and password in connection string, but still is fails saying login failed for that user.
Can anyone help me to find the issue?
I resolved this issue by creating a sql authentication login credential in my SQL server. I passed the created user id and password in my connection string.
<add name="DefaultConnection" connectionString="Data Source=DEESS01CW0184CO\SPQ11CONTENT;Initial Catalog=HangfireTest;User ID='testuser';password='testuser123'" providerName="System.Data.SqlClient" />
The issue still persisted for windows authentication.

Can not connect to Azure SQL Server using Active directory integrated authentication in AppService

We have web application deploy on Azure App Service. Our database is also on Azure which is configured to use AAD authentication (We have assigned AAD Admin).
We are using below connection string in web app to connect to this server and database using below connections string.
Data Source=xxxxxxx.database.windows.net;Initial
Catalog=xxxxxxx;Persist Security Info=False;Authentication=Active
Directory Integrated
Please note: This connection string is working fine when using thru local system. But getting below error when we use this conn string in Azure App Service:
Failed to authenticate the user NT Authority\Anonymous Logon in Active
Directory (Authentication=ActiveDirectoryIntegrated). Error code
0x4BC; state 10 The format of the specified domain name is invalid
According to your description, I found you used the Active Directory integrated authentication.
To use integrated Windows authentication, your domain’s Active Directory must be federated with Azure Active Directory. Your client application (or a service) connecting to the database must be running on a domain-joined machine under a user’s domain credentials
If you published the web app to Azure, Azure's web app server will not be in your domain’s Active Directory. So the SQL server will not pass the auth.
I suggest you could try to use Active Directory password authentication instead of the Active Directory integrated authentication.
Replace the connection string as below use azure AD user name and password. It will work well.
Server=tcp:brandotest.database.windows.net,1433;Initial Catalog=bradnotestsql;Persist Security Info=False;User ID={your_username};Password={your_password};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Authentication="Active Directory Password";
Since the accepted answers are a bit dated, if you are out here in 2020 or later, the correct way for setting up integrated authentication is as follows:
(excerpted from here, the asp.net standard implementation)
https://learn.microsoft.com/en-us/azure/app-service/app-service-web-tutorial-connect-msi
add the Microsoft.Azure.Services.AppAuthentication nuget package.
modify your web.config by adding: (in configSections)
<section name="SqlAuthenticationProviders" type="System.Data.SqlClient.SqlAuthenticationProviderConfigurationSection, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
(and then)
<SqlAuthenticationProviders>
<providers>
<add name="Active Directory Interactive" type="Microsoft.Azure.Services.AppAuthentication.SqlAppAuthenticationProvider, Microsoft.Azure.Services.AppAuthentication" />
</providers>
</SqlAuthenticationProviders>
It's important to pay attention to the name you use there. Then... your connection string will look like:
<add name="MyEntities" connectionString="metadata=res://*/Data.MyDB.csdl|res://*/Data.MyDB.ssdl|res://*/Data.MyDB.msl;provider=System.Data.SqlClient;provider connection string="server=tcp:MyDB.database.windows.net;database=MyDB;UID=AnyString;Authentication=Active Directory Interactive;"" providerName="System.Data.EntityClient" />
The important notes are that the name you specify in the SqlAuthenticationProviders section must be the exact same name you use in the connection string for Authentication.
The other important note is that, coming from your old connection strings, you have to change Data Source to be Server, and Initial Catalog to be Database. UID=AnyString is necessary, or an exception is thrown.
Failure to follow these steps exactly will net you a lovely error:
System.Data.Entity.Core.EntityException: The underlying provider failed on Open. ---> System.AggregateException: One or more errors occurred. ---> System.AggregateException: One or more errors occurred. ---> AdalException: The format of the specified domain name is invalid.\r\n at ADALNativeWrapper.ADALGetAccessToken(String username, IntPtr password, String stsURL, String servicePrincipalName, ValueType correlationId, String clientId, Boolean* fWindowsIntegrated, Int64& fileTime)\r\n at System.Data.SqlClient.ActiveDirectoryNativeAuthenticationProvider.<>c__DisplayClass2_0.b__0()\r\n at System.Threading.Tasks.Task`1.InnerInvoke()\r\n at System.Threading.Tasks.Task.Execute()\r\n --- End of inner exception stack trace
At the first the error doesn't make sense, but once you see that the parameters were renamed from Data Source to Server, it does make sense.
Maybe all you need to use is token (certificate) authentication as explained on below resource:
https://github.com/Microsoft/sql-server-samples/tree/master/samples/features/security/azure-active-directory-auth/token
Try to register your application with Azure Active Directory as explained on that resource.
Hope this helps.

Can not access Azure SQL database after moving Azure API app to custom domain

I moved my API from free plan app service to a basic plan app service with custom domain and SSL certificate.
1) I see that my API app's status is "running", Authentication (AAD) is working properly
2) if I open it's api definition (i.e. */swagger/docs/v1) it IS working
3) If i try a request that does not try to access backend Azure sql db, then it is working correctly
4) If I use a request that call backend Azure SQL db (it worked before moving API to custom domain) it fails with this error:
{"The underlying provider failed on Open., StackTrace: at
System.Data.Entity.Core.EntityClient.EntityConnection.Open()\r\n at
System.Data.Entity.Core.Objects.ObjectContext.EnsureConnection(Boolean
shouldMonitorTransactions)\r\n at
System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func1
func, IDbExecutionStrategy executionStrategy, Boolean
startLocalTransaction, Boolean releaseConnectionOnSuccess)\r\n at
System.Data.Entity.Core.Objects.ObjectContext.<>c__DisplayClass651.b__63()\r\n
at
System.Data.Entity.Infrastructure.DbExecutionStrategy.Execute[TResult](Func1
operation)\r\n at
System.Data.Entity.Core.Objects.ObjectContext.ExecuteStoreQueryReliably[TElement](String
commandText, String entitySetName, ExecutionOptions executionOptions,
Object[] parameters)\r\n at
System.Data.Entity.Core.Objects.ObjectContext.ExecuteStoreQuery[TElement](String
commandText, ExecutionOptions executionOptions, Object[]
parameters)\r\n at
System.Data.Entity.Internal.InternalContext.<>c__DisplayClass141.b__13()\r\n
at System.Data.Entity.Internal.LazyEnumerator1.MoveNext()\r\n at
System.Collections.Generic.List1..ctor(IEnumerable1 collection)\r\n
at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source)\r\n
at
P..Repositories.DataAccessLayer.DbContexts.P..DbContext.GetP..Dtos()\r\n
at
P..Repositories.Repositories.P..Repository.P..Repository..ctor()\r\n
at P..API.Controllers.A..Controller.Get()"}]}
Only thing I've found so far suggests that my API can not access Azure SQL because of firewall rules, but that doesn't sound as an option, since I just assigned a custom domain to my app, I believe it is in the same "place" in Azure... and I did not manage so far to find any suggestions regarding Azure SQL db connections when migrating API to custom domains...
Any ideas?
It turns out, that by some strange reason, after moving to custom domain - publishing settings, AzureDatabase connection string had a non-existent (seams like "generated" name -> Api name with added postfix _db) database name. When I changed it to the real db name, everything started to work again...
P.S. I guess unchecking "use this connection string at runtime (update destination web.config)" would give the same result, since web.config holds the right connection string.

Unable to authenticate to ASP.NET Web Api service with HttpClient

I have an ASP.NET Web API service that runs on a web server with Windows Authentication enabled.
I have a client site built on MVC4 that runs in a different site on the same web server that uses the HttpClient to pull data from the service. This client site runs with identity impersonation enabled and also uses windows authentication.
The web server is Windows Server 2008 R2 with IIS 7.5.
The challenge I am having is getting the HttpClient to pass the current windows user as part of its authentication process. I have configured the HttpClient in this manner:
var clientHandler = new HttpClientHandler();
clientHandler.UseDefaultCredentials = true;
clientHandler.PreAuthenticate = true;
clientHandler.ClientCertificateOptions = ClientCertificateOption.Automatic;
var httpClient = new HttpClient(clientHandler);
My understanding is that running the site with identity impersonation enabled and then building the client in this manner should result in the client authenticating to the service using the impersonated identity of the currently logged in user.
This is not happening. In fact, the client doesn't seem to be authenticating at all.
The service is configured to use windows authentication and this seems to work perfectly. I can go to http://server/api/shippers in my web browser and be prompted for windows authentication, once entered I receive the data requested.
In the IIS logs I see the API requests being received with no authentication and receiving a 401 challenge response.
Documentation on this one seems to be sparse.
I need some insight into what could be wrong or another way to use windows authentication with this application.
Thank You,
Craig
I have investigated the source code of HttpClientHandler (the latest version I was able to get my hands on) and this is what can be found in SendAsync method:
// BeginGetResponse/BeginGetRequestStream have a lot of setup work to do before becoming async
// (proxy, dns, connection pooling, etc). Run these on a separate thread.
// Do not provide a cancellation token; if this helper task could be canceled before starting then
// nobody would complete the tcs.
Task.Factory.StartNew(startRequest, state);
Now if you check within your code the value of SecurityContext.IsWindowsIdentityFlowSuppressed() you will most probably get true. In result the StartRequest method is executed in new thread with the credentials of the asp.net process (not the credentials of the impersonated user).
There are two possible ways out of this. If you have access to yours server aspnet_config.config, you should set following settings (setting those in web.config seems to have no effect):
<legacyImpersonationPolicy enabled="false"/>
<alwaysFlowImpersonationPolicy enabled="true"/>
If you can't change the aspnet_config.config you will have to create your own HttpClientHandler to support this scenario.
UPDATE REGARDING THE USAGE OF FQDN
The issue you have hit here is a feature in Windows that is designed to protect against "reflection attacks". To work around this you need to whitelist the domain you are trying to access on the machine that is trying to access the server. Follow below steps:
Go to Start --> Run --> regedit
Locate HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0 registry key.
Right-click on it, choose New and then Multi-String Value.
Type BackConnectionHostNames (ENTER).
Right-click just created value and choose Modify.
Put the host name(s) for the site(s) that are on the local computer in the value box and click OK (each host name/FQDN needs to be on it's own line, no wildcards, the name must be exact match).
Save everything and restart the machine
You can read full KB article regarding the issue here.
I was also having this same problem. Thanks to the research done by #tpeczek, I developed the following solution: instead of using the HttpClient (which creates threads and sends requests async,) I used the WebClient class which issues requests on the same thread. Doing so enables me to pass on the user's identity to WebAPI from another ASP.NET application.
The obvious downside is that this will not work async.
var wi = (WindowsIdentity)HttpContext.User.Identity;
var wic = wi.Impersonate();
try
{
var data = JsonConvert.SerializeObject(new
{
Property1 = 1,
Property2 = "blah"
});
using (var client = new WebClient { UseDefaultCredentials = true })
{
client.Headers.Add(HttpRequestHeader.ContentType, "application/json; charset=utf-8");
client.UploadData("http://url/api/controller", "POST", Encoding.UTF8.GetBytes(data));
}
}
catch (Exception exc)
{
// handle exception
}
finally
{
wic.Undo();
}
Note: Requires NuGet package: Newtonsoft.Json, which is the same JSON serializer WebAPI uses.
The reason why this is not working is because you need double hop authentication.
The first hop is the web server, getting impersonation with Windows authentication to work there is no problem. But when using HttpClient or WebClient to authenticate you to another server, the web server needs to run on an account that has permission to do the necessary delegation.
See the following for more details:
http://blogs.technet.com/b/askds/archive/2008/06/13/understanding-kerberos-double-hop.aspx
Fix using the "setspn" command:
http://www.phishthis.com/2009/10/24/how-to-configure-ad-sql-and-iis-for-two-hop-kerberos-authentication-2/
(You will need sufficient access rights to perform these operations.)
Just consider what would happen if any server was allowed to forward your credentials as it pleases... To avoid this security issue, the domain controller needs to know which accounts are allowed to perform the delegation.
To impersonate the original (authenticated) user, use the following configuration in the Web.config file:
<authentication mode="Windows" />
<identity impersonate="true" />
With this configuration, ASP.NET always impersonates the authenticated user, and all resource access is performed using the authenticated user's security context.

Resources