javaweb-servicestomcatc#-4.0bonita

Bonita Web API - 401 Unauthorized Error


I am trying to use Bonita Web API. I My code is below. As you can see I call the loginservice before calling any other API service. It logs in OK 200. But when I make the subsequent call to get the list of processes I get a 401 error. You get a JSESSIONID from the first call and you are suppose to pass it to the subsequent calls to authenticate you.

var baseAddress = new Uri(<base address>);
var cookieContainer = new CookieContainer();
using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
    {
            HttpResponseMessage result = client.PostAsync("/bonita/loginservice", new StringContent("login=<username>,password=<password>,redirect=false")).Result;
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            HttpResponseMessage result2 = client.GetAsync("/bonita/API/bpm/process").Result;
            result2.EnsureSuccessStatusCode();
    }

Solution

  • This works for .Net 2.0 C# but has some interesting things to check.

    WebClient wc = new WebClient();
    wc.Proxy = WebRequest.GetSystemWebProxy();
    //wc.Headers[HttpRequestHeader.AcceptEncoding] = "gzip, deflate";
    string strLogin = wc.DownloadString("http://localhost:8080/bonita/loginservice?username=walter.bates&password=bpm&redirect=false");
    
    wc.Headers[HttpRequestHeader.Cookie] = wc.ResponseHeaders[HttpResponseHeader.SetCookie].ToString();
    string strCookie = wc.ResponseHeaders[HttpResponseHeader.SetCookie].ToString();
    
    string strProcesses = wc.DownloadString("http://localhost:8080/bonita/API/bpm/process?p=0");
    

    First of all you should know how to determine that the executed operation is successful ( login, getProcesses and whatever) When you try to login you will always get the header (for example "JSESSIONID=50E509D37AC28E2D725CBD45A8112FA7; Path=/bonita; HttpOnly") and OK 200 even if your login attempt in Bonita is unsuccesful.

    For the successful login on the previous example

    1) You must Pass mandatory form data: username, password and redirect You must also be sure to pass redirect in lower case ."False" will not work, "false" will work. So for .Net suppose you have a property-> Boolean redirect. You must make it lowercase with redirect.ToString().ToLower() cause either way the value will be "False" and you don't want that.

    Let's say you try to login only with username and password without passing redirect. the result is that you will get both OK 200 and the header but you will also get a response which is wrong (the response must be empty), so on the next request (i.e getProcesses) you'll get (401) Unauthorized. Guess the results you will have if you pass redirect=False instead of redirect=false. Exactly the same.

    2)You must get: strLogin="" // the body of the response must be empty strCookie="JSESSIONID=4F67F134840A2C72DBB968D53772FB22; Path=/bonita; HttpOnly"

    For the successful getProcesses on the previous example you pass the header you got from login

    wc.Headers[HttpRequestHeader.Cookie] = wc.ResponseHeaders[HttpResponseHeader.SetCookie].ToString();
    

    and then you call the process and get a string in json format for example

    "[{\"id\":\"6996906669894804403\",\"icon\":\"\",\"displayDescription\":\"\",\"deploymentDate\":\"2014-11-19 17:57:40.893\",\"description\":\"\",\"activationState\":\"ENABLED\",\"name\":\"Travel request\",\"deployedBy\":\"22\",\"displayName\":\"Travel request\",\"actorinitiatorid\":\"4\",\"last_update_date\":\"2014-11-19 17:57:41.753\",\"configurationState\":\"RESOLVED\",\"version\":\"1.0\"}]"
    

    (or [] which means an empty json)

    If the cookie is not passed correctly you will get again 401 error.

    Solution for .Net 4.5.1

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using System.Text;
    using System.Threading.Tasks;
    using System.Web;
    
    
    namespace BonitaRestApi
    {
        class BonitaApi
        {
            private CookieCollection collection;
            string strCookietoPass;
            string sessionID;
    
            static void Main(string[] args)
            {
                BonitaApi obj = new BonitaApi();
                Task login = new Task(obj.Login);
                login.Start();
                login.Wait();
                Console.ReadLine();
    
                Task GetProcesses = new Task(obj.GetProcesses);
                GetProcesses.Start();
                GetProcesses.Wait();
                Console.ReadLine();
    
                Task logout = new Task(obj.Logout);
                logout.Start();
                logout.Wait();
                Console.ReadLine();
    
            }
    
            public async void Login()
            {
                const string url = "http://localhost:8080/bonita/";
    
                var cookies = new CookieContainer();
                var handler = new HttpClientHandler();
                handler.CookieContainer = cookies;
    
                using (var client = new HttpClient(handler))
                {
                    var uri = new Uri(url);
                    client.BaseAddress = uri;
                    //client.DefaultRequestHeaders.Accept.Clear();
                    //client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
                    var content = new FormUrlEncodedContent(new[] 
                    {
                        new KeyValuePair<string, string>("username", "helen.kelly"), 
                        new KeyValuePair<string, string>("password", "bpm"), 
                        new KeyValuePair<string, string>("redirect", "false"), 
                        new KeyValuePair<string, string>("redirectUrl", ""), 
                    });
    
                    HttpResponseMessage response = await client.PostAsync("loginservice", content);
    
                    if (response.IsSuccessStatusCode)
                    {
                        var responseBodyAsText = await response.Content.ReadAsStringAsync();
    
                        if (!String.IsNullOrEmpty(responseBodyAsText))
                        {
                            Console.WriteLine("Unsuccessful Login.Bonita bundle may not have been started, or the URL is invalid.");
                            return;
                        }
    
                        collection= cookies.GetCookies(uri);
                        strCookietoPass = response.Headers.GetValues("Set-Cookie").FirstOrDefault();
    
                        sessionID = collection["JSESSIONID"].ToString();
    
                        Console.WriteLine(string.Format("Successful Login Retrieved session ID {0}", sessionID));
                            // Do useful work 
                    }
                    else
                    {
                        Console.WriteLine("Login Error" + (int)response.StatusCode + "," + response.ReasonPhrase);
                    }
    
                }
            }
    
            public async void Logout()
            {
                const string url = "http://localhost:8080/bonita/";
    
                var cookies = new CookieContainer();
                var handler = new HttpClientHandler();
                handler.CookieContainer = cookies;
    
                using (var client = new HttpClient(handler))
                {
                    var uri = new Uri(url);
                    client.BaseAddress = uri;
    
                    var content = new FormUrlEncodedContent(new[] 
                    {
                        new KeyValuePair<string, string>("redirect", "false")
                    });
    
                    HttpResponseMessage response = await client.PostAsync("logoutservice", content);
    
                    if (response.IsSuccessStatusCode)
                    {
                        var responseBodyText = await response.Content.ReadAsStringAsync();
    
                        if (!String.IsNullOrEmpty(responseBodyText))
                        {
                            Console.WriteLine("Unsuccessful Logout.Bonita bundle may not have been started, or the URL is invalid.");
                            return;
                        }
    
                        Console.WriteLine("Successfully Logged out.");
                    }
                    else
                    {
                        Console.WriteLine("Logout Error" + (int)response.StatusCode + "," + response.ReasonPhrase);
                    }
    
                }
            }
    
            public async void GetProcesses()
            {
    
                var handler = new HttpClientHandler();
    
                Cookie ok = new Cookie("Set-Cookie:",strCookietoPass);
    
                handler.CookieContainer.Add(collection);
    
                using (var client = new HttpClient(handler))
                {
    
                    var builder = new UriBuilder("http://localhost/bonita/API/bpm/process");
                    builder.Port = 8080;
    
                    var query = HttpUtility.ParseQueryString(builder.Query);
                    query["p"] = "0";
                    query["c"] = "10";
                    builder.Query = query.ToString();
    
                    Uri uri= new Uri(builder.ToString());
                    client.BaseAddress = uri;
    
                    HttpResponseMessage response = await client.GetAsync(uri.ToString());
    
                    if (response.IsSuccessStatusCode)
                    {
                        var responseBodyText = await response.Content.ReadAsStringAsync();
    
                        if (String.IsNullOrEmpty(responseBodyText))
                        {
                            Console.WriteLine("Unsuccessful GetProcesses.Bonita bundle may not have been started, or the URL is invalid.");
                            return;
                        }
    
                        Console.WriteLine("Successfully GetProcesses:" + responseBodyText);
    
                    }
                    else
                    {
                        Console.WriteLine("GetProcesses Error" + (int)response.StatusCode + "," + response.ReasonPhrase);
                    }
    
                }
            }
        }
    }