I am using adal4j v1.1.2 to get token based on client certificate.
Snippet referred: Why does AcquireToken with ClientCredential fail with invalid_client (ACS50012)?
String AAD_HOST_NAME = "login.windows.net";
String AAD_TENANT_ID = "XXX";
String AAD_TENANT_ENDPOINT = "https://" + AAD_HOST_NAME + "/" + AAD_TENANT_ID + "/";
String AAD_CLIENT_ID = "XXX";
String AAD_RESOURCE_ID = "https://vault.azure.net";
String AAD_CERTIFICATE_PATH = "/XXX.pfx";
String AAD_CERTIFICATE_PASSWORD = "XXX";
String AAD_CLIENT_SECRET = "XXX";
ExecutorService service = ExecutorServiceHelper.createThreadPool(1, "azureHSMClientExecutorService-");
KeyStore keystore = KeyStore.getInstance("PKCS12", "SunJSSE");
keystore.load(new FileInputStream(AAD_CERTIFICATE_PATH),AAD_CERTIFICATE_PASSWORD.toCharArray());
String alias = keystore.aliases().nextElement();
PrivateKey key = (PrivateKey) keystore.getKey(alias, AAD_CERTIFICATE_PASSWORD.toCharArray());
X509Certificate cert = (X509Certificate) keystore.getCertificate(alias);
AsymmetricKeyCredential asymmetricKeyCredential = AsymmetricKeyCredential.create(AAD_CLIENT_ID,key, cert);
AuthenticationContext ctx = new AuthenticationContext(AAD_TENANT_ENDPOINT, false, service);
Future<AuthenticationResult> result = ctx.acquireToken(AAD_RESOURCE_ID, asymmetricKeyCredential, null);
AuthenticationResult authenticationResult = result.get();
String token = authenticationResult.getAccessToken();
This results in following auth exception
AuthenticationException: com.microsoft.aad.adal4j.AuthenticationException: {"error":"invalid_client","error_description":"AADSTS70002: Error validating credentials. AADSTS50027: Invalid JWT token. No certificate thumbprint specified in token header.\r\nTrace ID: 9719e621-d8ef-4194-93cd-a78103d5df6b\r\nCorrelation ID: f0300795-fb99-44b2-bd95-8df3975290be\r\nTimestamp: 2016-08-29 13:51:26Z"}
I'm not sure how to pass thumbprint while calling acquireToken. Is anything missing here?
According to your code, it seems that you want to authenticate with Azure Service Management API using certificate, but the code for getting access token seems to authenticate using Azure AD. You can refer to the article Authenticating Service Management Requests to know their differences.
As reference, there is a blog which introduce how to consume Windows Azure Service Management API with certificate in Java.
However, per my experience, according to the code String AAD_RESOURCE_ID = "https://vault.azure.net"; , it also seems that you want to do some management operations for Azure Key Vault. Withing the REST API reference for Azure Key Vault Management, you should get the access token with Azure Resource Manager to do those operations. So if you want to manage Key Vault, please refer to the other blog to know how to authenticate with ARM in Java.
Hope it helps.
Update:
The AAD_RESOURCE_ID for Key Vault should be like /subscriptions/{subscription-id}/resourceGroups/{resource-group-name}/providers/Microsoft.KeyVault/vaults/{vault-name}, please refer to the article https://msdn.microsoft.com/en-us/library/azure/mt620025.aspx and search the keyword resource id and see as the figure below.
And you can get the resource id via Azure CLI command azure keyvault show --vault-name <your-keyvault-name>.
Related
I'm implementing an integration that needs to authenticate with the SAML protocol.
Everything works fine without the Azure AD Token encryption but when it's active i'm unable to authenticate to the IdP.
I've got the .pem file used for the Token encryption but I can't find documentation on how to use this certificate.
I've tried to import the "encryption.pem" in my keystore that already contains the signing certificate and key that I use to sign the request and response (the certificates are different).
I think it does not work because the .pem file I have is a certificate and I think I need to generate a key pair from that cert.
Can someone point out how to do this with OpenSSL or also Java Keytool?
For more infos I'm posting my code that handles the keystore and the ExtendedMetadata bean where I'm trying to link the .pem certificate i got.
Resource storeFile = loader.getResource(keyStoreLocation);
String storePass = samlKeyStorePassword;
Map<String, String> passwords = new HashMap<>();
passwords.put(samlPrivateKeyAlias, samlPrivateKeyPassword);
String defaultKey = samlPrivateKeyAlias;
return new JKSKeyManager(storeFile, storePass, passwords, defaultKey);
// Setup advanced info about metadata
#Bean
public ExtendedMetadata extendedMetadata() {
ExtendedMetadata extendedMetadata = new ExtendedMetadata();
extendedMetadata.setIdpDiscoveryEnabled(false);
extendedMetadata.setSigningAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
extendedMetadata.setSignMetadata(true);
extendedMetadata.setEncryptionKey("enc"); //THIS IS WHERE I'M TRYING TO PUT MY ENCRYPTION KEY
extendedMetadata.setEcpEnabled(true);
return extendedMetadata;
} ```
I am currently using Identity Server 4 which is .Net Core based to issue JWT tokens. I have a .Net Core web api that has middleware in order for the JWT to be validated in the Startup.cs:
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = "http://localhost:5005";
options.Audience = "api1";
});
As we can see, its not asking for much except the location of the token server and who the api is which is `api1. Obviously, its doing some more complex things under the hood.
I found a Java based equivalent to the middleware above, which validates a JWT:
String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkEE";
RSAPublicKey publicKey = //Get the key instance
RSAPrivateKey privateKey = //Get the key instance
try {
Algorithm algorithm = Algorithm.RSA256(publicKey, privateKey);
JWTVerifier verifier = JWT.require(algorithm)
.withIssuer("auth0")
.build(); //Reusable verifier instance
DecodedJWT jwt = verifier.verify(token);
} catch (JWTVerificationException exception){
//Invalid signature/claims
}
This is from HERE as was recommended by the jwt.io site.
Basically I want to be able to implement something in Java that is doing the same thing as the .Net Core code above, but its clearly asking for things like a Public and Private key that I have no idea how to provide at this point, as the JWT is coming through the header of the request.
Under the hood, the Microsoft JWT middleware is going to IdentityServer's discovery endpoint and loading in configuration such as the issuer and JWKS (public keys). The discovery document is always hosted on /.well-known/openid-configuration.
To validate the token, you will at least need the public keys from the JWKS. In the past I've loaded it it using the jwks-rsa library: https://www.scottbrady91.com/Kotlin/JSON-Web-Token-Verification-in-Ktor-using-Kotlin-and-Java-JWT
When validating the access token, as a minimum, you'll also need to check the token's audience (is the token intended for you) and if it has expired.
I´m trying to read out the certificate of an etoken. I´ve followed the answer from Keystore from digital signature e-token using java. It´s giving me the certificates installed in the token but after that the token isn´t reachable anymore. Did somebody got something similar while accessing a token?
// Create instance of SunPKCS11 provider
String pkcs11Config = "name=eToken\nlibrary=C:\\path\\to\\your\\pkcs11.dll";
java.io.ByteArrayInputStream pkcs11ConfigStream = new java.io.ByteArrayInputStream(pkcs11Config.getBytes());
sun.security.pkcs11.SunPKCS11 providerPKCS11 = new sun.security.pkcs11.SunPKCS11(pkcs11ConfigStream);
java.security.Security.addProvider(providerPKCS11); // Get provider KeyStore and login with PIN String pin = "11111111";
java.security.KeyStore keyStore = java.security.KeyStore.getInstance("PKCS11", providerPKCS11);
keyStore.load(null, pin.toCharArray()); // Enumerate items (certificates and private keys) in the KeyStore
java.util.Enumeration<String> aliases = keyStore.aliases();
while (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
System.out.println(alias);
}
The problem persists, after plugging out/in the token is reachable again, but after running the code, the token seems to be locked again. OS Win2k8 Server.
Finally got this clear. After disconnecting other USB devices the Token responds as usual.
The Token should be plugged in to a fully powered port. Best on a separate Host- Bus.
I am using Apache LDAP API to set new attribute: userPassword in Oracle Internet Directory. I want to set this password with SHA encryption method. I currently have following code:
Attribute userPasswordAttribute = new DefaultAttribute("userPassword", "password"));
ModifyRequest modifyRequest = new ModifyRequestImpl();
modifyRequest.setName(dn);
modifyRequest.add(userPasswordAttribute);
ModifyResponse response = connection.modify(modifyRequest);
However this adds SSHA encrypted password along with some other attributes which I do not want (authpassword;oid). I have seen that there a class called EncryptionMethod in LDAP API but how to use it in my code?
Try this
String newPassword = "password";
modifyRequest.replace("userPassword", PasswordUtil.createStoragePassword(
newPassword.getBytes(), LdapSecurityConstants.HASH_METHOD_SHA));
I'm developing a java web service, with client certificate security enabled.
I don't want to add a parameter to each method with a user ID. Since the user is already authenticating through the soap header with his client certificate, is it possible to fetch the user data (common name, email, etc) from his certificate?
Thanks!
This is how you can retrieve DN from the request,
Object certChain = request.getAttribute(
"javax.servlet.request.X509Certificate");
if (certChain != null) {
X509Certificate certs[] = (X509Certificate[])certChain;
X509Certificate cert = certs[0];
String n = cert.getSubjectDN().getName();
}
For this to work, you have to configure the HTTPS connector properly. If AJP is used, you have to configure the AJP connector so the certificate is passed from Apache to Tomcat.
Cast your java.security.cert.Certificate to java.security.cert.X509Certificate and check the methods you have available on it - like getSubjectDN()