4

I use Watson APIs Java SDK and my Authentication was use function setUsernameAndPassword(username, password), but now I want to use Tokens for authentication.

my "Username and Password" Code

mAssistant = new Assistant("2018-02-16");
mAssistant.setUsernameAndPassword(mUserName, mPassword);
InputData input = new InputData.Builder("Hello").build();
MessageOptions options = new MessageOptions.Builder("{workspaceId}")
                                           .input(input)
                                           .build();
MessageResponse response = mAssistant.message(options).execute();
System.out.println(response);

it work fine.

I ues this method to get my token. curl -X GET --user "{username}:{password}" "https://gateway.watsonplatform.net/authorization/api/v1/token?url=https://gateway.watsonplatform.net/conversation/api"

Tokens for authentication
Method-1

mAssistant = new Assistant("2018-02-16");
Map<String, String> map = new HashMap<>();
map.put("X-Watson-Authorization-Token", "{token_string}");
mAssistant.setDefaultHeaders(map);
mAssistant.setSkipAuthentication(true);
InputData input = new InputData.Builder("Hello").build();
MessageOptions options = new MessageOptions.Builder("{workspaceId}")
                                           .input(input)
                                           .build();
MessageResponse response = mAssistant.message(options).execute();
System.out.println(response);

get the error code

E/WatsonService: POST status: 403, error: Forbidden
com.ibm.watson.developer_cloud.service.exception.ForbiddenException: Forbidden
05-07 16:05:57.720 10392-10476/mvi.rcu W/System.err:     at com.ibm.watson.developer_cloud.service.WatsonService.processServiceCall(WatsonService.java:401)
05-07 16:05:57.720 10392-10476/mvi.rcu W/System.err:     at com.ibm.watson.developer_cloud.service.WatsonService$WatsonServiceCall.execute(WatsonService.java:459)

Method-2

mAssistant = new Assistant("2018-02-16");
IamOptions options = new IamOptions.Builder()
                                   .accessToken(token)
                                   .build();
mAssistant.setIamCredentials(options);
mAssistant.setEndPoint("https://gateway.watsonplatform.net/conversation/api");
// do same ... 
// mAssistant.message(options).execute();
// ...

get error message

W/System.err: com.ibm.watson.developer_cloud.service.exception.UnauthorizedException: Unauthorized: Access is denied due to invalid credentials. Tip: Did you set the Endpoint?
W/System.err:     at com.ibm.watson.developer_cloud.service.WatsonService.processServiceCall(WatsonService.java:398)
W/System.err:     at com.ibm.watson.developer_cloud.service.WatsonService$WatsonServiceCall.execute(WatsonService.java:459)

If I want to use Tokens for authentication by Watson APIs Java SDK, what should I do?

Changemyminds
  • 1,147
  • 9
  • 25
  • Could you detail how you got the token? Is it still "fresh" when you try to access the service? – data_henrik May 07 '18 at 09:54
  • I update the got the token detail `curl -X GET --user "{username}:{password}" "https://gateway.watsonplatform.net/authorization/api/v1/token?url=https://gateway.watsonplatform.net/conversation/api"` I use the curl method to get the token and use the token to Watson APIs Java SDK – Changemyminds May 07 '18 at 10:43

3 Answers3

4

EDIT: The below answer works with the token you got before. However, I just noticed that you called the token API using the https://gateway.watsonplatform.net/conversation/api URL. If you instead get a token with https://gateway.watsonplatform.net/assistant/api, your posted code should work fine.


Due to the Conversation -> Assistant rename, there seems to be an issue with authorization using the new name. Therefore, once you get your authorization token, you can use the setEndPoint() method to call the Conversation endpoint, like so:

mAssistant = new Assistant("2018-02-16");
Map<String, String> map = new HashMap<>();
map.put("X-Watson-Authorization-Token", "{token_string}");
mAssistant.setDefaultHeaders(map);
mAssistant.setSkipAuthentication(true);

