0

I am creating an box android app that allows user to upload media files on their account. I have set up my client id and client secret,it is authenticating my app too. Uploading part is also done,but the problem i am facing is to save the auth data [which is obviously needed so user is not needed to login again and again]

Load, save and use of authentication data in Box Android API the solution given above is not working [may b they have removed 'Utils.parseJSONStringIntoObject' method]

i can store the access token and refresh token but whats the point of saving when i cant use them to re authenticate a user

    switch (requestCode) 
    {
        case AUTHENTICATE_REQUEST:
            if (resultCode == Activity.RESULT_CANCELED) 
            {
                String failMessage = data.getStringExtra(OAuthActivity.ERROR_MESSAGE);
                Toast.makeText(this, "Auth fail:" + failMessage, Toast.LENGTH_LONG).show();
            //    finish();
            }
            else 
            {
                BoxAndroidOAuthData oauth = data.getParcelableExtra(OAuthActivity.BOX_CLIENT_OAUTH);
                BoxAndroidClient client = new BoxAndroidClient(BoxSDKSampleApplication.CLIENT_ID, BoxSDKSampleApplication.CLIENT_SECRET, null, null);
                client.authenticate(oauth);
                String ACCESS_TOKEN=oauth.getAccessToken();
                String REFRESH_TOKEN=oauth.getRefreshToken();
                Editor editor = prefs.edit();
                editor.putString("ACCESS_TOKEN", ACCESS_TOKEN);
                editor.putString("REFRESH_TOKEN", REFRESH_TOKEN);
                editor.commit(); 


                BoxSDKSampleApplication app = (BoxSDKSampleApplication) getApplication();
                client.addOAuthRefreshListener(new OAuthRefreshListener() 
                {
                    @Override
                    public void onRefresh(IAuthData newAuthData) 
                    {
                        Log.d("OAuth", "oauth refreshed, new oauth access token is:" + newAuthData.getAccessToken());
                        //---------------------------------
                        BoxOAuthToken oauthObj=null;
                        try 
                        {
                             oauthObj=getClient().getAuthData(); 
                        }
                        catch (AuthFatalFailureException e) 
                {
                e.printStackTrace();
                }
                        //saving refreshed oauth object in client
                        BoxAndroidOAuthData newAuthDataObj=new BoxAndroidOAuthData(oauthObj);
                        getClient().authenticate(newAuthDataObj);

                    }

                });
                app.setClient(client);
            }

i have referred https://github.com/box/box-android-sdk-v2/tree/master/BoxSDKSample example

can any one tell me what i am doing wrong or any alternative to authenticate user using authdata,access token,refresh token?

UPDATE

refreshing token as they have said 'Our sdk auto refreshes OAuth access token when it expires. You will want to listen to the refresh events and update your stored token after refreshing.'

mClient.addOAuthRefreshListener(new OAuthRefreshListener() 
                {
                    @Override
                    public void onRefresh(IAuthData newAuthData) 
                    {


                        Log.d("OAuth", "oauth refreshed, new oauth access token is:" + newAuthData.getAccessToken());
                        try 
                        {

                             oauthObj=mClient.getAuthData();
                             mClient.authenticate(newAuthData);

                             String authToken=null;
                                //Storing oauth object in json string format
                             try 
                             {
                                 authToken = new BoxJSONParser(new AndroidBoxResourceHub()).convertBoxObjectToJSONString(newAuthData);
                                 prefs.edit().putString("BOX_TOKEN", authToken).commit();
                                 //saving authToken in shared Preferences
                                 mClient.authenticate(newAuthData);
                                String ACCESS_TOKEN=newAuthData.getAccessToken();
                                String REFRESH_TOKEN=newAuthData.getRefreshToken();

                                Log.v("New Access token ", oauthObj.getAccessToken());
                                Log.v("New Refresh token ", oauthObj.getRefreshToken());

                                editor.putString("ACCESS_TOKEN", ACCESS_TOKEN);
                                editor.putString("REFRESH_TOKEN", REFRESH_TOKEN);
                                prefs.edit().putString("BOX_TOKEN", authToken).commit();
                                editor.commit();

                             }
                             catch (BoxJSONException e1) 
                             {
                                    e1.printStackTrace();
                             }
                            Log.v("Token Refreshed", " ");
                        }
                        catch (AuthFatalFailureException e) 
                        {
                            e.printStackTrace();
                        }
                    }
                });
                app.setClient(mClient);
            }

            onClientAuthenticated();

In main activity,fetching stored token

                try 
            {
 stored_oauth_token=prefs.getString("BOX_TOKEN", null);
                authData = new BoxJSONParser(new AndroidBoxResourceHub()).parseIntoBoxObject(stored_oauth_token, BoxAndroidOAuthData.class);
            }
            catch (BoxJSONException e) 
            {
                e.printStackTrace();
            }
                mClient = new BoxAndroidClient(BoxSDKSampleApplication.CLIENT_ID, BoxSDKSampleApplication.CLIENT_SECRET, null, null);
                mClient.authenticate(authData);
                BoxSDKSampleApplication app = (BoxSDKSampleApplication) getApplication();
                app.setClient(mClient);

i tried this app to upload a file after existing ,it did work but after 60-70 odd minutes i couldn't upload file.
is there anything wrong in my code ?

Community
  • 1
  • 1
hardik9850
  • 581
  • 1
  • 9
  • 26

2 Answers2

2

This is how I initialize my Box client:

