0

I want to authenticate and get a specific course org unit id using valence and java. I have a application id and user key for the application I got from the d2l keytool. I am also using d2l's java client library for authenticating. i.e. com.d2lvalence.idkeyauth.*;

I am getting a http 403 error on the last line of code.
Can someone see what I doing wrong?

        URL url = null;
        URLConnection connection = null;
        String host = "ucbdev.desire2learn.com";
        int port = 443;
        String appID = "from d2l";
        String appKey = "from d2l";
        String userId = "";
        String userKey = "";

        AuthenticationSecurityFactory factory = new AuthenticationSecurityFactory();
        // appID and appKey are from d2l
        ID2LAppContext appContext = factory.createSecurityContext(appID, appKey);

        URI resultUri=new URI("?x_a=fromd2l&x_b=fromd2l");
        ID2LUserContext userContext=appContext.createUserContext(resultUri, host, port, true);
        if (userContext == null){
            System.out.println("USERCONTEXT is NULL");
        }
        System.out.println("USERCONTEXT HOST NAME IS :"+userContext.getHostName());

        userId = userContext.getUserId();
        userKey = userContext.getUserKey();
        System.out.println("userID is "+userId);
        System.out.println("userKey is "+userKey);

        URI newUri = userContext.createAuthenticatedUri("/d2l/api/lp/1.0/orgstructure/", "GET");
        String res = newUri.toString();
        System.out.println("authenticated uri usercontext s "+res);
        connection = newUri.toURL().openConnection();

        //cast the connection to a HttpURLConnection so we can examin the status code
        HttpURLConnection httpConnection = (HttpURLConnection) connection;
        httpConnection.setRequestMethod("GET");
        StringBuilder sb=new StringBuilder();

        BufferedReader in = null;
        //if the status code is success then the body is read from the input stream
        if(httpConnection.getResponseCode()==200) {
            in = new BufferedReader(new InputStreamReader(httpConnection.getInputStream()));
        //otherwise the body is read from the output stream
        } else {
            System.out.println("Error: " + httpConnection.getResponseCode() + ""); //error 403 here
        //    in = new BufferedReader(new InputStreamReader(httpConnection.getErrorStream()));
        }
Kevin
  • 61
  • 3

1 Answers1

1

You do not seem to be clear on how the authentication works for the Valence Learning Framework API. The AppId/AppKey pair you get back from D2L's KeyTool is the keypair that you'll use to prove that your API call comes from your app (i.e. you pass the AppId in the x_a parameter on a normal call, and you use the AppKey to generate a signature that you then pass in the x_c parameter on the call). But each normal API call also requires user tokens to prove the is being made on behalf of a known user:

All our SDKs work in the same general way:

  1. First you create an application context object that's built using your AppID/Key keypair.

  2. Then, you create an "URL for authentication": this URL will be a call to the special "get user tokens" API call (here the x_a parameter is your AppId, and the x_b parameter is the signature).

  3. You direct the user's browser to go to this URL for authentication, and it's x_target query parameter specifies the callback URL where the LMS should send the user ID/Key pair after it successfully determines who the user is.

  4. Once you have this User ID/Key pair, in subsequent normal API calls, you will pass the User ID in the x_b parameter (as you're passing the App Id in the x_a) and you will use the User Key to make a signature that you will pass in the x_d parameter.

Please follow along the authentication conceptual topic in the docs carefully, as it will show you all the steps involved in the process of your app getting back a UserID/Key pair so you can then use it to make API calls.

Viktor Haag
  • 3,363
  • 1
  • 18
  • 21
  • Viktor. The instructions you refer to require use of a browser based login. The system that needs to be developed is a batch java system with no interaction from a user. An alternative way than using a browser to log into is required. Here is the sequence: 1) Authenticate 2) get a specific course org unit id 3) update the course title. This is for about 1000 courses within our desire2learn environment. – Kevin Feb 28 '14 at 15:11
  • The most common recommendation we make in these cases is to build a utility user/role account pair, given only the permissions and enrollments required to accomplish your task. See this other Stack question for more info (http://stackoverflow.com/questions/9946274/authenticaton-method-for-desire2learn-rest-api-vs-soap). – Viktor Haag Mar 05 '14 at 14:38
  • See also this other question here (http://stackoverflow.com/questions/21712396/consuming-the-valence-api-as-an-application). – Viktor Haag Mar 05 '14 at 14:52