Signing Both Message and Assertion with Java Saml from Onelogin - saml-2.0

I am trying to follow this answer: https://stackoverflow.com/a/46000524/13925339
I can sign the SAML Response message:
String saml = "...";
String pubKeyBytes = "...";
String privKeyBytes = "...";
Document documentResponse = Util.loadXML(saml); //loads string to document
X509Certificate cert = null;
cert = Util.loadCert(pubKeyBytes);
PrivateKey privateKey = Util.loadPrivateKey(privKeyBytes);
//sign saml assertion:
String stringSignedResponse = Util.addSign(documentResponse, privateKey, cert, null);
I can pull out the SAML Assertion and sign that:
NodeList nodelist = documentResponse.getElementsByTagName("saml2:Assertion");
Node nodeSamlAssertion = nodelist.item(0);
String stringSignedSamlAssertion = Util.addSign(nodeSamlAssertion, privateKey, cert, null);
BUT how do I combine the two (as is possible with OneLogin's https://www.samltool.com/sign_response.php online tool in 'Sign Message and Assertion' mode)?

Worked out how to do this by
Turning the String returned from Util.addSign(nodeSamlAssertion,..) back into a Node
Importing that Node back into the SAML response Document object.
Using the Element.replaceChild method to switch the unsigned SAML Assertion node with the signed SAML Assertion node
Element nodeSignedSamlAssertion = DocumentBuilderFactory
.newInstance()
.newDocumentBuilder()
.parse(new ByteArrayInputStream(stringSignedSamlAssertion.getBytes()))
.getDocumentElement();
Node copiedNode = documentResponse.importNode(nodeSignedSamlAssertion, true);
documentResponse.getDocumentElement().replaceChild(copiedNode, documentResponse.getElementsByTagName("saml2:Assertion").item(0));

Related

Got a timeout error when I send an email using gmail:ClientConnector in ballerinalang

I try to implement a program in ballerina to send an email using ballerina gmail:ClientConnector with gmail API. But it gives a timeout error like below.
error: ballerina.lang.errors:Error, message: failed to invoke 'post' action in ClientConnector. response was not received within sender timeout of 180 seconds
at ballerina.net.http:ClientConnector.post(<native>:0)
at org.wso2.ballerina.connectors.oauth2:ClientConnector.post(org/wso2/ballerina/connectors/oauth2/ClientConnector.bal:53)
at org.wso2.ballerina.connectors.gmail:ClientConnector.sendMail(org/wso2/ballerina/connectors/gmail/gmailConnector.bal:631)
at .:main(helloworld.bal:26)
And here is the code which I implement.
import org.wso2.ballerina.connectors.gmail;
function main (string[] args) {
string clientId = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
string clientSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
string userId = "webmisproject#gmail.com";
string accessToken = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
string refreshToken = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
gmail:ClientConnector gmailConnector = create gmail:ClientConnector(userId,accessToken,refreshToken,clientId,clientSecret);
string to = "b.wathsala.bw#gmail.com";
string subject = "Test Mail";
string from = "webmisproject#gmail.com";
string messageBody = "Hello Buddhi";
string cc = "";
string bcc = "";
string id = "";
string threadId = "";
message gmailResponse;
gmailResponse = gmail:ClientConnector.sendMail(gmailConnector,to,subject,from,messageBody,cc,bcc,id,threadId);
}
I implement this code as in main function as well as a service in ballerina, but both give same error.As well it takes little bit time to give that error.
I solved that problem. I used UBUNTU 14.04. But when I run that code in UBUNTU 16.04 the issue was solved. So I think the problem is in UBUNTU 14.04. But I don't know what is the exact issue in UBUNTU 14.04.

Read Mail Attchments in appengine using Java

I am using App Engine application to receive emails to a specific list of email address ending with #my-app-id.appspotmail.com will be sent to your application.
Multipart multiPart = (Multipart) message.getContent();
BodyPart bp = multiPart.getBodyPart(0);
log.info("count is "+multiPart.getCount());
String attachFiles = "";
String messageContent = "";
for (int i = 0; i < multiPart.getCount(); i++) {
MimeBodyPart part = (MimeBodyPart) multiPart.getBodyPart(i);
if (Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition())) {
// this part is attachment
String fileName = part.getFileName();
log.info("file name is "+fileName);
} else {
// this part may be the message content
messageContent = part.getContent().toString();
}
}
I want to store the File inside a Blob store but i did not find an API for it, It is going inside the IF loop and am able to get the attachment file name. Any help will be appreciated.
You can read all the data inside the attachment part using the MimeBodyPart.getInputStream method, but you'll need to read the data yourself and create the Blob.