mClient = new BoxClient(BOX_CLIENT_ID, BOX_CLIENT_SECRET, null, null);
mClient.addOAuthRefreshListener(new OAuthRefreshListener() {
  @Override
  public void onRefresh(IAuthData newAuthData) {
    try {
      String authToken = new BoxJSONParser(new AndroidBoxResourceHub()).convertBoxObjectToJSONString(newAuthData);
      SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
      prefs.edit().putString("box_token", authToken).commit();
    } catch (BoxJSONException e) { }
  }
});

mAuthToken = prefs.getString("box_token", null);
if (mAuthToken != null) {
  BoxAndroidOAuthData authData = new BoxJSONParser(
    new AndroidBoxResourceHub()
  ).parseIntoBoxObject(mAuthToken, BoxAndroidOAuthData.class);
  mClient.authenticate(authData);
}

if (!mClient.isAuthenticated()) {
  Intent intent = OAuthActivity.createOAuthActivityIntent(context, BOX_CLIENT_ID, BOX_CLIENT_SECRET, false, "https://yoururl.com/");
  ((Activity) context).startActivityForResult(intent, BOX_AUTH_REQUEST_CODE);
}
André Restivo
  • 1,271
  • 14
  • 13
  • one more doubt ,in onRefresh() method what should i store as authToken in sharedPref. 1)oauthObj =mClient.getAuthData(); and converting it into authToken by your method or 2)directly newAuthData of onRefresh(IAuthData newAuthData) – hardik9850 Mar 14 '14 at 06:31
  • I'm storing the newAuthData in the shared preferences. The way I think it works, from inspecting the code, is that when a method call fails the API automatically retrieves a new authtoken using the current refresh token. The onRefresh method is then called and is up to you to store that new auth data permanently. – André Restivo Mar 14 '14 at 14:47
  • In the onRefresh method you don't have to reauthenticate. Box will do it for you. You just have to store the new tokens. – André Restivo Mar 18 '14 at 17:07
  • Where are you calling the addOAuthRefreshListener method? Are you sure the method is always called. If not, the token might have expired and you've received a new one but never saved it. – André Restivo Mar 18 '14 at 17:09
  • i have called addOAuthRefreshListener method after user grants my app successfully,before that i am storing authenticating client and storiing oauth data using your method. i am not sure if the method is being called always. – hardik9850 Mar 19 '14 at 04:42
  • i tried implementing OAuthRefreshListener but still it is not working – hardik9850 Mar 19 '14 at 09:08
  • I also had that problem. What happens if the activity is restarted? The user already authorised your app so the refresh listener never gets called. I added my refresh listener right after creating the box client. – André Restivo Mar 19 '14 at 13:36
  • after going through auth flow even if i restart my activity it will work upto 60-70 minutes but after that it crashes(failing to acquire new access token),will try adding refresh listner. after creating client. – hardik9850 Mar 20 '14 at 07:46
  • That happens if Box is unable to refresh the auth token. If it happens just catch the Exception and show an error to your user allowing him to retry. I updated my answer with a more complete example. – André Restivo Mar 20 '14 at 15:08
  • hi Andre,sorry to distrurb you again but could you help me out here,the refresh listener that i have implemented is never getting called [i have modified this file from SDK example](https://www.dropbox.com/s/h2w2eyun1iegh2a/FileListActivity.java).have i made a mistake here? – hardik9850 Apr 10 '14 at 04:34
  • Seems to be ok, although I don't have that code directly in my onCreate method. Two things, you should use Log.e(...) instead of printStackTrace and have you tried printing something when the onRefresh method is called. Also, don't forget that the onRefresh method is only called if you try a call to the box api. That's when box detects it needs to refresh its token. – André Restivo Apr 11 '14 at 07:02
1

So for the auth refresh there are a couple of things to be considered:

  1. box client automatically refreshes OAuth tokens, you'll want to attach a OAuthRefreshListener to listen to the refresh, if you want to persist, persist the oauth data passed into the refresh listener. The listener only update your persisted oauth data, you don't need to re-authenticate in the refresh listener, sdk does the re-authenticate automatically.
  2. When you first initiate box client, you need to authenticate either by persisted auth, or the OAuth UI. The logic should be:

    check client.isAuthenticated();

    2.1 If authenticated, do nothing.

    2.2 if not authenticated, try to check whether there's persisted auth data. If so, authenticate by client.authenticate(oauthdata);

    2.3 if 2.2 failed, start OAuth UI flow.

    2.4 at last, in case of OAuthFatalFailureException, start OAuth UI flow.

Jian Lin
  • 331
  • 1
  • 5
  • i altered my code according to your logic, but my refresh listener is not getting called not even once. please check my code [here](https://www.dropbox.com/s/h2w2eyun1iegh2a/FileListActivity.java) ,and my stack trace [here](https://www.dropbox.com/s/viqp02i92ddgwtq/boxlog.txt).i am handling authfailureException and starting UI authflow but user won't like to login again and again if sdk fails to refresh my tokens. – hardik9850 Apr 04 '14 at 04:57
  • It seems in the onCreate you try to authenticate the BoxClient from stored token. However it seems the token is never stored. In the onActivityResult from the authentication flow, you need to store it. – Jian Lin Apr 07 '14 at 22:28
  • please check line no. 204,210 – hardik9850 Apr 08 '14 at 04:46
  • i tried new [Helloworld example](https://github.com/box/box-android-sdk-v2/tree/master/HelloWorld2) that takes care of refreshing though it also fails to refresh tokens. – hardik9850 Apr 10 '14 at 04:35