Page 1 of 1

CAM authentication 401 error - TM1 REST API

Posted: Thu Apr 13, 2017 4:35 pm
by krishnadixit
Hi,
Has anyone successfully implemented this CAM authentication (with and without Integrated login)? Could you please share some sample code in java? I always get 401 Unauthorized response code.

Here is my sample code:

Code: Select all

public class CAM_Try {

  public static void main(String[] args) {
    System.out.println("testing starts");

    //for localhost testing only
    javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
      new javax.net.ssl.HostnameVerifier(){
        public boolean verify(String hostname
                   , javax.net.ssl.SSLSession sslSession) {
	  if (hostname.equals("localhost")) {
	    return true;
	  }
	  return false;
	}
       }
     );

     try {

       URL u = new URL("http://169.46.63.237:50102/api/v1/$metadata");
       HttpURLConnection c = (HttpURLConnection) u.openConnection();
       String encoded = Base64.encodeBase64String
       ("<userID>:<password>:<CAMNamespace ID>".getBytes());
       c.setRequestProperty("Authorization", "CAMNamespace " + encoded);
       System.out.println("\n encoded" + encoded);
       c.setRequestProperty("Accept","application/json; charset=utf-8");
       c.setRequestProperty("Content-Type","application/json;charset=utf-8");
       c.setRequestProperty("WWW-Authenticate"
       ,"CAMPassport http://ibmdemo.demos.ibm.com:9300/bi/v1/disp, CAMNamespace");
       c.setRequestMethod("GET");

       c.connect();

       int status = c.getResponseCode();
       System.out.println(status);
       System.out.println( "Response1  "+ c.getResponseMessage()+ "\n\n");

       Map<String, List<String>> map = c.getHeaderFields();
       System.out.println("Printing Response Header...\n");

       for (Map.Entry<String, List<String>> entry : map.entrySet()) {
         
	 System.out.println("Key : " + entry.getKey() + " ,Value : " + entry.getValue());

       }
       
       switch (status) {
         
	 case 200:
	 case 201:
	   BufferedReader br = new BufferedReader(
	          new InputStreamReader(c.getInputStream())
	        );
	   StringBuilder sb = new StringBuilder();
	   String line;
	   while ((line = br.readLine()) != null) {
	     System.out.println(line);
	   }
	   br.close();
	}

     } catch (MalformedURLException ex) {
         System.out.println(ex.getMessage());
	 System.err.println(Arrays.toString(ex.getStackTrace()));
     } catch (IOException ex) {
         System.err.println(ex.getMessage());
	 System.err.println(Arrays.toString(ex.getStackTrace()));
	 ex.printStackTrace();       
     }
	
  }

}
I get this error:-
*************************************************************************************

D:\TestApi_Try>java SSLTester
testing starts
encodedYWRtaW5pc3RyYXRvcjpJQk1EZW0wczpIYXJtb255IEFE
401
Response1 Unauthorized

