Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invoke API of another application which has form authentication

Tags:

c#

asp.net-mvc

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: enter image description here

It has an API which is POST method and returns a list.

enter image description here

I am accessing this api using ajax in the UI. ajax call javascript

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.

like image 871
Arshad Avatar asked Nov 05 '20 11:11

Arshad


People also ask

How does Web API implement form authentication?

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.

What is form authentication in REST API?

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.

What is external authentication in Web API?

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.


Video Answer


2 Answers

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.

like image 196
G.Dimov Avatar answered Oct 23 '22 16:10

G.Dimov


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;
    }
like image 22
Richard Hubley Avatar answered Oct 23 '22 18:10

Richard Hubley