upload file to dropbox by java - java

I am working on creating a simple desktop program in Java, and I want to upload files via this program to Dropbox, but the problem is that the access token has a short life (temporary), how can I make the access token have a long life, or if I can use the App key and App secret?
I need a simple solution like a method or a java example.
Is there anything better than Dropbox in this aspect and more flexible?
Thanks for any help.
This method works fine but the access token expires after a few hours
private void testUplaod() throws FileNotFoundException, IOException, DbxException {
DbxClientV2 client;
DbxRequestConfig config = new DbxRequestConfig("dropbox/TestUplaod");
try (InputStream in = new FileInputStream("D:\\t1.txt")) {
client = new DbxClientV2(config, ACCESS_TOKEN);
FileMetadata metadata = client.files().uploadBuilder("/t1.txt")
.uploadAndFinish(in);
}
I was expecting it would work sustainably.

When you get the access token, you should also receive a refresh token. When the access token expires, you make an API call with the refresh token to get a new one.

Dropbox is no longer offering the option for creating new long-lived access tokens. Dropbox is switching to only issuing short-lived access tokens (and optional refresh tokens) instead of long-lived access tokens. You can find more information on this migration here.
Apps can still get long-term access by requesting "offline" access though, in which case the app receives a "refresh token" that can be used to retrieve new short-lived access tokens as needed, without further manual user intervention. It's not possible to get a refresh token from the "Generate" button; you need to use the OAuth flow. You can find more information in the OAuth Guide and authorization documentation. There's a basic outline of processing this flow in this blog post which may serve as a useful example.
The official Dropbox Java SDK can actually handle the process for you automatically, as long as you supply the necessary credentials, e.g., as shown retrieved in the examples.

Related

Android, AccountManager and OAuth

I'm sure this is basic and I'm missing something. I've read through other answers on SO, I've googled, I've read resources and I just can't wrap my head around what I need to do.
I'm trying to figure out how to write an app that connects to Twitch's API, specifically how to authenticate with Twitch's api. Their documentation is here: https://github.com/justintv/Twitch-API/blob/master/authentication.md
I've created an app and stored my keys.
Now comes the part where I want my user to click a button which launches the authentication on their website. From what I can tell I do this by using an AccountManager. Except... I can't figure out what I'm supposed to do.
Here's the excerpt I've found online:
AccountManager am = AccountManager.get(this);
Bundle options = new Bundle();
am.getAuthToken(
myAccount_, // Account retrieved using getAccountsByType()
"Manage your tasks", // Auth scope
options, // Authenticator-specific options
this, // Your activity
new OnTokenAcquired(), // Callback called when a token is successfully acquired
new Handler(new OnError())); // Callback called if an error occurs
According to twitch's documentation I want to send the user to:
https://api.twitch.tv/kraken/oauth2/authorize
?response_type=code
&client_id=[your client ID]
&redirect_uri=[your registered redirect URI]
&scope=[space separated list of scopes]
&state=[your provided unique token]
And I simply have no idea how these two things need to be combined.
Firstly, I recommend to read the OAuth2 RFC. This should cover everything you need to know.
The AccountManager code snippet won't help you much unless there already is an app that provides authentication for Twitch. If that's not the case you either need to use an existing OAuth2 library or implement your own.
You could write your own AccountAuthenticator but that's a different challenge (and you still need some kind of OAuth2 client).
Doing it yourself is not that hard, see below.
Steps to implement it yourself
Twitch recommends to use the "Implicit Grant Flow" for mobile apps. That's what I'm going to describe below.
1. Get a client ID
Register your app as outlined in Developer Setup to get a client ID
As redirect URI you can use something like https://localhost:12398/, the actual port doesn't really matter.
2. Build the authentication URL
In your client app you need to construct the authentication URL like so:
https://api.twitch.tv/kraken/oauth2/authorize?
response_type=token&
client_id=[your client ID]&
redirect_uri=[your registered redirect URI]&
scope=[space separated list of scopes]
Apparently [your client ID] should be replaced by the client ID you've received from Twitch, same goes for [your registered redirect URI] (that's the URL above, i.e. https://localhost:12398/). [space separated list of scopes] is the list of scopes (i.e. features your want to access), see Scopes. Make sure you URL-encode the parameter values properly.
Assuming your client ID is 123456 and the scopes you need are user_read and channel_read your URL would look like this:
https://api.twitch.tv/kraken/oauth2/authorize?
response_type=token&
client_id=123456&
redirect_uri=https%3A%2F%2Flocalhost%3A12398%2F&
scope=user_read%20channel_read
Note that you should also pass a state parameter, just use a randomly generated value. You can also append the (non-standard) force_verify parameter to make sure the user actually needs to log in each time (instead of continuing a previous session), but I think you can achieve the same by clearing the cookie store (given that you open the URL in a webview in the context of your app) before you open the login page.
With a random state the URL would look like this:
https://api.twitch.tv/kraken/oauth2/authorize?
response_type=token&
client_id=123456&
redirect_uri=https%3A%2F%2Flocalhost%3A12398%2F&
scope=user_read%20channel_read&
state=82hdknaizuVBfd9847guHUIhndzhuehnb
Again, make sure the state value is properly URL encoded.
3. Open the authentication URL
Ideally you just open the URL in a WebView inside of your app. In that case you need to intercept all request to load a new URL using WebViewClient.shouldOverrideUrlLoading
Once the client is redirected to your redirect URL you can close the webview and continue with step 4.
Theoretically it's possible to utilize the default browser to do the authentication, but I would have security concerns since an external app could learn about your client ID and the access token.
4. Extract the access token
The actual URL you get redirected to in step #3 will have the form:
https://[your registered redirect URI]/#access_token=[an access token]&scope=[authorized scopes]
or to pick up the example
https://localhost:12398/#access_token=xxx&scope=user_read%20channel_read
Where xxx is the actual access token.
If you passed a state it will be present like so:
https://localhost:12398/#access_token=xxx&scope=user_read%20channel_read&state=82hdknaizuVBfd9847guHUIhndzhuehnb
All you have to do now is to parse the (URL encoded) access token, scope and state. Compare the scopes and state to the ones that you actually sent. If they match you can start using the access_token to authenticate.
Note According to the OAuth2 RFC, the response URL MUST also contain a token_type and it SHOULD contain an expires_in duration in seconds.
Once you received the access token you can use it to authenticate as described here.
Access tokens issued by the Implicit Grant Flow usually expire after a certain time and the user needs to authenticate again. The Twitch documentation doesn't mention any expiration time, so it's possible that the token is valid forever. So make sure your app doesn't store it or store it in a secure way (like using Android's key store provider to generate and store a key to encrypt the access token).
If the implicitly issued access token expires you could consider using the "Authorization Code Flow". That's quite similar but it contains an additional step to receive the access token and a "refresh token" that can be used to renew the access token. I leave it up to you to figure out how that works.

