0

I am new to Azure related concepts and am facing issue in connecting the Azure Key vault.

Please find my code snippets as follows and let me know why am getting the below exception:

Get Key started.../n SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. Get Key failedjava.lang.RuntimeException: java.util.concurrent.ExecutionException: com.microsoft.aad.adal4j.AuthenticationException: {"error_description":"AADSTS70002: Error validating credentials. AADSTS50012: Invalid client secret is provided.\r\nTrace ID: 13f8e909-89d8-472f-a1c1-9f4bcf693700\r\nCorrelation ID: bf818c41-4092-4f7d-8292-b1275a5da62f\r\nTimestamp: 2017-10-17 07:22:12Z","error":"invalid_client"} Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.RuntimeException: java.util.concurrent.ExecutionException: com.microsoft.aad.adal4j.AuthenticationException: {"error_description":"AADSTS70002: Error validating credentials. AADSTS50012: Invalid client secret is provided.\r\nTrace ID: 1234\r\nCorrelation ID: 123456\r\nTimestamp: 2017-10-17 07:22:12Z","error":"invalid_client"} at com.google.common.util.concurrent.AbstractFuture$Sync.getValue(AbstractFuture.java:299) at com.google.common.util.concurrent.AbstractFuture$Sync.get(AbstractFuture.java:286) at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:116) at Program.main(Program.java:88)

Corresponding Code am trying to connect Azure Key Vault :

KeyVaultCredentials kvCred = new ClientSecretKeyVaultCredential("clientID", "client Secret");
    KeyVaultClient vc = new KeyVaultClient(kvCred);



    byte[] byteText = textToEncrypt.getBytes("UTF-16");

    /*************************************/

    // Get Key from Key Vault
    System.out.println("Get Key started.../n");

    start = System.currentTimeMillis();
    ServiceCallback<KeyBundle> serviceCallbackgetkey = new ServiceCallback<KeyBundle>(){
        @Override
        public void failure(Throwable t) {
            System.out.println("Get Key failed"+t.toString());

        }

        @Override
        public void success(KeyBundle result ) {//ServiceResponse
            System.out.println("Get Key Success");
            JsonWebKey myKey = result.key();
            keyIdentifier =  myKey.kid();
            System.out.println("Key ID:"+keyIdentifier);
            end = System.currentTimeMillis();       
            formatter = new DecimalFormat("#0.00000");
            System.out.print("Get Key Execution time is " + formatter.format((end - start) / 1000d) + " seconds\n");
            start = 0;
            end =0;
         }
    };

    ServiceCall<KeyBundle> call = vc.getKeyAsync(keyVaultURI, "MyKey1", serviceCallbackgetkey);

    System.out.println(call.get());

Note: Am using the same Client-ID and Client Secret in postman for connecting a different REST api and is working fine.

Also, I tried executing the following code from here. But facing same issue.

Please help me identifying why am unable to connect the vault.

Esh
  • 836
  • 5
  • 16
  • 43

2 Answers2

2

I tried to reproduce your issue but failed.

I thought your issue probably results from the permission to authorize keyvault API for your application.

You could refer to the code below which works for me.

Program Class:

import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.util.concurrent.ExecutionException;

import com.microsoft.azure.keyvault.KeyVaultClient;
import com.microsoft.azure.keyvault.authentication.KeyVaultCredentials;


public class Program {

    public static void main(String[] args)
            throws InterruptedException, ExecutionException, URISyntaxException, UnsupportedEncodingException {

        KeyVaultCredentials kvCred = new ClientSecretKeyVaultCredential("APP_ID", "APP_SECRET");
        KeyVaultClient vc = new KeyVaultClient(kvCred);
        String keyIdentifier = "https://jaygong.vault.azure.net/keys/jaytest/b21bae081025418c806d73affc2937e0";
        System.out.println(vc.getKey(keyIdentifier));

    }
}