Spring LDAP AD paging support not working - LDAP: error code 12 - 00000057: LdapErr: DSID-0C09079A

When trying to run the code above I'm getting javax.naming.OperationNotSupportedException with the message:
[LDAP: error code 12 - 00000057: LdapErr: DSID-0C09079A, comment: Error processing control, data 0, v2580].
The first page is successfully retrieved and the exception is thrown only at second loop iteration.
public void pagedResults() {
PagedResultsCookie cookie = null;
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
int page = 1;
do {
logger.info("Starting Page: " + page);
PagedResultsDirContextProcessor processor = new PagedResultsDirContextProcessor(20, cookie);
List<String> lastNames = ldapTemplate.search("", initialFilter.encode(), searchControls, UserMapper.USER_MAPPER_VNT, processor);
for (String l : lastNames) {
logger.info(l);
}
cookie = processor.getCookie();
page = page + 1;
} while (null != cookie.getCookie());
}
However, when I remove Spring LDAP using pure implementation as above, it works!
try {
LdapContext ctx = new InitialLdapContext(env, null);
// Activate paged results
int pageSize = 5;
byte[] cookie = null;
ctx.setRequestControls(new Control[] { new PagedResultsControl(pageSize, Control.CRITICAL) });
int total;
do {
/* perform the search */
NamingEnumeration results = ctx .search("",
"(&(objectCategory=person)(objectClass=user)(SAMAccountName=vnt*))",
searchCtls);
/* for each entry print out name + all attrs and values */
while (results != null && results.hasMore()) {
SearchResult entry = (SearchResult) results.next();
System.out.println(entry.getName());
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (int i = 0; i < controls.length; i++) {
if (controls[i] instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc = (PagedResultsResponseControl) controls[i];
total = prrc.getResultSize();
if (total != 0) {
System.out.println("***************** END-OF-PAGE "
+ "(total : " + total
+ ") *****************\n");
} else {
System.out.println("***************** END-OF-PAGE "
+ "(total: unknown) ***************\n");
}
cookie = prrc.getCookie();
}
}
} else {
System.out.println("No controls were sent from the server");
}
// Re-activate paged results
ctx.setRequestControls(new Control[] { new PagedResultsControl(
pageSize, cookie, Control.CRITICAL) });
} while (cookie != null);
ctx.close();
} catch (NamingException e) {
System.err.println("PagedSearch failed.");
e.printStackTrace();
} catch (IOException ie) {
System.err.println("PagedSearch failed.");
ie.printStackTrace();
}
Any hints?
The bad thing about LDAP paged results is that they only work if the same underlying connection is used for all requests. The internals of Spring LDAP get a new connection for each LdapTemplate operation, unless you use the transactional support.
The easiest way to make sure the same connection will be used for a sequence of LDapTemplate operations is to use the transaction support, i.e. configure transactions for Spring LDAP and wrap the target method with a Transactional annotation.
I managed to make my example above work using SingleContextSource.doWithSingleContext approach.
However my scenario is different, my app is service oriented and the paged results as well as the cookie should be sent to an external client so that he decides to request next pages or not.
So as far as I can tell, spring-ldap does not support such case. I must use pure implementation so that I can keep track of the underlying connection during requests. Transaction support could help as well as SingleContextSource, but not among different requests.
#marthursson
Is there any plan in spring ldap to such support in the future?
I found I could use your first example (Spring) as long as I set the ignorePartialResultException property to true in my ldapTemplate configuration and put the #Transactional on my method as suggested.
you can replace ldapTemplate DirContext like this
ldapTemplate.setContextSource(new SingleContextSource(ldapContextSource().getReadWriteContext()));

Testing X509 Certificate Expiry date with C

