I have an MVC application hosted in on premise IIS which has form authentication. <system.web>
setting is:
<system.web>
<compilation debug="true" targetFramework="4.8"/>
<httpRuntime targetFramework="4.8"/>
<authentication mode="Forms">
<forms loginUrl="~/Login" timeout="2880"/>
</authentication>
<authorization>
<allow users="?" verbs="OPTIONS"/>
<deny users="?"/>
</authorization>
</system.web>
So, when a user is not authenticated, it redirects to login page. My login controller looks like:
It has an API which is POST method and returns a list.
I am accessing this api using ajax in the UI.
It is working fine in this application. Now I have another MVC application which is in azure cloud and it needs to access this API. When I am invoking it (http://my-premise-application.com/api/customer/list), it is returning the content of the login page. What are possible way to invoke api of the first application from the second application? Any suggestion or guidance would be helpful.
Forms authentication uses an HTML form to send the user's credentials to the server. It is not an Internet standard. Forms authentication is only appropriate for web APIs that are called from a web application, so that the user can interact with the HTML form. - Easy to implement: Built into ASP.NET.
The login form associated with the security constraint is sent to the client and the URL path triggering the authentication is stored by the container. The user is asked to fill out the form, including the username and password fields. The client posts the form back to the server.
Using an external authentication service saves end users from having to create another account for your web application, and also from having to remember another username and password.
As you mentioned in the comments you have to make a C# HTTP call to the other project Web API. You can do it by creating anywhere in your project a class named MakeRequestService
and one static
method named MakeWebRequest
, which will return a string, being the JSON you need.
public class MakeRequestService
{
public static string MakeWebRequest(string url, string verb, int timeout, Dictionary<string, string> headers = null, string contentType = "", string json = "")
{
string myResult = string.Empty;
try
{
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(url);
myRequest.Method = verb;
myRequest.Timeout = timeout;
if (!string.IsNullOrEmpty(contentType))
myRequest.ContentType = contentType;
if (headers != null)
{
foreach (var header in headers)
{
if (header.Key == HttpRequestHeader.Accept.ToString())
myRequest.Accept = header.Value;
else
myRequest.Headers.Add(header.Key, header.Value);
}
}
if (!string.IsNullOrEmpty(json))
{
byte[] bytes = Encoding.UTF8.GetBytes(json);
myRequest.ContentLength = bytes.Length;
using (var streamWriter = new StreamWriter(myRequest.GetRequestStream()))
{
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
}
using (HttpWebResponse response = myRequest.GetResponse() as HttpWebResponse)
{
StreamReader reader = new StreamReader(response.GetResponseStream());
myResult = reader.ReadToEnd();
}
}
catch (WebException ex)
{
if (ex.Status == WebExceptionStatus.ProtocolError)
{
if (ex.Response is HttpWebResponse response)
{
Stream stream = response.GetResponseStream();
StreamReader sr = new StreamReader(stream: stream);
myResult = sr.ReadToEnd();
stream.Position = 0;
}
}
else
{
myResult = ex.Message;
}
}
return myResult;
}
}
You can then use this method in the following way:
string res = MakeRequestService.MakeWebRequest(
url: "The FULL URL of the first project, based on your example, e.g. http://localhost:69963/api/customer",
verb: "POST",
contentType: "application/json"
);
var outcome = JsonConvert.DeserializeObject<IEnumerable<Customer>>(res);
The catch
block in the MakeWebRequest
method is just an example and will return a plain string containing the JSON error body in case of an unsuccessful API call. You can modify it for your needs, e.g. rethrow the WebException
and handle it the way you want.
The MakeWebRequest
method is very abstract so you can use it for the API calls as well. If you make a POST
request with JSON body - just pass the body to the json
parameter. If you make a GET
request with query parameters, just build the whole URL, containing the query parameters, and then invoke the method.
Here is some code I use to login with a C# app. You will need to modify to work with your application. The SharedCookie will need to be added to each future request since it has your Session Cookie included.
public void Login()
{
byte[] bytes;
string data;
SharedCookie = new CookieContainer();
var url = Host + "/login";
try
{
//Start Session
var request = CreateRequest(url, "GET");
request.CookieContainer = SharedCookie;
using (var tmpResponse = request.GetResponse())
{
DoWriteResponse(tmpResponse);
tmpResponse.Close();
}
//Login
data = "username=user&password=pass";
bytes = Encoding.UTF8.GetBytes(data);
request = CreateRequest(url, "POST");
request.CookieContainer = SharedCookie;
using (var stream = request.GetRequestStream())
{
stream.Write(bytes, 0, bytes.Length);
}
using (var tmpResponse = request.GetResponse())
{
DoWriteResponse(tmpResponse);
tmpResponse.Close();
}
IsLoggedIn = true;
}
catch (System.Net.WebException ex)
{
Console.WriteLine("Web Error:" + ex.Status);
Console.WriteLine("Url:" + url);
Console.WriteLine(ex.Message);
}
catch (Exception ex)
{
Console.WriteLine("Url:" + url);
Console.WriteLine(ex.Message);
}
}
private void DoWriteResponse(WebResponse tmpResponse)
{
if (debug)
{
Console.WriteLine("************BEGIN**************");
Console.WriteLine("************" + tmpResponse.ResponseUri + "**************");
Console.WriteLine("*******************************");
using (var reader = new StreamReader(tmpResponse.GetResponseStream()))
{
var pageText = reader.ReadToEnd();
Console.WriteLine(pageText);
}
Console.WriteLine("*************END***************");
}
}
private HttpWebRequest CreateRequest(string url, string method)
{
var request = (HttpWebRequest)WebRequest.Create(url);
request.Referer = Host;
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36";
request.Method = method;
request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
return request;
}
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