Google Drive API - OAuth2.0: How to Automate Authentication Process? Doubts and Questions

I'm trying to integrate Google APIs inside a project (Thesis project) and I have some doubts and questions. So, here it is the scenario:
I wrote a back-end application in Java that runs solely from a command-line and has absolutely no interaction with a user. Its goal is to allow communication and interaction between sensors and actuators. Everything works great. Now I'd like to integrate something in order to let the sensors backup data both with a certain periodicity and due to some detected threshold value. So I thought, why not trying with Google Drive. The first very useful links have been:
https://developers.google.com/drive/web/quickstart/quickstart-java
https://developers.google.com/accounts/docs/OAuth2InstalledApp
Quick start examples work like a charm. However it requires quite a bit of settings: create a project inside the Developer Console (therefore an account), enable Drive API, then create a Client ID and a Client Secret. Once you've done these steps, you can hard-coded client ID and secret to form the request URL for google drive. Then you're kindly asked to enter the url in a browser, log in if you're not, accept and finally copy and paste into your console the authorization code for obtaining an access token. Wow, quite a security proccess. But hey, I completely agree with it, above all in a scenario where we have either a web app, a smartphone app or a web service that needs users' authentication and authorization in order to let the app doing its job by accessing someone else account. But in my case, I just would like that sensors will backup data on my google drive.
These facts lead to my first question: in order to use Google APIs (Drive in this case), do I have to create a project anyway? Or is there another approach? If I'm not wrong, there aren't other ways to create a client Id and secret without creating a project inside the Developer Console. This puzzles me a lot. Why should I create a project to use basically some libraries?
So, let's assume the previous as justifiable constraints and move on the real question: how to automate the authentication process? Given my scenario where a sensor (simply a Java module) want to backup data, it would be impossible to complete all that steps. The google page about OAuth 2.0 has a great explanations about different scenarios where we can embed the authentication procedure, included one for "devices with limited input capabilities". Unluckily, this is more complicated then the others and requires that "The user switches to a device or computer with richer input capabilities, launches a browser, navigates to the URL specified on the limited-input device, logs in, and enters the code." (LOL)
So, I didn't give up and I ended up on this post that talks about OAuth Playground: How do I authorise an app (web or installed) without user intervention? (canonical ?). It really looks like as a solution for me, in particular when it says:
NB2. This technique works well if you want a web app which access
your own (and only your own) Drive account, without bothering to write
the authorization code which would only ever be run once. Just skip
step 1, and replace "my.drive.app" with your own email address in step
5.
However if I'm not wrong, I think that OAuth Playground it's just for helping test and debug projects that use Google APIs, isn't it? Moreover, Google drive classes such as GoogleAuthorizationCodeFlow and GoogleCredential (used inside the Java quick start example) always need Client ID, Client Secret and so on, which brings me to point zero (create a project and do the whole graphical procedure).
In conclusion: is there a way to avoid the "graphical" authentication interaction and convert it into an automated process using only Drive's APIs without the user intervention? Thanks a lot, I would be grateful for any tip, hint, answer, pointer :-)
This is just a snippet of code that I wrote thanks to pinoyyid suggestions. Just to recap what we should do in this case (when in your program there isn't a user interaction for completing all the Google GUI authentication process). As reported in https://developers.google.com/drive/web/quickstart/quickstart-java
Go to the Google Developers Console.
Select a project, or create a new one.
In the sidebar on the left, expand APIs & auth. Next, click APIs. In the list of APIs, make sure the status is ON for the Drive API.
In the sidebar on the left, select Credentials.
In either case, you end up on the Credentials page and can create your project's credentials from here.
From the Credentials page, click Create new Client ID under the OAuth heading to create your OAuth 2.0 credentials. Your application's client ID, email address, client secret, redirect URIs, and JavaScript origins are in the Client ID for web application section.
The pinoyyd post is neater and get straight to the point: How do I authorise a background web app without user intervention? (canonical ?)
Pay attention to step number 7
Finally the snippet of code is very simple, it's just about sending a POST request and it's possible to do that in many ways in Java. Therefore this is just an example and I'm sure there is room for improvements ;-)
// Both to set access token the first time that we run the module and in general to refresh the token
public void sendPOST(){
try {
URL url = new URL("https://www.googleapis.com/oauth2/v3/token");
Map<String,Object> params = new LinkedHashMap<>();
params.put("client_id", CLIENT_ID);
params.put("client_secret", CLIENT_SECRET);
params.put("refresh_token", REFRESH_TOKEN);
params.put("grant_type", "refresh_token");
StringBuilder postData = new StringBuilder();
for (Map.Entry<String,Object> param : params.entrySet()) {
if (postData.length() != 0) postData.append('&');
postData.append(URLEncoder.encode(param.getKey(), "UTF-8"));
postData.append('=');
postData.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
}
byte[] postDataBytes = postData.toString().getBytes("UTF-8");
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length));
conn.setDoOutput(true);
conn.getOutputStream().write(postDataBytes);
BufferedReader in_rd = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
// Read response body which should be a json structure
String inputLine;
StringBuilder responseBody = new StringBuilder();
while ((inputLine = in_rd.readLine()) != null) {
responseBody.append(inputLine);
}
in_rd.close();
//Parsing Response --> create a json object
JSONObject jsonResp = new JSONObject(responseBody);
//Modify previous access token String
ACCESS_TOKEN = jsonResp.getString("access_token");
}
catch(MalformedURLException ex_URL){
System.out.println("An error occured: " + ex_URL.getMessage());
}
catch(JSONException ex_json) {
System.out.println("An error occured: " + ex_json.getMessage());
}
catch(IOException ex_IO){
System.out.println("An error occured: " + ex_IO.getMessage());
}
} //end of sendRefreshPOST method
Hope this snippet of code will help others that will face the same situation !
I wrote the SO post at How do I authorise an app (web or installed) without user intervention? (canonical ?)
What it describes is indeed the solution to your use-case. The key bit you'd missed is step 7 where you enter the details of your own application into the OAuth Playground. From that point, the playground is impersonating your app and so you can do the one-time authorization and obtaining a refresh token.

