Why is WSPasswordCallback.getPassword null when I try my SOAP request - axis2

I have made an Axis2 web service with Rampart security, but I was constantly receiving NullPointerException at this line:
if((pwcb.getIdentifier().equals("bob")) && pwcb.getPassword().equals("bobPW")) )
So I added this code:
if ( pwcb.getPassword()==null) {
throw new Exception ("passsssssssss is null:"+pwcb.getPassword());
}
Which threw the exception; so I know that the problem is that pwcb.getPassword is null, but don't understand why.
This is the SOAP request I'm sending:
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:nilo="http://nilo">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1">
<wsse:UsernameToken xmlns:wsu="http://docs.oasisopen.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="123">
<wsse:Username>bob</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">bobPW</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<nilo:getdataForChecking>
<nilo:data>tranXml</nilo:data>
</nilo:getdataForChecking>
</soapenv:Body>
</soapenv:Envelope>
Here is the handle method that I'm using:
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
//When the server side need to authenticate the user
WSPasswordCallback pwcb = (WSPasswordCallback)callbacks[i];
if ( pwcb.getPassword()==null) {
try {
throw new Exception ("passsssssssss null:"+pwcb.getPassword());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else {
try {
throw new Exception ("pass nooot null:"+pwcb.getPassword());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(pwcb.getIdentifier().equals("bob") && pwcb.getPassword().equals("bobPW")) {
return;
}
//When the client requests for the password to be added in to the
//UT element
}
}

Whether WSPasswordCallback contains password depends on its usage field. For instance for usage USERNAME_TOKEN_UNKNOWN the password is set and callback handler is supposed to throw an exception, if it does not match username. For SIGNATURE on the other hand, the password field is empty and the callback needs to set it, so that the key can be retrieved from keystore.
You should verify in what scenario callback is called and react appropriately. For instance:
// Rampart expects us to do authentication in this case
if (pwcb.getUsage() == WSPasswordCallback.USERNAME_TOKEN_UNKNOWN) {
String password = passwordFor(pwcb.getIdentifier());
if (pwcb.getPassword().equals(password))
return;
throw new UnsupportedCallbackException(callback,
"password check failed for user " + pwcb.getIdentifier());
}
if (pwcb.getUsage() == WSPasswordCallback.SIGNATURE) {
pwcb.setPassword(passwordFor(pwcb.getIdentifier()));

The handler needs to know the password of the user that initiated the call. You do not have to do the comparison yourself.
Modifying this line from:
if((pwcb.getIdentifier().equals("bob")) && pwcb.getPassword().equals("bobPW")) )
to:
if (pwcb.getIdentifier().equals("bob"))
{
pwcb.setPassword("bobPW");
}

Related

WCF FaultException<T> is not caught in client, instead caught as service fault

I have service configured for FaultException but on the client end I am not getting the exception caught in
catch (FaultException<MyServiceFault> fe)
{
}
instead it is always caught in
catch (FaultException fx)
{
}
I am using selfhost and channelfactory.
my Service:
[FaultContract(typeof(MyServiceFault))]
public string HelloWorld()
{
int a=5;
try
{
var b = a/0;
}
catch(Exception e)
{
throw new FaultException<MyServiceFault>(new MyServiceFault(){Message ="Divide by zero"}, "Divide by Zero");
}
}
I also have the [DataContract] attribute on the MyServiceFault.
I am wondering if I miss any configuration.
I've answered a similar question here: Proper way to throw exception over WCF
Try to declare your operation like this:
[FaultContractAttribute(
typeof(MyServiceFault),
Action = "",
Name = "MyServiceFault",
Namespace = "YourNamespace")]
public string HelloWorld()
Hope it helps.

TCP Server configuration in Mule - writing into client socket

I am trying to create a mule flow with a TCP inbound endpoint which is a TCP server that listens to a port. When a successful client connection is identified, before receiving any request from the client, I need to write a message into the socket (which lets the client know that I am listening), only after which the client sends me further requests. This is how I do it with a sample java program :
import java.net.*;
import java.io.*;
public class TCPServer
{
public static void main(String[] args) throws IOException
{
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(4445);
}
catch (IOException e)
{
System.err.println("Could not listen on port: 4445.");
System.exit(1);
}
Socket clientSocket = null;
System.out.println ("Waiting for connection.....");
try {
clientSocket = serverSocket.accept();
}
catch (IOException e)
{
System.err.println("Accept failed.");
System.exit(1);
}
System.out.println ("Connection successful");
System.out.println ("Sending output message - .....");
//Sending a message to the client to indicate that the server is active
PrintStream pingStream = new PrintStream(clientSocket.getOutputStream());
pingStream.print("Server listening");
pingStream.flush();
//Now start listening for messages
System.out.println ("Waiting for incoming message - .....");
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
{
System.out.println ("Server: " + inputLine);
out.println(inputLine);
if (inputLine.equals("Bye."))
break;
}
out.close();
in.close();
clientSocket.close();
serverSocket.close();
}
}
I have tried to use Mule's TCP inbound endpoint as a server, but I am not able to see how I can identify a successful connection from the client, inorder to trigger the outbound message. The flow gets triggered only when a message is sent across from the client. Is there a way I can extend the functionality of the Mule TCP connector and have a listener which could do the above requirement?
Based on the answer provided, this is how I implemented this -
public class TCPMuleOut extends TcpMessageReceiver {
boolean InitConnection = false;
Socket clientSocket = null;
public TCPMuleOut(Connector connector, FlowConstruct flowConstruct,
InboundEndpoint endpoint) throws CreateException {
super(connector, flowConstruct, endpoint);
}
protected Work createWork(Socket socket) throws IOException {
return new MyTcpWorker(socket, this);
}
protected class MyTcpWorker extends TcpMessageReceiver.TcpWorker {
public MyTcpWorker(Socket socket, AbstractMessageReceiver receiver)
throws IOException {
super(socket, receiver);
// TODO Auto-generated constructor stub
}
#Override
protected Object getNextMessage(Object resource) throws Exception {
if (InitConnection == false) {
clientSocket = this.socket;
logger.debug("Sending logon message");
PrintStream pingStream = new PrintStream(
clientSocket.getOutputStream());
pingStream.print("Log on message");
pingStream.flush();
InitConnection = true;
}
long keepAliveTimeout = ((TcpConnector) connector)
.getKeepAliveTimeout();
Object readMsg = null;
try {
// Create a monitor if expiry was set
if (keepAliveTimeout > 0) {
((TcpConnector) connector).getKeepAliveMonitor()
.addExpirable(keepAliveTimeout,
TimeUnit.MILLISECONDS, this);
}
readMsg = protocol.read(dataIn);
// There was some action so we can clear the monitor
((TcpConnector) connector).getKeepAliveMonitor()
.removeExpirable(this);
if (dataIn.isStreaming()) {
}
return readMsg;
} catch (SocketTimeoutException e) {
((TcpConnector) connector).getKeepAliveMonitor()
.removeExpirable(this);
System.out.println("Socket timeout");
} finally {
if (readMsg == null) {
// Protocols can return a null object, which means we're
// done
// reading messages for now and can mark the stream for
// closing later.
// Also, exceptions can be thrown, in which case we're done
// reading.
dataIn.close();
InitConnection = false;
logger.debug("Client closed");
}
}
return null;
}
}
}
And the TCP connector is as below:
<tcp:connector name="TCP" doc:name="TCP connector"
clientSoTimeout="100000" receiveBacklog="0" receiveBufferSize="0"
sendBufferSize="0" serverSoTimeout="100000" socketSoLinger="0"
validateConnections="true" keepAlive="true">
<receiver-threading-profile
maxThreadsActive="5" maxThreadsIdle="5" />
<reconnect-forever />
<service-overrides messageReceiver="TCPMuleOut" />
<tcp:direct-protocol payloadOnly="true" />
</tcp:connector>
What you're trying to do is a little difficult to accomplish but not impossible. The messages are received by the org.mule.transport.tcp.TcpMessageReceiver class, and this class always consumes the data in the input stream to create the message that injects in the flow.
However, you could extend that receiver and instruct the TCP module to use yours by adding a service-overrides tag in your flow's tcp connector (documented here) and replacing the messageReceiver element.
In your extended receiver you should change the TcpWorker.getNextMessage method in order to send the ack message before read from the input stream.
HTH, Marcos.

Xamarin.Auth with Google APIs: Renew credentials?

I'm trying to use Xamarin.Auth with the Xamarin Google-APIs to login to Google and access Drive. I've managed to get nearly everything working, but the authentication tokens seem to expire after about an hour. Everything works great for awhile, but after about an hour, when I attempt access, I get an Invalid Credentials [401] error and a leak:
Google.Apis.Requests.RequestError
Invalid Credentials [401]
Errors [
Message[Invalid Credentials] Location[Authorization - header] Reason[authError] Domain[global]
]
: GoogleDriveAgent: FetchRemoteFileList() Failed! with Exception: {0}
[0:] Google.Apis.Requests.RequestError
Invalid Credentials [401]
Errors [
Message[Invalid Credentials] Location[Authorization - header] Reason[authError] Domain[global]
]
: GoogleDriveAgent: FetchRemoteFileList() Failed! with Exception: {0}
objc[37488]: Object 0x7f1530c0 of class __NSDate autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool() to debug
objc[37488]: Object 0x7f151e50 of class __NSCFString autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool() to debug
//...more leaks.
I'd like to make sure I'm using Xamarin.Auth and the Google APIs as intended, so here is my code:
In my GoogleDriveService class, I've got an account store and a saved account:
AccountStore Store {
get {
if (m_store == null)
m_store = AccountStore.Create ();
return m_store;
}
}
Account SavedAccount {
get {
var savedAccounts = Store.FindAccountsForService ("google");
m_savedAccount = (savedAccounts as List<Account>).Count > 0 ? (savedAccounts as List<Account>) [0] : null;
return m_savedAccount;
}
}
I initialize a session and start the service:
void InitializeSession ()
{
Authenticator = new GoogleAuthenticator (ClientID, new Uri (RedirectUrl), GoogleDriveScope);
Authenticator.Completed += HandleAuthenticationCompletedEvents;
if (SavedAccount != null) {
Authenticator.Account = SavedAccount;
StartService ();
}
UpdateSignInStatus ();
}
bool StartService ()
{
try {
Service = new DriveService (Authenticator);
return true;
} catch (Exception ex) {
// Log exception
return false;
}
}
...and respond to authentication completed events:
void HandleAuthenticationCompletedEvents (object sender, AuthenticatorCompletedEventArgs e)
{
if (e.IsAuthenticated) { // Success
UpdateSignInStatus();
Store.Save (e.Account, "google");
Authenticator.Account = e.Account;
StartService();
LoginController.DismissViewController(true, null);
} else { // Cancelled or no success
UpdateSignInStatus();
LoginController.DismissViewController(true, null);
LoginController = null;
InitializeSession (); // Start a new session
}
}
Again, everything works fine, for awhile, but then the authentication expires. I understand that it should, but I thought the credentials saved in the AccountStore ought to still work.
In the Xamarin.Auth getting started docs, it says that calling Save again will overwrite the credentials and that "This is convenient for services that expire the credentials stored in the account object." Sounds promising...
So I tried another approach: having an IsSignedIn property that always overwrites the credentials in the getter...
public bool IsSignedIn {
get {
if (Authenticator == null) {
m_isSignedIn = false;
return m_isSignedIn;
}
if (Authenticator.Account != null) {
Store.Save (Authenticator.Account, "google"); // refresh the account store
Authenticator.Account = SavedAccount;
m_isSignedIn = StartService ();
} else {
m_isSignedIn = false;
}
return m_isSignedIn;
}
}
...and then I access IsSignedIn before any API calls (Fetching metadata, downloading, etc). It doesn't work: I'm still getting expired credentials errors shown above.
Is this a case of needing to refresh the token? What am I doing wrong?
Access tokens are supposed to expire relatively quickly. This is why after the first auth you also receive a refresh_token that you can use to get a new access token if the current one expires. Consecutive auths will not give you a refresh token necessarily, so make sure you keep the one you receive!
All you have to do after an access token becomes invalid is use the refresh_token and send an OAuthRequest to the token_url of Google's OAuth endpoint.
var postDictionary = new Dictionary<string, string>();
postDictionary.Add("refresh_token", googleAccount.Properties["refresh_token"]);
postDictionary.Add("client_id", "<<your_client_id>>");
postDictionary.Add("client_secret", "<<your_client_secret>>");
postDictionary.Add("grant_type", "refresh_token");
var refreshRequest = new OAuth2Request ("POST", new Uri (OAuthSettings.TokenURL), postDictionary, googleAccount);
refreshRequest.GetResponseAsync().ContinueWith (task => {
if (task.IsFaulted)
Console.WriteLine ("Error: " + task.Exception.InnerException.Message);
else {
string json = task.Result.GetResponseText();
Console.WriteLine (json);
try {
<<just deserialize the json response, eg. with Newtonsoft>>
}
catch (Exception exception) {
Console.WriteLine("!!!!!Exception: {0}", exception.ToString());
Logout();
}
}
});

why pwcb.getPassword is null in this code

I try to add the rampart security to my axis2 web service using rampart module.
So here is what I have made:
I have stored in a database the hashed value of "bobWWW" password and the salt
In my PWCBHandler.java class
•I select the stored in the database password and hash
•I try to hash with same algorithm pwcb.getPassword() with the same stored salt
•check if this new hashed password is equal to the stored password
But I constantly was receiving nullpointerexception so I decide to check and wrote this code
if(pwcb.getPassword()==null)
{
try {
throw new Exception ("passwordget pass null" +pwcb.getPassword());
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
And I see that pwcb.getPassword() is empty. So here is the code of PWCBHandler.java
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
{
for (int i = 0; i < callbacks.length; i++)
{
WSPasswordCallback pwcb = (WSPasswordCallback)callbacks[i];
try {
pasandsalt = getdataforChecking();
if(pwcb.getPassword()==null)
{
try {
throw new Exception ("passwordget pass null" +pwcb.getPassword());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
passwordforchecking = hash(pwcb.getPassword(),Base64.decodeBase64(pasandsalt[1]));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if((pwcb.getIdentifier().equals("bob")) && (passwordforchecking.equals(pasandsalt[0])) )
{
return;
}
}
And here is my soaprequest with the sequeiry header
var sr =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<soapenv:Envelope " +
"xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" " +
"xmlns:nilo=\"http://nilo\">"+
"<soapenv:Header>"+
'<wsse:Security xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" soapenv:mustUnderstand="1">'+
'<wsse:UsernameToken xmlns:wsu="http://docs.oasisopen.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="123">'+
'<wsse:Username>bob</wsse:Username>'+
'<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">bobWWW</wsse:Password>'+
'</wsse:UsernameToken>'+
'</wsse:Security>'+
"</soapenv:Header>"+
"<soapenv:Body>" +
"<nilo:getdataForChecking>" +
'<nilo:data>'+tranXml+'</nilo:data>' +
' </nilo:getdataForChecking>'+
'</soapenv:Body>' +
'</soapenv:Envelope>';
According to your soap headers i can see you are using a Plain text password instead of Password Digest. You might need to change the rampart configuration
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">bobWWW</wsse:Password>
this might be helpful to you. http://wso2.com/library/240/

Has anyone ever got WS-Trust to work in JBoss 7?

I've literally tried everything under the sun to get token based WS-Trust Web Services to work, to no avail. I can obtain a token from an STS, but the life of me, I can not figure out how make the WS server secure and accessible from the outside using a token.
So what I would love to know, is if anyone has ever got this to work on JBoss 7. I'm not interested in "this and that on jboss should give you some information". Been there done that - doesn't work. Have YOU been able to get it to work?
I looked at picketlink to secure web services using SAML but it appears to be exposing the SAML authentication using a JAAS security context. So instead I just wrote a custom handler using the picketlink API to secure the WS. The handler essentially does the same thing (i.e. saml assertion expiration and digital signature validation check) as the SAMLTokenCertValidatingCommonLoginModule available in picketlink jars but passes the SAML attributes into WS message context instead of passing it along as a JAAS security context.
Find below the code snippet.
See org.picketlink.identity.federation.bindings.jboss.auth.SAMLTokenCertValidatingCommonLoginModule
class of the picketlink-jbas-common source for implementation of methods getX509Certificate, validateCertPath used in the custom handler.
public class CustomSAML2Handler<C extends LogicalMessageContext> implements SOAPHandler {
protected boolean handleInbound(MessageContext msgContext) {
logger.info("Handling Inbound Message");
String assertionNS = JBossSAMLURIConstants.ASSERTION_NSURI.get();
SOAPMessageContext ctx = (SOAPMessageContext) msgContext;
SOAPMessage soapMessage = ctx.getMessage();
if (soapMessage == null)
throw logger.nullValueError("SOAP Message");
// retrieve the assertion
Document document = soapMessage.getSOAPPart();
Element soapHeader = Util.findOrCreateSoapHeader(document.getDocumentElement());
Element assertion = Util.findElement(soapHeader, new QName(assertionNS, "Assertion"));
if (assertion != null) {
AssertionType assertionType = null;
try {
assertionType = SAMLUtil.fromElement(assertion);
if (AssertionUtil.hasExpired(assertionType))
throw new RuntimeException(logger.samlAssertionExpiredError());
} catch (Exception e) {
logger.samlAssertionPasingFailed(e);
}
SamlCredential credential = new SamlCredential(assertion);
if (logger.isTraceEnabled()) {
logger.trace("Assertion included in SOAP payload: " + credential.getAssertionAsString());
}
try {
validateSAMLCredential(credential, assertionType);
ctx.put("roles",AssertionUtil.getRoles(assertionType, null));
ctx.setScope("roles", MessageContext.Scope.APPLICATION);
} catch (Exception e) {
logger.error("Error: " + e);
throw new RuntimeException(e);
}
} else {
logger.trace("We did not find any assertion");
}
return true;
}
private void validateSAMLCredential(SamlCredential credential, AssertionType assertion) throws LoginException, ConfigurationException, CertificateExpiredException, CertificateNotYetValidException {
// initialize xmlsec
org.apache.xml.security.Init.init();
X509Certificate cert = getX509Certificate(credential);
// public certificate validation
validateCertPath(cert);
// check time validity of the certificate
cert.checkValidity();
boolean sigValid = false;
try {
sigValid = AssertionUtil.isSignatureValid(credential.getAssertionAsElement(), cert.getPublicKey());
} catch (ProcessingException e) {
logger.processingError(e);
}
if (!sigValid) {
throw logger.authSAMLInvalidSignatureError();
}
if (AssertionUtil.hasExpired(assertion)) {
throw logger.authSAMLAssertionExpiredError();
}
}
}