How can I programaticlaly test if a X509 ?* certificate is expired or not ?
Is their a direct crypto api ?
or I have to get the not_after time and check it manually in my code ?
You didn't say which language so I was summing them up anyway:
php
$data = openssl_x509_parse(file_get_contents('/path/to/cert.crt'));
$validFrom = date('Y-m-d H:i:s', $data['validFrom_time_t']);
$validTo = date('Y-m-d H:i:s', $data['validTo_time_t']);
Java X509Certificate
InputStream inStream = null;
try (InputStream inStream = new FileInputStream("fileName-of-cert")) {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate)cf.generateCertificate(inStream);
// check if valid on specific date (now set for today)
cert.checkValidity(new Date());
// Date nBefore = cert.getNotBefore();
// Date nAfter = cert.getNotAfter();
}
C++
using namespace System;
using namespace System::Security::Cryptography::X509Certificates;
int main()
{
// The path to the certificate.
String^ Certificate = "Certificate.cer";
// Load the certificate into an X509Certificate object.
X509Certificate^ cert = X509Certificate::CreateFromCertFile( Certificate );
// Get the value.
String^ results = cert->GetExpirationDateString();
// Display the value to the console.
Console::WriteLine( results );
}
C
X509 *x
time_t *ptime;
i=X509_cmp_time(X509_get_notBefore(x), ptime);
i=X509_cmp_time(X509_get_notAfter(x), ptime);
You should be able to use:
result=X509_cmp_time(X509_get_notBefore(cert), ptime);
and
result=X509_cmp_time(X509_get_notAfter(cert), ptime);
using OpenSSL. I'm not sure if you can get it less "manual" than that.

Is there anyway to know which user is calling the WCF Ria service on server side, using silverlight on clientside?

Is there anyway to know which user is calling the WCF Ria service on server side? Client side is siverlight, user has to be authenticated first in order to use the system.
I need to know which user is actually calling the service in my current task, thanks, i searched a lot, but seems no good findings.
Once the client side has successfully cleared your authentication challenge, the server can issue a token to the caller on the client side. In subsequent calls to the server, the client would send the token as one of the arguments and the server would verify the token and respond accordingly.
The token can contain a segment of information that identifies a given user, and implementing this will provide the functionality you are seeking.
The only guidelines for generating tokens is that they are unique, non-predictable and expirable. I have always encrypted my tokens so that they appear as gibberish, but step this is optional.
I've also done very much "googleing" and got a lot of headache before I got the solution.
I don't use RIA-Services - but it should be (hopefully) the same...:
The SL-Client sends a "login-request" to the server.
On the (WCF) server-side, I do the following (LoginData = Return-Info for SL-Client):
public LoginData LoginRequest() {
(...)
OperationContext context = OperationContext.Current;
System.ServiceModel.Channels.MessageProperties prp = context.IncomingMessageProperties;
System.ServiceModel.Channels.RemoteEndpointMessageProperty endPrp = prp[System.ServiceModel.Channels.RemoteEndpointMessageProperty.Name] as System.ServiceModel.Channels.RemoteEndpointMessageProperty;
(...)
try {
clientIP = endPrp.Address;
System.Net.IPAddress ipAddress = System.Net.IPAddress.Parse(clientIP);
System.Net.IPHostEntry ipHostEntry = System.Net.Dns.GetHostEntry(ipAddress);
(...)
If you want to check the users WindowsPrincipal, you can do the following (securityGroup = server-side setting, which users can login):
(...)
switch (securityGroup) {
case SecurityGroup.AllClientsCanAccess: {
clientCanLogin = true;
} break;
case SecurityGroup.UseWindowsCredentials: {
if (OperationContext.Current.ServiceSecurityContext != null && OperationContext.Current.ServiceSecurityContext.WindowsIdentity != null) {
if (OperationContext.Current.ServiceSecurityContext.WindowsIdentity.IsAuthenticated) {
if (subSecurityInfo1 == true) { // only clients in specific roles can log in
bool userRoleFound = false;
WindowsPrincipal userPrincipal = new WindowsPrincipal(OperationContext.Current.ServiceSecurityContext.WindowsIdentity);
if (userPrincipal == null)
break;
foreach (string userRoleToPass in subSecurityList) { // subSecurityList = settings, which roles can pass
loginError.ErrorInfo += string.Format("{0}\n", userRoleToPass);
if (userPrincipal.IsInRole(userRoleToPass)) {
clientCanLogin = userRoleFound = true;
break;
}
}
if (userRoleFound) {
loginError.ErrorInfo = string.Empty;
break;
}
else {
loginError.ErrorNo = LoginErrorCodeNoEnum.UserIsNotInRole;
}
}
(...)
Hope it helps...

Resources