How to auto-authenticate with box.com java sdk

My question is similar to this post:
How to get an access token without Box’s authorization page
In that post, he asks:
I have been granted access(collaborate) in a folder. What I need is to access the folder daily and fetch files from it. Right now the developer token I generate expires in 1 hour. Is there a way I can get the authorization code without the first leg, which requires a user interface. This way I can refresh the access toke whenever I fetch files.
The highest rated answer from "Skippy Ta" tells me most of what I need to know EXCEPT the following:
How do I authenticate using the developer token and how do I refresh? From the github repo for the HelloWorld sample app (https://github.com/box/box-java-sdk-v2) I downloaded, I see these two steps:
boxClient.authenticate(boxOAuthToken);
for the initial authentication, and
boxClient.addOAuthRefreshListener(new OAuthRefreshListener() {
#Override
public void onRefresh(IAuthData newAuthData) {
// TODO: Update the stored access token.
}
});
for the refresh.
I'm having trouble putting all this together. First, the authenticate method does not accept a String boxOAuthToken, it accepts an IAuthData object, whatever that is. So I cannot conduct the initial authentication.
Even if I were to achieve initial authentication, I could not refresh, because I don't know how to access the token once I'm authenticated in order to store it, and if I stored that token as a String, I don't know how to wrap it in the proper object and conduct the update alluded to by the
// TODO: Update the stored access token.
comment above. Thanks for any help you can offer.
You can take a look at the javafx login UI: https://github.com/box/box-java-sdk-v2/tree/master/BoxJavaFxOAuth
But anyway if you need to build a BoxOAuthToken object from access token and refresh token and authenticate from it, here is what you can do:
HashMap<String, String> tokenMap = new HashMap<String, String>();
tokenMap.put("access_token", access);
tokenMap.put("refresh_token", refresh);
BoxOAuthToken token = new BoxOAuthToken(tokenMap);
boxClient.authenticate(token);
As for the refresh, the sdk auto-refreshes. The only time you need to worry about it is when your app quits and you need to persist the auth. At that point you can save the oauth token out. The refresh listener is used to update the oauth token for you so at the point you need to save oauth out, you have the latest oauth data.

How to get offline token and refresh token and auto-refresh access to Google API

I'm developing an app that accesses Google APIs (starting with Calendar API) using OAuth2 and the google client libraries for that (is on Appengine and GWT BTW).
I have implemented my OAuth2Call back servlet, extending the Google AbstractAppEngineAuthorizationCodeCallbackServlet.
I have it working, I get access and can look at calendars etc, but have two problems:
1) I do not get a refresh token, despite explicitly requesting offline access:
public static GoogleAuthorizationCodeFlow newFlow( String scope ) throws IOException {
GoogleAuthorizationCodeFlow.Builder builder = new GoogleAuthorizationCodeFlow.Builder(
HTTP_TRANSPORT,
JSON_FACTORY,
getClientSecrets(),
Collections.singleton( scope ) );
builder.setCredentialStore( new AppEngineCredentialStore() ).setAccessType("offline");
return builder.build();
}
2) I cannot see how to set the automatic refresh functionality.
These pages describe the methods:
Class Credential.Builder
Class CredentialStoreRefreshListener
But I can't see where to add the refresh listener. There is no such method in the GoogleAuthorizationCodeFlow.Builder class, unlike the Credential.Builder class
EDIT
After debugging the code more, when the credential comes back (in the onSuccess() method) it seems to have a RefreshListener set already.....so maybe that's their by default, and my only problem is I'm not getting a refresh_token, despite asking for it.
Maybe need to review settings in the Google API Console also?
One thing you should be careful about: a refresh token is returned (in addition to the access token) only when the user gives consent explicitly for the requested scopes. Basically, when the approval page is shown. All subsequent flows will only return an access token.
Now, in order to test your application and make sure you receive the refresh token the first time around, you could use the approval_prompt=force parameter (builder.setApprovalPrompt("force")) to make sure the approval page is shown in the flow and you obtain explicit consent from the user. After you sort out any issues and make sure the refresh tokens are stored properly, you can remove that flag (the default is auto)
More information is also available in the offline access section in the developer guide.
To get the refresh token you have to set both accessType = "offline" and approvalPrompt = "force".
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
HTTP_TRANSPORT,
JSON_FACTORY,
CLIENT_ID,
CLIENT_SECRET,
SCOPE)
.setAccessType("offline")
.setApprovalPrompt("force")
.build();
I looked into this, and concluded that the access_token only needs to be used once. That is, every Google query is a two step process:
Use the refresh_token to generate a temporary access_token
Use the access_token for the one or more queries necessary for your operation.
I've seen a couple posts here about ensuring that the server clock is synchronized. But that seems like unnecessary complexity.
For a more detailed explanation: http://www.tqis.com/eloquency/googlecalendar.htm

OAuth protocol / java- Scribe : storing the token?

I've been playing with the [scribe API][1] and a basic example e.g:
https://github.com/fernandezpablo85/scribe-java/blob/master/src/test/java/org/scribe/examples/TwitterExample.java
In a command line oriented interface, the user is asked to open a web-browser and to copy'n paste the "accessToken".
Once the user has copied the "accessToken", I want to avoid this "browser step" in the later invocations of the tool: can I store the "accessToken" somewhere to re-use it later ? would it work for any server (Twitter ? Flickr... ) ? How should I change the code to reuse the previously saved "accessToken" ?
Thanks,
In the case of the Twitter API you should store the access token as it represents the user's permission for your application to access their account.
However, bear in mind that the token may be revoked by the user, so ensure your application is able to obtain it again.
To change the code to use a previously saved accessToken all you would have to do is look up the token for the current user - perhaps it's retrieved from a database, and then start making requests. Essentially you would just skip the whole "obtaining request token" block of code.

Categories

Resources