Printing Response Header...
Key : null ,Value : [HTTP/1.1 401 Unauthorized]
Key : WWW-Authenticate ,Value : [CAMPassport http://ibmdemo.demos.ibm.com:9300/bi/v1/disp, CAMNamespace]
Key : Content-Length ,Value : [0]
Key : Set-Cookie ,Value : [TM1SessionId=RjWJ-6VaVUbOEVTl9IZQKQ; Path=/api/; Http
Only]
Key : Connection ,Value : [keep-alive]
Key : Content-Type ,Value : [text/plain]​

*************************************************************************************

What am I missing? Please help. Thanks.

Re: CAM authentication 401 error - TM1 REST API

Posted: Wed Apr 19, 2017 6:22 am
by krishnadixit
Any breakthrough?
Has anybody implemented CAM authentication in REST API?
Please help.

Re: CAM authentication 401 error - TM1 REST API

Posted: Wed Apr 19, 2017 1:06 pm
by BrianL
Someone else has asked this question on the IBM DeveloperWorks site. https://www.ibm.com/developerworks/comm ... 0bc02186ca

The answer appears to be
I have been working on this as well for a development project. I spoke with Guido at IBM offering management and he confirmed the only way to access Planning Analytics (cloud) from the REST API is with non-interactive user accounts.

When you do this you should use the CAMNamespace header in the following format.

CANNamespace:base64(UN:PW:NameSpace)

My understanding is that this is a problem with the way IBM BlueID works. Cloud Dev is working on a new authentication method that will allow for 3rd party access to the PA Cloud REST API via named user accounts.



keep in mind PA Local has no such issue.

Re: CAM authentication 401 error - TM1 REST API

Posted: Thu Apr 20, 2017 5:46 am
by failurehappening
As Brian said it's of the form
CANNamespace:base64(UN:PW:NameSpace)
but you need to convert the (UN:PW:NameSpace) string to bytes and the encode the bytes to give you the encoded authorisation.

The way I connect is using an HttpPost object and then adding the authorisation as a header, which is a slightly different method of doing it to the way you're looking at it, but you can probably work it out from this though:

Code: Select all

String tm1Url = Constants.getBaseURL()+  "/api/v1/ExecuteMDX?$expand=Axes($expand=Hierarchies($select=Name),Tuples($expand=Members($select=Name))),Cells";
HttpPost httpPost = new HttpPost(tm1Url);
httpPost.addHeader("Authorization", Constants.getAuthorisationType()  + Constants.getAuthorisation());
This is a snippet of my Constants class:

Code: Select all

public class Constants {
	private static String hostname = "hostname.company.com"; 
	private static String portNumber = "12345"; 
	private static String userName = "admin"; 
	private static String password = "apple"; 
	private static String nameSpace = "namespace";
	private static String authorizationType = "CAMNamespace "; 
	
	private static String authorization = userName + ":" + password+ ":" + nameSpace; 
	private static String baseURL = "http://" + hostname + ":" + portNumber;
		
	private static byte[] authorizationBytes = authorization.getBytes(StandardCharsets.UTF_8);
	private static String authorizationEncoded = Base64.getEncoder().encodeToString(authorizationBytes);

	

	public Constants() {
	}

	public static String getBaseURL(){
		return baseURL;
	}
	
	public static String getAuthorisation(){
	return authorizationEncoded;
	}

	public static String getAuthorisationType () {
		return authorizationType;
		}

}

Re: CAM authentication 401 error - TM1 REST API

Posted: Thu Apr 20, 2017 2:16 pm
by krishnadixit
failurehappening wrote:As Brian said it's of the form
CANNamespace:base64(UN:PW:NameSpace)
but you need to convert the (UN:PW:NameSpace) string to bytes and the encode the bytes to give you the encoded authorisation.

The way I connect is using an HttpPost object and then adding the authorisation as a header, which is a slightly different method of doing it to the way you're looking at it, but you can probably work it out from this though:

Code: Select all

String tm1Url = Constants.getBaseURL()+  "/api/v1/ExecuteMDX?$expand=Axes($expand=Hierarchies($select=Name),Tuples($expand=Members($select=Name))),Cells";
HttpPost httpPost = new HttpPost(tm1Url);
httpPost.addHeader("Authorization", Constants.getAuthorisationType()  + Constants.getAuthorisation());
This is a snippet of my Constants class:

Code: Select all

public class Constants {
	private static String hostname = "hostname.company.com"; 
	private static String portNumber = "12345"; 
	private static String userName = "admin"; 
	private static String password = "apple"; 
	private static String nameSpace = "namespace";
	private static String authorizationType = "CAMNamespace "; 
	
	private static String authorization = userName + ":" + password+ ":" + nameSpace; 
	private static String baseURL = "http://" + hostname + ":" + portNumber;
		
	private static byte[] authorizationBytes = authorization.getBytes(StandardCharsets.UTF_8);
	private static String authorizationEncoded = Base64.getEncoder().encodeToString(authorizationBytes);

	

	public Constants() {
	}

	public static String getBaseURL(){
		return baseURL;
	}
	
	public static String getAuthorisation(){
	return authorizationEncoded;
	}

	public static String getAuthorisationType () {
		return authorizationType;
		}

}
I think I am doing the same thing in a different way. I am converting UserID, Pwd, and Namespace to bytes, and encoding the bytes to authorization. What & where wrong am I doing or what am I missing? :?
Its kinda of frustrating as I am stuck on this from weeks now :cry:

Any specific and full code available? Please help

Re: CAM authentication 401 error - TM1 REST API

Posted: Thu Apr 20, 2017 3:20 pm
by BrianL
I'm not sure the code is your problem.
I have been working on this as well for a development project. I spoke with Guido at IBM offering management and he confirmed the only way to access Planning Analytics (cloud) from the REST API is with non-interactive user accounts.
I'm assuming that 'Administrator' is actually an interactive user account...

Re: CAM authentication 401 error - TM1 REST API

Posted: Mon May 08, 2017 2:33 pm
by krishnadixit
Hi all,

Thanks for replies.
After breaking head for about 20+ days I finally could crack it. Thought of sharing the solution just in case if anybody gets stuck like me.
My code is good, however, it needs to run on IBM specific JRE. I was running it on Oracle JRE and hence was not getting through CAM. Reason not clear but issue is resolved. May be due to SSL version.

Cheers all :D