ClientSecretKeyVaultCredential Class:

import java.net.MalformedURLException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import com.microsoft.aad.adal4j.AuthenticationContext;
import com.microsoft.aad.adal4j.AuthenticationResult;
import com.microsoft.aad.adal4j.ClientCredential;
import com.microsoft.azure.keyvault.authentication.KeyVaultCredentials;

public class ClientSecretKeyVaultCredential extends KeyVaultCredentials {
    private String applicationId;
    private String applicationSecret;

    public ClientSecretKeyVaultCredential(String applicationId, String applicationSecret) {
        this.setApplicationId(applicationId);
        this.setApplicationSecret(applicationSecret);
    }

    public String getApplicationId() {
        return applicationId;
    }

    private void setApplicationId(String applicationId) {
        this.applicationId = applicationId;
    }

    public String getApplicationSecret() {
        return applicationSecret;
    }

    private void setApplicationSecret(String applicationSecret) {
        this.applicationSecret = applicationSecret;
    }

    @Override
    public String doAuthenticate(String authorization, String resource, String scope) {
        AuthenticationResult res = null;

        try {
            res = GetAccessToken(authorization, resource, applicationId, applicationSecret);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return res.getAccessToken();
    }

    private AuthenticationResult GetAccessToken(String authorization, String resource, String clientID, String clientKey)
            throws InterruptedException, ExecutionException {
        AuthenticationContext ctx = null;
        ExecutorService service = Executors.newFixedThreadPool(1);
        try {
            ctx = new AuthenticationContext(authorization, false, service);
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        Future<AuthenticationResult> resp = ctx.acquireToken(resource, new ClientCredential(
                clientID, clientKey), null);
        AuthenticationResult res = resp.get();
        return res;
    }

}

Results:

enter image description here

Please notice that you should authorize your application to use the key or secret. Here is the powershell way which is mentioned in the official doc.

Set-AzureRmKeyVaultAccessPolicy -VaultName 'XXXXXXX' -ServicePrincipalName XXXXX -PermissionsToKeys decrypt,sign,get,unwrapKey

Update Answer:

I'm not sure if your application has permission to call KeyVault API. You could add this permission on portal.

enter image description here

Hope it helps you.

Jay Gong
  • 23,163
  • 2
  • 27
  • 32
  • Thanks mate for your effort. unfortunately am still getting the same error. Also tried granting privilege for my application to access the key vault. Not sure what to do further. Also, am pretty sure that the applicationID and secret are working fine as it is working in postman to generate token. – Esh Oct 19 '17 at 06:50
  • @Esh If you're completely using my code and still not working. Consider the issue of parameters or permissions. You could try to regenerate your application and key and retry. I'll continue to help you to fix this issue. – Jay Gong Oct 19 '17 at 07:15
  • Thanks jay for your effort and support. I could see for Microsoft.Azure.ActiveDirectory i have Delegate Permission as 1 and don't have permission for Azure Key Vault(Granting privilege has failed). I think i should get admin privilege to grant special permissions. I will try once again giving same access privilege and let you know. – Esh Oct 19 '17 at 09:14
  • @Esh OK. Maybe that's the key. – Jay Gong Oct 19 '17 at 09:16
  • 1
    figured out the issue, the problem is with the client_secret which has some special characters like % when generated. It seems, the azure key vault is accepting client secret which are encrypted with base64 encoding and it's special characters. Thanks you very much for your effort and for your helping hand. – Esh Oct 19 '17 at 14:59
  • @Esh It's great.The solution you provided gave me very useful experience.You could mark answer for other's reference on the forum.Thank you ! Have a nice day! – Jay Gong Oct 20 '17 at 01:49
1

Figured out the issue, the problem is with the client_secret which has some special characters like % when generated. It seems, the azure key vault is accepting client secret which are encrypted with base64 encoding and it's special characters.

Esh
  • 836
  • 5
  • 16
  • 43