// change here
mAssistant.setEndPoint("https://gateway.watsonplatform.net/conversation/api");

Assistant is just an alias for Conversation internally so your API calls should work the same.

Alternatively, you could just use the Conversation service directly, although at some point that will go away in favor of just the Assistant service.

Logan Patiño
  • 91
  • 1
  • 10
  • It's work fine for me. So use Watson service token have two method, which method is better ? I added the code in the below question. – Changemyminds May 08 '18 at 01:57
  • I would go with grabbing the token from the Assistant URL, just to be consistent with the service you're using. Like you said though, either way works. – Logan Patiño May 08 '18 at 15:20
0

There is actually an example in the README of the Java SDK: There is a method setIamCredentials() to configure how the Watson service, including Watson Assistant, handles the token-based access. It can manage token refresh for you if you provide the API key, or you pass in the token itself and need to take care of refreshs.

Not tested, but similar to the example for the Discovery service and adapted for you code:

mAssistant = new Assistant("2018-02-16");
IamOptions options = new IamOptions.Builder()
  .apiKey("<iam_api_key>")
  .build();
mAssistant.setIamCredentials(options);

Note that this is using the strategic IBM Cloud IAM (Identity and Access Management), not the Watson service token. That feature was recently added to the Watson services and I would recommend using it. You can manage the API key using the UI or by bx iam commands.

data_henrik
  • 16,724
  • 2
  • 28
  • 49
  • I only have the "{token_string}", so I don't use apiKey, I change the method to amOptions options = new IamOptions.Builder().accessToken("{token_string}").build(); and It didn't work. – Changemyminds May 07 '18 at 09:09
  • `status: 401, error: Not Authorized W/System.err: com.ibm.watson.developer_cloud.service.exception.UnauthorizedException: Unauthorized: Access is denied due to invalid credentials. Tip: Did you set the Endpoint?` so I need to add EndPoint `mAssistant.setEndPoint("https://gateway.watsonplatform.net/conversation/api");` but It not work again. The error message is the same as above. Is my endPoint url set wrong ? I only want to use authtoken. – Changemyminds May 07 '18 at 10:36
  • I updated the answer, somehow I overread that you were using the Watson tokens, not the IBM Cloud IAM tokens. You can use the UI or CLI to obtain the API key. – data_henrik May 07 '18 at 11:30
  • if i want to use watson token, i couldn't use Watson APIs Java SDk, right? Do you have any suggestion? – Changemyminds May 07 '18 at 12:07
  • There is only built-in support for the IAM tokens which is the strategic method to authenticate. You don't need any userid / password and can assign different API keys. – data_henrik May 07 '18 at 12:20
0

The below code work fine for me, but I have the question, which method is better ?

Method-1

Get token by url https://gateway.watsonplatform.net/assistant/api

curl -X GET --user {username}:{password} "https://gateway.watsonplatform.net/authorization/api/v1/token?url=https://gateway.watsonplatform.net/assistant/api"

Use token

mAssistant = new Assistant("2018-02-16");
Map<String, String> map = new HashMap<>();
map.put("X-Watson-Authorization-Token", "{token_string}");
mAssistant.setDefaultHeaders(map);
mAssistant.setSkipAuthentication(true);

Method-2

Get token by url https://gateway.watsonplatform.net/conversation/api

curl -X GET --user {username}:{password} "https://gateway.watsonplatform.net/authorization/api/v1/token?url=https://gateway.watsonplatform.net/conversation/api"

Use token

mAssistant = new Assistant("2018-02-16");
Map<String, String> map = new HashMap<>();
map.put("X-Watson-Authorization-Token", "{token_string}");
mAssistant.setDefaultHeaders(map);
mAssistant.setSkipAuthentication(true);
mAssistant.setEndPoint("https://gateway.watsonplatform.net/conversation/api");
Changemyminds
  • 1,147
  • 9
  • 25