How can I set the URI of the Reference node under SignedInfo, under Signature. Why does it not pick the value of the ID from Response object when I sign it?
Here is my code:
QName respQName = new QName(SAMLConstants.SAML20P_NS,Response.DEFAULT_ELEMENT_LOCAL_NAME, "samlp");
Response resp = new ResponseBuilder().buildObject(respQName);
resp.setID(uuid);
//resp.set .......
Signature signature = (Signature) Configuration.getBuilderFactory().getBuilder(Signature.DEFAULT_ELEMENT_NAME) .buildObject(Signature.DEFAULT_ELEMENT_NAME);
signature.setSigningCredential(signingCredential);
signature.setKeyInfo(new SAMLResponseGenerator().getKeyInfo(signingCredential, null, uuid));
assertion.setSignature(signature);
resp.getAssertions().add(assertion);
Signer.signObject(signature);
marshallerFactory = Configuration.getMarshallerFactory();
Element responseTxt = marshallerFactory.getMarshaller(resp).marshall(resp);
System.out.println(XMLHelper.nodeToString(responseTxt));
What am I missing?
In case anybody is facing the same issue: the reference uri seems to come in only when the actual response object is marshalled & then signed. Only signing it without marshalling is not enough. In my case, Iam encrypting the assertion after signing it.
Element responseTxt = new ResponseMarshaller().marshall(resp);
Signer.signObject(signature);
EncryptedAssertion encryptedAssertion = getEncryptedAssertion(resp.getAssertions().get(0), credential);
resp.getAssertions().clear();
resp.getEncryptedAssertions().add(encryptedAssertion);
Related
I am trying to iterate over a paginated list of accounts but when I send a request using the value from "next_uri" I receive an error from the server:
{"errors":[{"id":"not_found","message":"Not found"}]}
I am correctly adding headers etc as all other API calls work fine, its just the request using the "next_uri" that is not working. I think I am following the api spec correctly so I am unsure what is the issue and how to fix it. Does anyone know what is wrong with the code / logic please?
Simplified code:
ArrayList<X> results = new ArrayList<>();
String uri = "/v2/accounts";
javax.ws.rs.client.Client client = getClient();
while(uri != null){
T response = client.target("https://api.coinbase.com")
.path(uri).request(MediaType.APPLICATION_JSON).get(responseType);
results.addAll(response.getData());
uri = response.getPagination()==null ? null :response.getPagination().getNextUri();
}
return results;
The results are this:
Request 1:
https://api.coinbase.com/v2/accounts
Response 1: pagination":
{"ending_before":null,"starting_after":null,"previous_ending_before":null,"next_starting_after":"ef35df6c-a45b-5858-b755-f12a709cf26e","limit":25,"order":"desc","previous_uri":null,"next_uri":"/v2/accounts?starting_after=ef35df6c-a45b-5858-b755-f12a709cf26e"},"data":[{....}]
Request 2:
https://api.coinbase.com/v2/accounts%3Fstarting_after=ef35df6c-a45b-5858-b755-f12a709cf26e
Response 2:
{"errors":[{"id":"not_found","message":"Not found"}]}
This was related to how the jax-rs library needs the query params adding. Just relying on the uri is not enough, the parameters also need adding specifically:
target = target.queryParam(e.getKey(), e.getValue());
so the final code is something like
WebTarget target = client.target(e"https://api.coinbase.com");
if(params !=null){
for(Map.Entry<String, String> e : params.entrySet()){
target = target.queryParam(e.getKey(), e.getValue());
}
}
target = target.path(path);
return target.request(MediaType.APPLICATION_JSON).get(responseType);
I’m using Hyperledger Fabric Java SDK to get a transaction by txId. The return object includes Transaction Information.
TransactionInfo txInfo = channel.queryTransactionByID(txId);
Common.Envelope envelope = txInfo.getEnvelope();
Common.Payload payload = Common.Payload.parseFrom(envelope.getPayload());
The Payload message includes headers and data. I can parse headers by using Common.Header.ChannelHeader and Common.Header.SignatureHeader.
Common.ChannelHeader channelHeader = Common.ChannelHeader.parseFrom(payload.getHeader().getChannelHeader());
Common.SignatureHeader signatureHeader = Common.SignatureHeader.parseFrom(payload.getHeader().getSignatureHeader());
The problem is, I cannot see any message type to get data from Payload.
My expectation would be like,
SomeMessage someMsg = SomeMessage.parseFrom(payload.getData());
What is the ideal approach to get a data object?
Thanks to Driden Myung's tip, Finally found a way to parse QSCC responses into TxReadWriteSet or even KVRWSet !!
Here is an example:
TransactionInfo txInfo = channel.queryTransactionByID(txId);
Common.Envelope envelope = txInfo.getEnvelope();
Common.Payload payload = Common.Payload.parseFrom(envelope.getPayload());
FabricTransaction.Transaction transaction = FabricTransaction.Transaction.parseFrom(payload.getData());
FabricTransaction.TransactionAction action = transaction.getActionsList().get(0); // 0 is a index
FabricTransaction.ChaincodeActionPayload chaincodeActionPayload = FabricTransaction.ChaincodeActionPayload.parseFrom(action.getPayload());
FabricProposalResponse.ProposalResponsePayload prp = FabricProposalResponse.ProposalResponsePayload.parseFrom(chaincodeActionPayload.getAction().getProposalResponsePayload());
FabricProposal.ChaincodeAction ca = FabricProposal.ChaincodeAction.parseFrom(prp.getExtension());
Rwset.TxReadWriteSet txrws = Rwset.TxReadWriteSet.parseFrom(ca.getResults());
TxReadWriteSetInfo txrwsInfo = new TxReadWriteSetInfo(txrws);
KvRwset.KVRWSet kvrwSet = txrwsInfo.getNsRwsetInfo(0).getRwset();
KvRwset.KVWrite kvWrite = kvrwSet.getWrites(0);
String writeVal = kvWrite.getValue().toStringUtf8();
I found the answer.
FabricTransaction.Transaction transaction = FabricTransaction.Transaction.parseFrom(payload.getData());
After that,
FabricTransaction.TransactionAction action = transaction.getActionsList().get(index);
FabricTransaction.ChaincodeActionPayload chaincodeActionPayload = FabricTransaction.ChaincodeActionPayload.parseFrom(action.getPayload());
chaincodeActionPayload.getAction().getEndorsementsList().forEach(endorsement -> {
// This is my current point
???? endorser = ????.parseFrom(endorsement.getEndorser());
});
Let me add if I can find more. Anybody add comments welcome.
We have faced a similar problem to get the request data from a transaction.
The following code will help to get the transaction request data of a transaction
Fabric SDK version : 2.1.4
// get transaction from transaction ID
TransactionInfo txInfo = channel.queryTransactionByID(txId);
// transaction is stored inside the envelope containing the payload and signature
Common.Envelope envelope = txInfo.getEnvelope();
// parse payload from the envelope
Common.Payload payload = Common.Payload.parseFrom(envelope.getPayload());
// payload contains Header and Data. We are parsing data to get the transaction
TransactionPackage.Transaction transaction = TransactionPackage.Transaction.parseFrom(payload.getData());
// get first action from the transaction action list. it contains input and other details
TransactionPackage.TransactionAction action = transaction.getActionsList().get(0); // 0 is a index
// chaincode action payload contains input parameters. So we are taking the action payload
TransactionPackage.ChaincodeActionPayload chaincodeActionPayload = TransactionPackage.ChaincodeActionPayload.parseFrom(action.getPayload());
// chaincode ProposalPayload contains Input and TransientMap. We are parsing actionPayload to proposalPayload
ProposalPackage.ChaincodeProposalPayload prp = ProposalPackage.ChaincodeProposalPayload.parseFrom(chaincodeActionPayload.getChaincodeProposalPayload());
// parse the input to chaincodeInvocationSpec so that we can unmarshal the input
Chaincode.ChaincodeInvocationSpec chaincodeInvocationSpec = Chaincode.ChaincodeInvocationSpec.parseFrom(prp.getInput());
// get the input and parse the arg list and get input arguments
chaincodeInvocationSpec.getChaincodeSpec().getInput().getArgsList().get(ChaincodeInput.ARGS_FIELD_NUMBER).toStringUtf8();
I am new in Docusign.
I have a requirement to create an envelope and show envelope inside Iframe for adding the signature of the user. But I am not getting direct URL by that I user directly sign it.
Currently, the user is getting mail in that user is getting URL. On clicking on that URL, the user is able to sign.
I am using below code to generate URL for Iframe
public ViewUrl getViewUrl(EnvelopeSummary envelopeSummary, Recipients recipients) throws ApiException{
EnvelopesApi envelopesApi = new EnvelopesApi(DocusignFactory.appClient());
RecipientViewRequest returnUrl = new RecipientViewRequest();
returnUrl.setReturnUrl("https://www.docusign.com/devcenter");
returnUrl.setAuthenticationMethod("email");
Signer signer = recipients.getSigners().get(0);
returnUrl.setEmail("myemail#gamil.com");
Tabs tabs = signer.getTabs();
String usename= tabs.getFirstNameTabs().get(0).getName()+" "+tabs.getLastNameTabs().get(0).getName();
returnUrl.setUserName(usename);
return envelopesApi.createRecipientView(DocusignFactory.getDocusignLogin().getAccountId(), envelopeSummary.getEnvelopeId().toString(), returnUrl);}
By using above code I am getting URL. But that URL is just showing the envelope.
Getting Recipients object from EnvelopeTemplate Object and modifying object according to my inputs
public Recipients populateRecipients(Recipients recipients) {
Signer signer = recipients.getSigners().get(0);
signer.setEmail("myemil#gmail.com");
signer.setName("My Name");
//signer.setNote("Here");
signer.setRecipientId("1");
signer.setClientUserId("1001");
signer.setDeliveryMethod("Email");
Tabs tabs = signer.getTabs();
DateSigned dateSigned = tabs.getDateSignedTabs().get(0);
dateSigned.setValue("01/01/2017");
dateSigned.setDocumentId("1");
dateSigned.setRecipientId("1");
//dateSigned.setTabId("1");
List<DateSigned> dateSigneds = new ArrayList<DateSigned>();
dateSigneds.add(dateSigned);
tabs.setDateSignedTabs(dateSigneds);
EmailAddress emailAddress =tabs.getEmailAddressTabs().get(0);
emailAddress.setName("myemil#gmail.com");
emailAddress.setDocumentId("");
emailAddress.setRecipientId("1");
//emailAddress.setTabId("2");
List<EmailAddress> emailAddresss = new ArrayList<EmailAddress>();
emailAddresss.add(emailAddress);
tabs.setEmailAddressTabs(emailAddresss);
FirstName firstName = tabs.getFirstNameTabs().get(0);
firstName.setName("firstName");
firstName.setDocumentId("1");
firstName.setRecipientId("1");
//firstName.setTabId("3");
List<FirstName> firstNames = new ArrayList<FirstName>();
firstNames.add(firstName);
tabs.setFirstNameTabs(firstNames);
LastName lastName = tabs.getLastNameTabs().get(0);
lastName.setName("lastName");
lastName.setDocumentId("1");
lastName.setRecipientId("1");
//lastName.setTabId("4");
List<LastName> lastNames = new ArrayList<LastName>();
lastNames.add(lastName);
tabs.setLastNameTabs(lastNames);
signer.setTabs(tabs);
List<Signer> signers = new ArrayList<Signer>();
signers.add(signer);
recipients.setSigners(signers);
return recipients;
You're missing one of the required parameters for the Recipient View (https://docs.docusign.com/esign/restapi/Envelopes/EnvelopeViews/createRecipient) method --
clientUserId A sender created value that shows [that] the recipient is embedded (captive). Maximum of 100 characters.
Create a value for the clientUserId and include it for the signer when you create the transaction (when you send the signing request).
Then include it when you want the Recipient View. It's a security measure to ensure that it is ok for your web app to authenticate the signer.
Only include the clientUserId for signers where you can authenticate them yourself and you plan to offer them the embedded signing view.
If we try to parse an expired JWT, results in expired exception.
Is there a way to read claims even the JWT was expired.
Below is used to parse JWT in java:
Jwts.parser().setSigningKey(secret.getBytes()).parseClaimsJws(token).getBody();
There is a better approach to do this.
if you see JWT Exception handler object e.g. ExpiredJwtException, expection object itself contains the following:-
header, claims and message
so claims can easily extracted through this object i.e. e.getClaims().getId() where e is ExpiredJwtException object.
ExpiredJwtException consturct is as follow:-
public ExpiredJwtException(Header header, Claims claims, String message) {
super(header, claims, message);
}
Example:-
try{
// executable code
}catch(ExpiredJwtException e){
System.out.println("token expired for id : " + e.getClaims().getId());
}
JWT objects are Base64URL encoded. This means that you can always read headers and payload by manually Base64URL-decoding it. In this case you will simply ignore exp attribute.
For instance you can do like this (I'm using Java8 built-in Base64 class, but you can use any external library, such as Apache Commons Codec):
Base64.Decoder decoder = Base64.getUrlDecoder();
String src = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImV4cCI6IjEzMDA4MTkzODAifQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.2GpoV9q_uguSg0Ku6peI5aZ2qBxO5qOA42zaS25gq_c";
String[] parts = src.split("\\."); // Splitting header, payload and signature
System.out.println("Headers: "+new String(decoder.decode(parts[0]))); // Header
System.out.println("Payload: "+new String(decoder.decode(parts[1]))); // Payload
and the output is:
Headers: {"alg":"HS256","typ":"JWT","exp":"1300819380"}
Payload: {"sub":"1234567890","name":"John Doe","admin":true}
Please note also that the exp attribute is set to 1300819380, which corresponds to 16 january 2016.
this might be old but for anyone whose facing this issue, the java's io.jsonwebtoken
ExpiredJwtException already got the claims in it, you can get it by calling e.getClaims().
If you use io.jsonwebtoken you try my function:
public Claims getClaimsFromToken(String token) {
try {
// Get Claims from valid token
return Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token)
.getBody();
} catch (ExpiredJwtException e) {
// Get Claims from expired token
return e.getClaims();
}
}
If Someone comes in looking for jose4j library then below works:
invalidJwtException.getJwtContext().getJwtClaims()
Just set the ValidateLifetime property of the TokenValidationParameters to false before calling ValidateToken.
TokenValidationParameters tokenValidationParameters = new TokenValidationParameters();
tokenValidationParameters.ValidateLifetime = false;
JwtSecurityTokenHandler jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
ClaimsPrincipal principal = jwtSecurityTokenHandler.ValidateToken(token, tokenValidationParameters, out SecurityToken validatedToken);
Then you can read the claims like this:
string name = principal.Claims.FirstOrDefault(e => e.Type.Equals(ClaimTypes.Name)).Value;
string email = principal.Claims.FirstOrDefault(e => e.Type.Equals(ClaimTypes.Email)).Value;
I'm trying to create a SAML response. One of the attributes that makes up the assertion is called address and the attribute value needs to be a custom type that is defined in an XSD. How do I add custom attribute value types to the response?
If your attribute value XML is in String form:
String yourXMLFragment = "...";
AttributeStatementBuilder attributeStatementBuilder =
(AttributeStatementBuilder) builderFactory.getBuilder(AttributeStatement.DEFAULT_ELEMENT_NAME);
AttributeStatement attributeStatement = attributeStatementBuilder.buildObject();
AttributeBuilder attributeBuilder =
(AttributeBuilder) builderFactory.getBuilder(Attribute.DEFAULT_ELEMENT_NAME);
Attribute attr = attributeBuilder.buildObject();
attr.setName("yourAttributeName");
XSAnyBuilder sb2 = (XSAnyBuilder) builderFactory.getBuilder(XSAny.TYPE_NAME);
XSAny attrAny = sb2.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSAny.TYPE_NAME);
attrAny.setTextContent(yourXMLFragment.trim());
attr.getAttributeValues().add(attrAny);
attributeStatement.getAttributes().add(attr);
Actually this above does not yeld correct results. The above example can be used only to create xsany with text content not xml content (xml content gets escaped).
So after digging in opensaml sources the following did work as needed:
public XSAny createXSAny(Element dom)
{
XSAnyBuilder anyBuilder = (XSAnyBuilder) Configuration.getBuilderFactory().getBuilder(XSAny.TYPE_NAME);
XSAny any = anyBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSAny.TYPE_NAME);
// this builds only the root element not the whole dom
XSAny xo=anyBuilder.buildObject(dom);
// set/populate dom so whole dom gets into picture
xo.setDOM(dom);
any.getUnknownXMLObjects().add(xo);
return any;
}