Google Sheets java sdk OAuth non autorisé après quelques heures (spring boot)


J'ai créé avec succès une spring boot Serviceclass afin d'écrire sur Google sheets, en suivant le Java Quistart Tutorial for Sheets API

Mon problème est que l'autorisation ne se renouvelle pas, donc après la première authentification réussie via le navigateur, après quelques heures, je reçois 401 non autorisé. Comment puis-je renouveler automatiquement le jeton sans réémettre la connexion du navigateur?

Ci-Dessous le code, merci d'avance

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver.Builder;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.sheets.v4.Sheets;
import com.google.api.services.sheets.v4.SheetsScopes;
import com.google.api.services.sheets.v4.model.AppendValuesResponse;
import com.google.api.services.sheets.v4.model.ValueRange;

@Service
public class GoogleSheetsServiceImpl implements GoogleSheetsService {

    private static final Log LOGGER = LogFactory.getLog(GoogleSheetsServiceImpl.class);

    /** Application name. */
    @Value("${google-sheets.application-name}")
    private String applicationName;

    /** Directory to store user credentials for this application. */
    private static final java.io.File DATA_STORE_DIR = new java.io.File(System.getProperty("user.home"),
            ".credentials/sheets.googleapis.com-orders");

    /** Global instance of the {@link FileDataStoreFactory}. */
    private FileDataStoreFactory dataStoreFactory;

    /** Global instance of the JSON factory. */
    private JsonFactory jsonFactory;

    /** Global instance of the HTTP transport. */
    private HttpTransport httpTransport;

    /**
     * Global instance of the scopes required by this quickstart.
     *
     * If modifying these scopes, delete your previously saved credentials at
     * ~/.credentials/sheets.googleapis.com-java-quickstart
     */
    private List<String> scopes;

    /** Sheet service. */
    private Sheets sheetsService;

    public GoogleSheetsServiceImpl() throws Throwable {
        // init
        try {
            this.jsonFactory = JacksonFactory.getDefaultInstance();
            this.scopes = Arrays.asList(SheetsScopes.SPREADSHEETS);
            this.httpTransport = GoogleNetHttpTransport.newTrustedTransport();
            this.dataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR);
        } catch (Throwable t) {
            LOGGER.error("Error on init Google Sheets Service: " + t.getMessage());
            throw t;
        }

        // get sheet service
        Credential credential = this.authorize();
        this.sheetsService = new Sheets.Builder(this.httpTransport, this.jsonFactory, credential)
                .setApplicationName(this.applicationName).build();
    }

    public void appendValueRangeToGoogleSheet(String spreadsheetId, String range, ValueRange valueRange)
            throws IOException {

        // append line
        Sheets.Spreadsheets.Values.Append request = sheetsService.spreadsheets().values()
                .append(spreadsheetId, range, valueRange).setValueInputOption("RAW");
        AppendValuesResponse response = request.execute();
    }

    /**
     * Creates an authorized Credential object.
     * 
     * @return an authorized Credential object.
     * @throws IOException
     */
    private Credential authorize() throws IOException {
        // Load client secrets.
        InputStream in = GoogleSheetsServiceImpl.class.getResourceAsStream("/google_sheets/client_secret.json");
        GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(this.jsonFactory, new InputStreamReader(in));

        // Build flow and trigger user authorization request.
        GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(this.httpTransport, this.jsonFactory,
                clientSecrets, this.scopes).setDataStoreFactory(this.dataStoreFactory).setAccessType("online").build();
        LocalServerReceiver.Builder localServerReceiverBuilder = new Builder();
        localServerReceiverBuilder.setHost("localhost");
        localServerReceiverBuilder.setPort(46228);
        Credential credential = new AuthorizationCodeInstalledApp(flow, localServerReceiverBuilder.build())
                .authorize("user");
        LOGGER.info("Credentials saved to " + DATA_STORE_DIR.getAbsolutePath());
        return credential;
    }

}

Modifier:

Résolu modification la construction de l'objet GoogleAuthorizationCodeFlow comme suit:

GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(this.httpTransport, this.jsonFactory,
            clientSecrets, this.scopes).setDataStoreFactory(this.dataStoreFactory).setAccessType("offline")
                    .setApprovalPrompt("force")
                    .addRefreshListener(
                            new DataStoreCredentialRefreshListener(credentialUserId, this.dataStoreFactory))
                    .build();
Author: user4330585, 2017-10-12

1 answers

Il existe un concept nommé refresh token et il semble qu'il corresponde à vos besoins.

Vous pouvez trouver bien discribe dans cette question: https://stackoverflow.com/a/7209263/4988996

Edit: Selon votre commentaire, j'ai trouvé que Google a DataStoreCredentialRefreshListener

Accédez aux ressources protégées à l'aide des informations d'identification. Les jetons d'accès expirés sont automatiquement actualisés à l'aide du jeton d'actualisation, le cas échéant. Assurez-vous d'utiliser DataStoreCredentialRefreshListener pour les informations d'identification à l'aide des informations d'Identification.Constructeur.addRefreshListener (CredentialRefreshListener).

Paiement: https://developers.google.com/api-client-library/java/google-oauth-java-client/oauth2

static void addDataStoreCredentialRefreshListener( Credential.Builder credentialBuilder, String userId, DataStoreFactory dataStoreFactory) throws IOException { credentialBuilder.addRefreshListener( new DataStoreCredentialRefreshListener(userId, dataStoreFactory)); }

 2
Author: Furkan Yavuz, 2017-10-19 16:35:31