You signed in with another tab or window.Reload to refresh your session.You signed out in another tab or window.Reload to refresh your session.You switched accounts on another tab or window.Reload to refresh your session.Dismiss alert
The idea is to uploadYoutube videos in the users account after authenticating the app.The authentication process will happen only once and the app can be able to upload using the stored user credentials.
The sample code for **Youtube Authentication **
publicstaticCredentialauthorize(List<String>scopes,StringcredentialDatastore)throwsIOException {// Load client secrets.ReaderclientSecretReader =newInputStreamReader(Auth.class.getResourceAsStream("/client_secrets.json"));GoogleClientSecretsclientSecrets =GoogleClientSecrets.load(JSON_FACTORY,clientSecretReader);// Checks that the defaults have been replaced (Default = "Enter X here").if (clientSecrets.getDetails().getClientId().startsWith("Enter") ||clientSecrets.getDetails().getClientSecret().startsWith("Enter ")) {System.out.println("Enter Client ID and Secret from https://console.developers.google.com/project/_/apiui/credential " +"into src/main/resources/client_secrets.json");System.exit(1); }// This creates the credentials datastore at ~/.oauth-credentials/${credentialDatastore}FileDataStoreFactoryfileDataStoreFactory =newFileDataStoreFactory(newFile(System.getProperty("user.home") +"/" +CREDENTIALS_DIRECTORY));DataStore<StoredCredential>datastore =fileDataStoreFactory.getDataStore(credentialDatastore);GoogleAuthorizationCodeFlowflow =newGoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT,JSON_FACTORY,clientSecrets,scopes).setCredentialDataStore(datastore) .build();// Build the local server and bind it to port 8080LocalServerReceiverlocalReceiver =newLocalServerReceiver.Builder().setPort(8080).build();// Authorize.returnnewAuthorizationCodeInstalledApp(flow,localReceiver).authorize("user"); }
Problem which I faced was
1. An instance of **jetty server** instance which will be listening constantly until the response is coming from Google as mentioned in the redirect url. 2. Though there is a function called `setHost()` inside `new LocalServerReceiver.Builder()` class which responsible for creating a local jetty server instance, was throughing a **Cannot assign requested address** error everytime a host name was given irrespective of the port which did not matter.
The solution was to stop all the dependencides from the local jetty server at the first place.But then there should a mechanism that will save the credentials when the google callback happens.This can be overcome by creating an endpoint which will save get theauthentication code and exchanging with google for the refresh and access token.All this functions was already given in the AuthorizationCodeInstalledApp.authorize() function.
publicCredentialauthorize(StringuserId)throwsIOException {try {//get the credentials from the stored credentials fileCredentialcredential =flow.loadCredential(userId);if (credential !=null && (credential.getRefreshToken() !=null ||credential.getExpiresInSeconds() >60)) {returncredential; }//otherwise get from the google authentication// open in browserStringredirectUri =receiver.getRedirectUri();//set your custom name-value pairAuthorizationCodeRequestUrlauthorizationUrl =flow.newAuthorizationUrl().setRedirectUri(redirectUri);onAuthorization(authorizationUrl);// receive authorization code and exchange it for an access tokenStringcode =receiver.waitForCode();TokenResponseresponse =flow.newTokenRequest(code).setRedirectUri(redirectUri).execute();// store credential and return itreturnflow.createAndStoreCredential(response,userId); }finally {receiver.stop(); } }
authorize() : This will check whether the credentials of the useris already present then it will return the user credentials.Othewisefollowing process is followed
1.Create an url that will ask the user to give access to the app .2.After successful authentication a code will be received (An instance of jetty server continuously listens untill the code is received ).3.Exchange the code just received with the accesstoken and refreshtoken for offline upload.4.Store the credentials that we just received from google.
To customize this flow we should first create a class which will extendAuthorizationCodeInstalledApp class and will have all the functionality of the above function broken to serve each functionality individually.
/** * Get access token from stored credentials * @param userId lookup the credential file by the userid specified. * @return credential object or null if there is no such userid exits */publicCredentialgetAuthorizationFromStorage(StringuserId){try {//get credentials from storageCredentialcredential=flow.loadCredential(userId);/* check whether the credential object and refresh token is not null as then it can generate new accesstoken * other wise of the access token is not expired */if(credential!=null && (credential.getRefreshToken() !=null ||credential.getExpiresInSeconds() >60))returncredential; }catch (IOExceptione) {e.printStackTrace(); }returnnull; }
HeregetAuthorizationFromStorage gets the user credentials with the userid and returns null if it is not found.
/** * Get the authentication with the credentials from Google * creates the url that will lead the user to the authentication page * and creating a custom defined name-value pair in the state parameter. * The value should be encoded with base64 encoder so we can receive the * same code redirected from google after authentication. * @link http://stackoverflow.com/questions/7722062/google-oauth2-redirect-uri-with-several-parameters * @param userid * @param credentialDatastore * @author soumik 2016-09-27T11:00:40.312Z */publicvoidgetAuthorizationFromGoogle(Stringuserid,StringcredentialDatastore)throwsIOException {//callback url after google authenticationStringredirectUri=GOOGLE_CALLBACK;//create the Json String that will send along with the other parametersGoogleRequestJSONrequestJSON=newGoogleRequestJSON();requestJSON.setUserid(userid);requestJSON.setCredentialDatastore(credentialDatastore);Stringrequest=newGson().toJson(requestJSON);/*Inside state parameter we can encode our custom parameter that * will be received after callback*/AuthorizationCodeRequestUrlauthorizationUrl =flow.newAuthorizationUrl() .setRedirectUri(redirectUri) .set("state",Base64.encodeBase64String(request.getBytes()));onAuthorization(authorizationUrl); }
Now in this function a custom variable is been passed along with the the redirecting URI .The custom parameters have to be encoded with Base64 format and assign it tostate variable. Thisstate variable is sent back after authentication which will identify the user for which the code is sent.
Finally save the credentials and get the the Credential object.
/** * Save the credentials that we get from google. * 1.create the GoogleAuthorizationCodeFlow object from the credentialDatastore * from the response received from the google after authentication. * 2.Hit google to get the permanent refresh-token that can be used to get the * accesstoken of the user any time . * 3.Store the tokens like accesstoken and refreshtoken in the filename as userid * @param userid it will be send in the googlecallback url * @param credentialDatastore it will be send in the googlecallback url * @param code it will be send in the googlecallback url * @return the credential object * @throws URISyntaxException * @throws IOException * @author soumik 2016-09-27T11:00:54.747Z */publicCredentialsaveAuthorizationFromGoogle(Stringuserid,StringcredentialDatastore,Stringcode)throwsURISyntaxException,IOException {// Load client secrets.URIfilePath =newURI(GOOGLE_APIKEY);ReaderclientSecretReader =newInputStreamReader(newFileInputStream(filePath.toString()));//Reader clientSecretReader = new InputStreamReader(Auth.class.getResourceAsStream(GOOGLE_APIKEY));GoogleClientSecretsclientSecrets =GoogleClientSecrets.load(JSON_FACTORY,clientSecretReader);// This creates the credentials datastore at ~/.oauth-credentials/${credentialDatastore}FileDataStoreFactoryfileDataStoreFactory =newFileDataStoreFactory(newFile(System.getProperty("user.home") +"/" +CREDENTIALS_DIRECTORY));DataStore<StoredCredential>datastore =fileDataStoreFactory.getDataStore(credentialDatastore);//Builds a login URL based on client ID, secret, callback URI, and scopesGoogleAuthorizationCodeFlowflow =newGoogleAuthorizationCodeFlow .Builder(HTTP_TRANSPORT,JSON_FACTORY,clientSecrets,SCOPES) .setAccessType("offline") .setApprovalPrompt("auto") .setCredentialDataStore(datastore) .build();//get the refreshtoken from google as soon as we get the code from googleTokenResponseresponse =flow.newTokenRequest(code).setRedirectUri(GOOGLE_CALLBACK).execute();//save the credentials that we got the tokenresponse.Credentialcredential=flow.createAndStoreCredential(response,userid);returncredential; }