AWS cognito does not generate tokens when run from a serverlet - java

I am trying to get amazon cognito to work. If I run the code to generate a login token from a standalone java program it works.
public class cognito extends HttpServlet
{
public static void main(String[] args) throws Exception {
AWSCredentials credentials = new BasicAWSCredentials("*******", "********");
AmazonCognitoIdentityClient client =
new AmazonCognitoIdentityClient(credentials);
client.setRegion(Region.getRegion(Regions.EU_WEST_1));
GetOpenIdTokenForDeveloperIdentityRequest tokenRequest =
new GetOpenIdTokenForDeveloperIdentityRequest();
tokenRequest.setIdentityPoolId("*************");
HashMap<String, String> map = new HashMap<String, String>();
//Key -> Developer Provider Name used when creating the identity pool
//Value -> Unique identifier of the user in your <u>backend</u>
map.put("test", "AmazonCognitoIdentity");
//Duration of the generated OpenID Connect Token
tokenRequest.setLogins(map);
tokenRequest.setTokenDuration(1000l);
GetOpenIdTokenForDeveloperIdentityResult result = client
.getOpenIdTokenForDeveloperIdentity(tokenRequest);
String identityId = result.getIdentityId();
String token = result.getToken();
System.out.println("id = " + identityId + " token = " + token);
}
}
However when I run this code from a servlet on a redhat linux server, it always times out.
Any suggestion would be helpful

map.put("test", "AmazonCognitoIdentity");
are you sure your developer provider name is "test"?
you can see it in your cognito identity pool edit page.
And "AmazonCognitoIdentity" should be your own unique user-id.

Without the actual exception, it is hard to tell what is the exact issue. It could be that something else running in your servlet engine is setting a much more aggressive socket timeout than the default when it runs from the command line. You might want to explicitly set the connection and socket timeouts using methods using this class http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/ClientConfiguration.html and pass it in to the identity client constructor.

Related

Unable to validate google recaptcha enterprise. getting error: java.io.IOException: The Application Default Credentials are not available

