Dialogflow authentication programmatically java

2019-07-20 12:54发布

问题:

Hi there I have an issue with the authentication of dialogflow. I know I have to set an GOOGLE_APPLICATION_CREDENTIALS or download Gcloud CLI to acces my agent. But since I am going to use multiple agents I need to login with credentials to my API. So I do not want to use these methods.

I saw in an other thread that there is a code available for node.js who does exactly this what I want.

Dialogflow easy way for authorization.

I want to be able to process my downloaded json file to get acces to the dialogflow agent.

This is what I tried:

//Load the json file 
 String credential = "JSON{}"
 //Read the json file
 GoogleCredentials credentials = GoogleCredentials.fromStream(new 
 ByteArrayInputStream(credential.getBytes())); 
 //Read the project ID           
 String projectId = ((ServiceAccountCredentials)credentials).getProjectId();
 System.out.println("the ID"+ projectId);
 //Read the token
 AccessToken token = ((ServiceAccountCredentials)credentials).getAccessToken();
 System.out.println("the token "+ token);

It displays the projectID but the token is null. and the error I am receiving is

"message": "The Application Default Credentials are not available. They 
are available if running in Google Compute Engine. Otherwise, the 
environment variable GOOGLE_APPLICATION_CREDENTIALS must be defined 
pointing to a file defining the credentials. See 
https://developers.google.com/accounts/docs/application-default- 
credentials for more information.",

So now I am stuck how can I programmatically connect to other agents? without using the GOOGLE_APPLICATION_CREDENTIALS in Java?

Please help me out

回答1:

I had the same problem and I think this is what you're looking for. I have copied the values of each agent configuration credentials json in my own config file, indexed by each projectId, and I read privatekey, privateKeyId, clientEmail, clientId, tokenServerUri from this config file.

Then I build a Credentials object with those values, and then a SessionSettings object with the credentials

This way you can forget about the GOOGLE_APPLICATION_CREDENTIALS environment variable

        PrivateKey privKey = null;

        StringBuilder pkcs8Lines = new StringBuilder();
        BufferedReader rdr = new BufferedReader(new StringReader(privatekey);


        String line;
        while ((line = rdr.readLine()) != null) {
            pkcs8Lines.append(line);
        }

        // Remove the "BEGIN" and "END" lines, as well as any whitespace

        String pkcs8Pem = pkcs8Lines.toString();
        pkcs8Pem = pkcs8Pem.replace("-----BEGIN PRIVATE KEY-----", "");
        pkcs8Pem = pkcs8Pem.replace("-----END PRIVATE KEY-----", "");
        pkcs8Pem = pkcs8Pem.replaceAll("\\s+", "");

        // Base64 decode the result

        byte[] pkcs8EncodedBytes = Base64.getDecoder().decode(pkcs8Pem);

        // extract the private key

        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkcs8EncodedBytes);
        KeyFactory kf;
        try {
            kf = KeyFactory.getInstance("RSA");
            try {
                privKey = kf.generatePrivate(keySpec);
            } catch (InvalidKeySpecException e) {
                throw new GenericException(e);
            }
        } catch (NoSuchAlgorithmException e) {
            throw new GenericException(e);
        }

        Credentials myCredentials = ServiceAccountCredentials.newBuilder().setProjectId(projectId)
                .setPrivateKeyId(privateKeyId).setPrivateKey(privKey)
                .setClientEmail(clientEmail).setClientId(clientId)
                .setTokenServerUri(URI.create(tokenServerUri)).build();

        SessionsSettings sessionsSettings = SessionsSettings.newBuilder()
                .setCredentialsProvider(FixedCredentialsProvider.create(myCredentials)).build();

        try (SessionsClient sessionsClient = SessionsClient.create(sessionsSettings)) {