Unauthorized status from mobile Xamarin Forms application

Hi,

 

I want to connect to the Axelor server with a Xamarin forms application, I use this method to test the rest services connectivity :

 

Login login = new()

{

UserName = Constants.Login,

Password = Constants.Password

};

 

// Build authentication string

byte[] bytes = Encoding.UTF8.GetBytes($"{login.UserName}:{login.Password}");

string authorizationString = Convert.ToBase64String(bytes);

 

// Add headers to the HTTP client

httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authorizationString);

 

// Build HTTP message and send, strRoot = login.jsp

string url = $"{Constants.RestBaseUrl}/{strRoot}";

HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, url);

var sessionResponse = await httpClient.SendAsync(message);

 

/* sessionResponse.IsSuccessStatusCode = true, and sessionResponse.Headers =

{

Set-Cookie: JSESSIONID=E5EA31C3A5CBDF0A1C4B05ED2230679E; Path=/Gradle___com_axelor___axelor_erp_6_3_0_war; HttpOnly

Date: Mon, 14 Nov 2022 19:40:04 GMT

}

*/

sessionResponse.Headers.ToList().ForEach(x =>

httpClient.DefaultRequestHeaders.Add(x.Key, x.Value.FirstOrDefault()));

 

 

var rt = $"{Constants.RestBaseUrl}/ws/rest/com.axelor.apps.poultryfarming.db.Hatchery";

var response = await httpClient.GetAsync(rt);

 

var returnValue = await response.Content.ReadAsStringAsync();

/* returnValue :

<!doctype html><html lang="en"><head><title>HTTP Status 401 – Unauthorized</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 401 – Unauthorized</h1><hr class="line" /><p><b>Type</b> Status Report</p><p><b>Description</b> The request has not been applied because it lacks valid authentication credentials for the target resource.</p><hr class="line" /><h3>Apache Tomcat/8.5.73</h3></body></html>

*/

var stat = response.StatusCode; // return: Unauthorized

var cc = response.IsSuccessStatusCode;

 

return returnValue;

}

catch (Exception e)

{

throw;

}

but i always get the Unauthorized status !

 

Can you help me please

 

 

Hi, I think, you need send CSRF cookie too in the header.
The Axelor Open Platform has CSRF protection enabled using pac4j. If you want to call web services from a browser client, you need to make sure you handle the CSRF token: [Web Services :: Axelor Documentation]

It works well with RestSharp.RestRequest!

I will upload a complete example with .NET MAUI on github later.

This is my solution :

public class RestClientService : IRestClientService
{
    //private readonly ILogger<RestClientService> _logger;
    public RestClientService()
    {
        //_logger = logger;
    }

    public async Task<bool> LoginAsync(Login login)
    {
        string jsonString = JsonSerializer.Serialize(login);
        try
        {
            Constants.Cookies = null;
            Constants.IsServerConnected = false;

            var uri = new Uri($"{Constants.RestBaseUrl}/login.jsp");
            var _RestClient = new RestClient(uri);
            var request = new RestRequest(uri, Method.Post);
            request.AddHeader("Content-Type", "application/json");

            request.AddParameter("application/json", login, ParameterType.RequestBody);

            RestResponse response = await _RestClient.ExecuteAsync(request);

            if (response.IsSuccessStatusCode)
            {
                Constants.Cookies = response.Cookies;
                Constants.IsServerConnected = true;
            }
            return response.IsSuccessStatusCode;
        }
        catch (Exception e)
        {
           // _logger.LogError(e, "LoginError");
            throw;
        }
    }

    public async Task<RootData<T>> RestServiceGetAsync<T>(string model, int offset = 0, int limit = 10)
    {
        try
        {
            var uri = $"{Constants.RestBaseUrl}/ws/rest/{model}";
            var _RestClient = new RestClient(uri);
            var request = new RestRequest(uri, Method.Get);

            request.AddHeader("Content-Type", "application/json");

            if (Constants.Cookies.Any() && Constants.IsServerConnected)
            {
                string cookie = "";
                Constants.Cookies.ToList().ForEach(x => cookie += $"{x.Name}={x.Value}; ");
                request.AddHeader("Cookie", cookie);
            }
            else
            {
                throw new Exception("The server is not connected !");
            }

            request.AddParameter("offset", offset, ParameterType.UrlSegment);
            request.AddParameter("limit", limit, ParameterType.UrlSegment);

            RestResponse response = await _RestClient.ExecuteAsync(request);

            if (response.IsSuccessStatusCode)
            {
                var data = new MemoryStream(Encoding.UTF8.GetBytes(response.Content));
                var rslt = await JsonSerializer.DeserializeAsync<RootData<T>>(data);
                return rslt;
            }
            return null;

        }
        catch (Exception e)
        {
            //_logger.LogError(e, $"GetModelError: {model}");
            throw;
        }
    }

    public async Task<bool> LogoutAsync()
    {
        try
        {
            var uri = $"{Constants.RestBaseUrl}/logout";
            var _RestClient = new RestClient(uri);
            var request = new RestRequest(uri, Method.Get);

            request.AddHeader("Content-Type", "application/json");

            if (Constants.Cookies.Any() && Constants.IsServerConnected)
            {
                string cookie = "";
                Constants.Cookies.ToList().ForEach(x => cookie += $"{x.Name}={x.Value}; ");
                request.AddHeader("Cookie", cookie);
            }
            else
            {
                throw new Exception("The server is not connected !");
            }

            RestResponse response = await _RestClient.ExecuteAsync(request);
            return response.IsSuccessStatusCode;
        }
        catch (Exception e)
        {
            //_logger.LogError(e, "LogoutError");
            throw;
        }
    }
}
1 J'aime

Call Axelor rest services with RestClient example : https://github.com/dalmed/Maui-Axelor-Mobile.git