Unable to validate google recaptcha enterprise. getting error:
java.io.IOException: The Application Default Credentials are not available.
java.io.IOException: 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.
I have also created credential json with service account and set in environment variable GOOGLE_APPLICATION_CREDENTIALS and alternatively created credential json with aws external account and set in environment variable. but "I was getting required parameters" must be specified error
Note: I am able to get the token from client side but this error is from server side.
Code blocks used to get credentials:
Method1 :
// If you don't specify credentials when constructing the client, the client library will
// look for credentials via the environment variable GOOGLE_APPLICATION_CREDENTIALS.
Storage storage = StorageOptions.getDefaultInstance().getService();
System.out.println("Buckets:");
Page<Bucket> buckets = storage.list();
for (Bucket bucket : buckets.iterateAll()) {
System.out.println(bucket.toString());
}
Method2:
System.setProperty("GOOGLE_APPLICATION_CREDENTIALS", jsonPath);
System.out.println("GOOGLE_APPLICATION_CREDENTIALS");
System.out.println(System.getProperty("GOOGLE_APPLICATION_CREDENTIALS"));
FileInputStream fileInputStream = new FileInputStream(jsonPath);
GoogleCredentials credentials = GoogleCredentials.fromStream(fileInputStream)
.createScoped(Lists.newArrayList("https://www.googleapis.com/auth/cloud-platform"));
Storage storage = StorageOptions.newBuilder().setCredentials(credentials).build().getService();
System.out.println("Buckets:");
Page<Bucket> buckets = storage.list();
for (Bucket bucket : buckets.iterateAll()) {
System.out.println(bucket.toString());
}
Interpreting assesment:
/**
* Create an assessment to analyze the risk of an UI action.
*
* #param projectID: GCloud Project ID
* #param recaptchaSiteKey: Site key obtained by registering a domain/app to use recaptcha services.
* #param token: The token obtained from the client on passing the recaptchaSiteKey.
* #param recaptchaAction: Action name corresponding to the token.
*/
public static void createAssessment(String projectID, String recaptchaSiteKey, String token,
String recaptchaAction)
throws IOException {
// Initialize a client that will be used to send requests. This client needs to be created only
// once, and can be reused for multiple requests. After completing all of your requests, call
// the `client.close()` method on the client to safely
// clean up any remaining background resources.
try (RecaptchaEnterpriseServiceClient client = RecaptchaEnterpriseServiceClient.create()) {
// Specify a name for this assessment.
String assessmentName = "assessment-name";
// Set the properties of the event to be tracked.
Event event = Event.newBuilder()
.setSiteKey(recaptchaSiteKey)
.setToken(token)
.build();
// Build the assessment request.
CreateAssessmentRequest createAssessmentRequest = CreateAssessmentRequest.newBuilder()
.setParent(ProjectName.of(projectID).toString())
.setAssessment(Assessment.newBuilder().setEvent(event).setName(assessmentName).build())
.build();
Assessment response = client.createAssessment(createAssessmentRequest);
// Check if the token is valid.
if (!response.getTokenProperties().getValid()) {
System.out.println("The CreateAssessment call failed because the token was: " +
response.getTokenProperties().getInvalidReason().name());
return;
}
// Check if the expected action was executed.
if (!response.getTokenProperties().getAction().equals(recaptchaAction)) {
System.out.println("The action attribute in your reCAPTCHA tag " +
"does not match the action you are expecting to score");
return;
}
// Get the risk score and the reason(s).
// For more information on interpreting the assessment,
// see: https://cloud.google.com/recaptcha-enterprise/docs/interpret-assessment
float recaptchaScore = response.getRiskAnalysis().getScore();
System.out.println("The reCAPTCHA score is: " + recaptchaScore);
for (ClassificationReason reason : response.getRiskAnalysis().getReasonsList()) {
System.out.println(reason);
}
}
I was able to acheive the same using recaptcha V3 instead of enterprise version. As we had to acheive scored based assesment , V3 supports score based validation.

Connect to HP quality center alm (version 12.50)

We need in our company to connect to HP alm and get differents tests and defects using Java. I work on 64bits machine (jdk 1.8). I tried many solutions on the web, here is different tests and errors I get on each test.
First method: Connecting using comp4j
Here is my Java code:
String url = "https://*****.saas.hpe.com/qcbin/";
String domain = "DEFAULT_827852153";
String project = "827852153_DEMO";
String username = "****";
String password = "*****";
try {
ITDConnection itd = ClassFactory.createTDConnection();
itd.initConnectionEx(url);
System.out.println("Test1:" + itd.connected());
itd.connectProjectEx(domain, project, username, password);
} catch (Exception e) {
e.printStackTrace();
}
The exception I get:
com4j.ExecutionException: com4j.ComException: 80040154 CoCreateInstance failed : Classe non enregistrée : .\com4j.cpp:153
at com4j.ComThread.execute(ComThread.java:236)
at com4j.Task.execute(Task.java:26)
at com4j.COM4J.createInstance(COM4J.java:99)
at com4j.COM4J.createInstance(COM4J.java:74)
at com.mercury.qualitycenter.otaclient.ClassFactory.createTDConnection(Unknown Source)
at infrastructure.Test.main(Test.java:24)
Second method: Connecting using rest api
I followed this tutorial step by step
https://www.consulting-bolte.de/index.php/tech-blog/hp-alm/hp-alm-rest-api/115-connect-to-hp-alm-via-java-using-rest-api
This tutorial uses ALM REST API official documentation
( https://admhelp.microfocus.com/alm/en/12.60/api_refs/REST_TECH_PREVIEW/ALM_REST_API_TP.html#REST_API_Tech_Preview/CodeSamples/infrastructure/RestConnector.htm%3FTocPath%3DExample%2520Application%7Cinfrastructure%7C_____10).
Whatever user or password I pass to the login method it returns status code 200. So login and password aren't considered in the code. But when i try read defects using this code:
AlmConnector alm = new AlmConnector();
RestConnector conn = RestConnector.getInstance();
conn.init(new HashMap<String, String>(), Constants.HOST,
Constants.DOMAIN, Constants.PROJECT);
alm.login("***", "***");
conn.getQCSession();
String defectUrl = conn.buildEntityCollectionUrl("defect");
defectUrl += "/89";
Map<String, String> requestHeaders = new HashMap<String, String>();
requestHeaders.put("Accept", "application/xml");
conn.first = false;
Response res = conn.httpGet(defectUrl, null, requestHeaders);
String postedEntityReturnedXml = res.toString();
Entity entity = EntityMarshallingUtils.marshal(Entity.class,
postedEntityReturnedXml);
List<Field> fields = entity.getFields().getField();
for (Field field : fields) {
System.out.println(field.getName() + " : "
+ field.getValue().size());
}
alm.logout();
alm = null;
I get this exception:
Exception in thread "main" javax.xml.bind.UnmarshalException: élément inattendu (URI : "", local : "html"). Les éléments attendus sont <{}Entity>
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:681)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:247)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:242)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:109)
at
...........
I didn't change anything in the api infrastructure code.
I just want to write a simple Java code which allows me to connect to HP alm and just read defects.
For the COM4J case: you have three issues:
You have to use 32-bit version of Java, since OTAClient.dll is 32-bit and there is no 64-bit version of it unfortunately
You need to install ALM Connectivity Add-in from (https://yoursever/qcbin/PlugIns/TDConnectivity/TDConnect.exe) or register ALM Client
ALM server URL must end with qcbin, while you have: String url = "https://*****.saas.hpe.com/qcbin/"; (ends with /)
For the REST API case: looks like you got HTML instead of XML which is possible when error happens and return code is not 200, then ALM might return HTML with some error message. I would start with checking HTTP return code and checking what is in postedEntityReturnedXml
As a side note - we are developing a product for integration with ALM which is called Bumblebee (https://www.agiletestware.com/bumblebee), so maybe you might have a look at it.

Error using DocuSign AuthenticationApi.login() for Legacy Authentication - Missing grant_type/code

I'm trying to use the Authentication::login() API call in the DocuSign Java SDK and am receiving an error. Here's some code:
#Component
public class TestClass {
private ApiClient apiClient;
public void authenticate() {
this.apiClient = new ApiClient("account-d.docusign.com", "docusignAccessCode",
"mySecretIntegratorKey", "myClientSecret");
final AuthenticationApi authenticationApi = new AuthenticationApi(this.apiClient);
try {
// ERROR ON THE LINE BELOW
final LoginInformation loginInformation = authenticationApi.login();
} catch (final ApiException e) {
// do something appropriate
}
}
}
The mySecretIntegratorKey and myClientSecret values are not the real values I'm sending in obviously, but the other ones are.
Here is the error I am receiving when making the login() call:
Caused by: org.apache.oltu.oauth2.common.exception.OAuthSystemException: Missing grant_type/code
at com.docusign.esign.client.auth.OAuth$OAuthJerseyClient.execute(OAuth.java:184)
at org.apache.oltu.oauth2.client.OAuthClient.accessToken(OAuthClient.java:65)
at org.apache.oltu.oauth2.client.OAuthClient.accessToken(OAuthClient.java:55)
at org.apache.oltu.oauth2.client.OAuthClient.accessToken(OAuthClient.java:71)
at com.docusign.esign.client.auth.OAuth.updateAccessToken(OAuth.java:92)
... 123 common frames omitted
I realize that this is using the older legacy authentication, however I have a limitation that won't allow me to upgrade to the newer method of authentication until the first of the year. So for now I need to use this legacy method using SDK Version 2.2.1.
Any ideas what I'm doing wrong here? I'm sure it is something simple...
Thank you for your time.
You want to use Legacy authentication?
In that case you need to make a number of updates to your code.
Only call new ApiClient(base_url)
Set the X-DocuSign-Authentication header--
From an old Readme:
String authHeader = "{\"Username\":\"" + username +
"\",\"Password\":\"" + password +
"\",\"IntegratorKey\":\"" + integratorKey + "\"}";
apiClient.addDefaultHeader("X-DocuSign-Authentication", authHeader);
Then use the authenticationApi.login to look up the user's Account ID(s) and matching base urls.
The authenticationApi.login doe not actually log you in. (!)
Rather, that method just gives you information about the current user.
There is no login with the API since it does not use sessions. Instead, credentials are passed with every API call. The credentials can be an Access Token (preferred), or via Legacy Authentication, a name / password / integration key triplet.
When using Legacy Authentication, the client secret is not used.
More information: see the Readme section for using username/password in this old version of the repo.
Just in case someone was looking for complete legacy code that works! The below C# code snippet works. This is production ready code. I've tested it and it works. You will have to create an EnvelopeDefinition separately as this code is not included. However, the piece below will authenticate the user and will successfully send an envelope and get back the Envelope ID:
string username = "john.bunce#mail.com";
string password = "your_password";
string integratorKey = "your_integration_key";
ApiClient apiClient = new ApiClient("https://www.docusign.net/restapi");
string authHeader = "{\"Username\":\"" + username + "\", \"Password\":\"" + password + "\", \"IntegratorKey\":\"" + integratorKey + "\"}";
apiClient.Configuration.AddDefaultHeader("X-DocuSign-Authentication", authHeader);
AuthenticationApi authApi = new AuthenticationApi(apiClient.Configuration);
LoginInformation loginInfo = authApi.Login();
string accountId = loginInfo.LoginAccounts[0].AccountId;
string baseURL = loginInfo.LoginAccounts[0].BaseUrl;
string[] baseUrlArray= Regex.Split(baseURL, "/v2");
ApiClient apiClient2 = new ApiClient(baseUrlArray[0]);
string authHeader2 = "{\"Username\":\"" + username + "\", \"Password\":\"" + password + "\", \"IntegratorKey\":\"" + integratorKey + "\"}";
apiClient2.Configuration.AddDefaultHeader("X-DocuSign-Authentication", authHeader2);
EnvelopesApi envelopesApi = new EnvelopesApi(apiClient2.Configuration);
EnvelopeSummary results = envelopesApi.CreateEnvelope(accountId, envelopeDefinition);
string envelopeID = results.EnvelopeId;

Subject must match Issuer claim in the client assertion

I want to integrate office365 service management API for collecting events from it.I want to use client credential way to use service to service call but i am getting following error,
{
"error":"invalid_client",
"error_description":"AADSTS50048: Subject must match Issuer claim in the client assertion.
\r\nTrace ID: 1ad7acd8-3945-4fe0-a313-07638eb76e42\r\nCorrelation ID: a6c3a3c9-b737-4bfc-894f-3086c3ce8dfa\r\nTimestamp: 2016-06-09 07:20:15Z",
"error_codes":[50048
],
"timestamp":"2016-06-09 07:20:15Z",
"trace_id":"1ad7acd8-3945-4fe0-a313-07638eb76e42",
"correlation_id":"a6c3a3c9-b737-4bfc-894f-3086c3ce8dfa"
}
i use following doc to integration,
For getting client assersion,
https://msdn.microsoft.com/en-us/library/azure/dn645543.aspx I am getting this. But for Access token,
https://msdn.microsoft.com/en-us/library/office/dn707383.aspx I not getting this as a response getting above error.
Somebody help me please :)
How did you get the client_assertion? The link you provide doesn’t describe how to get the ‘client_assertion’. It acquire the token with the app’s id and secret which is doesn’t support for the Office 365 Management API. You can refer the blog to about the ‘client_assertion’.
And here is an C# code sample which use the ADAL to get the access token for the client credentials flow:
string clientId = "{clientId}";
string certThumbprint = "‎{copy from mmc}";
certThumbprint = certThumbprint.Replace("\u200e", string.Empty).Replace("\u200f", string.Empty).Replace(" ", string.Empty);
string apiResourceId = "https://manage.office.com";
X509Certificate2 cert = null;
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
string authority = "https://login.windows.net/{yourTentant}";
var authContext = new AuthenticationContext(authority);
try
{
store.Open(OpenFlags.ReadOnly);
cert = store.Certificates.Find(X509FindType.FindByThumbprint, certThumbprint, false)[0];
}
finally
{
store.Close();
}
var certCred = new ClientAssertionCertificate(clientId, cert);
AuthenticationResult result = null;
try
{
result = await authContext.AcquireTokenAsync(apiResourceId, certCred);
}
catch (Exception ex)
{
}

insert a domain name into servlet authentication token

I am using Waffle for an SSO solution in my web-app.
Everything works fine but I would like to modify some functionality slightly:
Currently, if a user is not connected to the domain the SSO fails and opens a little authorization dialog:
The windows authorization requires the user name formatted like Domain\Username but most of my users will not know to add the domain in front of their username. So I would like to provide a default domain name if one is not specified.
I found a waffle function that I can override which will give me access to the decoded authentication token, I added a println to the waffle function and it shows the username in plain text (either with or without the domain depending on what is typed in the dialog):
public IWindowsSecurityContext acceptSecurityToken(String connectionId, byte[] token, String securityPackage) {
// I can see the passed username in the logs with this
System.out.println(new String(token));
// I don't understand any of the JNA stuff below this comment:
IWindowsCredentialsHandle serverCredential = new WindowsCredentialsHandleImpl(
null, Sspi.SECPKG_CRED_INBOUND, securityPackage);
serverCredential.initialize();
SecBufferDesc pbServerToken = new SecBufferDesc(Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
SecBufferDesc pbClientToken = new SecBufferDesc(Sspi.SECBUFFER_TOKEN, token);
NativeLongByReference pfClientContextAttr = new NativeLongByReference();
CtxtHandle continueContext = _continueContexts.get(connectionId);
CtxtHandle phNewServerContext = new CtxtHandle();
int rc = Secur32.INSTANCE.AcceptSecurityContext(serverCredential.getHandle(),
continueContext, pbClientToken, new NativeLong(Sspi.ISC_REQ_CONNECTION),
new NativeLong(Sspi.SECURITY_NATIVE_DREP), phNewServerContext,
pbServerToken, pfClientContextAttr, null);
WindowsSecurityContextImpl sc = new WindowsSecurityContextImpl();
sc.setCredentialsHandle(serverCredential.getHandle());
sc.setSecurityPackage(securityPackage);
sc.setSecurityContext(phNewServerContext);
switch (rc)
{
case W32Errors.SEC_E_OK:
// the security context received from the client was accepted
_continueContexts.remove(connectionId);
// if an output token was generated by the function, it must be sent to the client process
if (pbServerToken != null
&& pbServerToken.pBuffers != null
&& pbServerToken.cBuffers.intValue() == 1
&& pbServerToken.pBuffers[0].cbBuffer.intValue() > 0) {
sc.setToken(pbServerToken.getBytes());
}
sc.setContinue(false);
break;
case W32Errors.SEC_I_CONTINUE_NEEDED:
// the server must send the output token to the client and wait for a returned token
_continueContexts.put(connectionId, phNewServerContext);
sc.setToken(pbServerToken.getBytes());
sc.setContinue(true);
break;
default:
sc.dispose();
WindowsSecurityContextImpl.dispose(continueContext);
_continueContexts.remove(connectionId);
throw new Win32Exception(rc);
}
return sc;
}
That whole function is from the Waffle API I only added the println at the beginning.
The passed username prints in plain text inside this token between a bunch of random byte chars (ÉsR=ÍtÍö?æ¸+Û-).
I am admittedly in very far over my head with JNA and java in general but I thought that because I can see the username here there must be a way to prepend the domain name to the username part of this token? I could be wrong.
My other idea was to add the domain to the pbClientToken that is created from the raw byte[] token this method is passed.
The pbClientToken is a JNA Structure object derivative. It has the Stucture method writeField which looked promising but I can't seem to figure out what field I should write. The Structure.getFields method doesn't seem to be available from pbClientToken.
I was hoping that this was a simple problem for someone more familiar with byte[] processing or JNA.
You cannot do this. What happens behind this dialog is a call to LogonUser on the user's machine, which gives you a ticket, which is then sent to the server. Unfortunately the server is not in the same domain, so even if you manage to extract the username it's completely useless.

Categories