WSO2 Send Recovery Notification - authentication

In our current WSO2 setup, after a user performs a self creation, we place his account into a locked state, and send a confirmation email to the address specified during creation. This email has a link which allows the user to verify his account.
For development purposes, we are attempting to get the workflow down using the UserInformationRecoveryService wsdl in SOAP UI. The service which we seem to want is called sendRecoveryNotification. Here is the signature of this service:
sendRecoveryNotification(String username, String key, String notificationType)
The username parameter is simply the username of the WSO2 user in question, which we have. For the notificationType we have been using email, which presumably would trigger an email to be sent to the user. The problem is with the key parameter. It is not clear what value should be used as key, and all our guesses always lead to this error response:
18001 invalid confirmation code for user : tbiegeleisen#abc.com#tenant.com
We also noticed that several other services also expect a key, and it is not clear how to get this value.
Can someone shed light on the workflow for user recovery in WSO2? It seems to be a Catch-22 with regard of requiring a token in order to generate a new token to be sent to a user.

The WSO2 documentation clearly spells out the workflow for recovery with notification. The key which needs to be used is the return value from a call to the verifyUser() SOAP web service. This service itself expects a Captcha which normally would be sent from the UI. Here is a code snippet showing how a recovery notification can be sent:
String cookies = client.login("admin#tenant.com#tenant.com", "admin");
UserInformationRecoveryUtil userInfoutil = new UserInformationRecoveryUtil(webserviceUrl, cookies);
CaptchaInfoBean captchaInfo = new CaptchaInfoBean();
captchaInfo.setImagePath(captchaPath);
captchaInfo.setSecretKey(captchaKey);
captchaInfo.setUserAnswer(captcha);
String username = emailId + "#" + tenantDomain;
String key = userInfoutil.verifyUser(username, captchaInfo);
// now pass the key based on the Captcha along with the type of recovery action
userInfoutil.sendRecoveryNotification(username, key, "accountUnLock");

Related

How to pass UserName & Password in IBMMQ Client Message using .NET or C++ Program

I am writing a .NET Console application, our goal is keep a message on the queue and read the message. the message header should contain User Name & Password. I try to pass the Message with below code it is not working.
hashTable.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_CLIENT);
hashTable.Add(MQC.HOST_NAME_PROPERTY, strServerName);
hashTable.Add(MQC.CHANNEL_PROPERTY, strChannelName);
hashTable.Add(MQC.PORT_PROPERTY, 1414);
hashTable.Add(MQC.USER_ID_PROPERTY, "XXXXXX");
hashTable.Add(MQC.PASSWORD_PROPERTY, "XXXXXX");
hashTable.Add(MQC.USE_MQCSP_AUTHENTICATION_PROPERTY, true);
queueManager = new MQQueueManager(strQueueManagerName,hashTable);
queue = queueManager.AccessQueue(requestQueue, MQC.MQOO_OUTPUT + MQC.MQOO_FAIL_IF_QUIESCING);
requestMessage = new MQMessage();
requestMessage.WriteString(StrAPICMessage);
requestMessage.Format = MQC.MQFMT_STRING;
requestMessage.MessageType = MQC.MQMT_REQUEST;
requestMessage.Report = MQC.MQRO_COPY_MSG_ID_TO_CORREL_ID;
requestMessage.ReplyToQueueName = responseQueue;
requestMessage.ReplyToQueueManagerName = strQueueManagerName;
queuePutMessageOptions = new MQPutMessageOptions();
queue.Put(requestMessage, queuePutMessageOptions);
In the Message Descriptor it is taking the default value mentioned MQ Server. it is not takeing my UserName "XXXXX"
I have tried using the CSICS Bridge header also unable to send the message with my application Service account + Password.
help me on this scenario.
See "MQCSP authentication mode" here: https://www.ibm.com/docs/en/ibm-mq/latest?topic=authentication-connection-java-client
It says:
In this mode, the client-side user ID is sent as well as the user ID and password to be authenticated, so you are able to use ADOPTCTX(NO). The user ID and password are available to a server-connection security exit in the MQCSP structure that is provided in the MQCXP structure.
"client-side user ID" means the UserId that the application is running under. Therefore, if you are authenticating with a different UserId than the one that the application is running under.
Therefore, you (or your MQAdmin) will need to change ADOPTCTX to YES.
Your program works fine for me, when I fill in the correct values for my qmgr connection.
Except for one change I made: instead of TRANSPORT_MQSERIES_CLIENT I used TRANSPORT_MQSERIES_MANAGED. That keeps everything in the managed .Net space.
Without that change, I was actually getting MQRC_UNSUPPORTED_FUNCTION during the connection which typically means either some kind of mismatch between versions of interfaces, or it couldn't find the C dll that underpins the unmanaged environment. And I wasn't going to take time to dig into that further.
Running amqsbcg against the output queue, I see
UserIdentifier : 'mqguest '
which is the id I had set in the USER_ID_PROPERTY.

Removing a user from backend created by IdentityServer4

I am debugging confirmation email flow when signing up a new User in Asp.Net Core web application with Identity Server 4.
Since I had already signed up with my actual email, to reuse it, I modified the UserName and Email in AspNetUsers table using SQL Update to some random value.
Now when I am signing up with the original email again. I am getting a duplicate user error
result = await _userManager.CreateAsync(user, model.Password);
I have already:
Cleared browser cache.
Closed local IIS Express
Restarted Visual Studio.
Used_userManager.DeleteAsync() after updating the UserName and Email back to original values but this gives an Microsoft.AspNetCore.Identity.IdentityError with description Optimistic concurrency failure, object has been modified.
On running this query on Sql Server
select * from INFORMATION_SCHEMA.COLUMNS where COLUMN_NAME in ( 'UserName' , 'Email')
I get the following:
I know that this is not a good practice to mess with backend, but this is development environment and I could continue my work with another email.
I would request readers to help in understanding how the User could be safely scorched to be able to reuse the email.
Appreciate your time
I agree with Kyle's comment and to further speed up your debug process you should note that if you use gmail to do this you can debug this process using one email.
from google/gmails perspective myaccount#gmail.com == my.acount#gmail.com == m.y.a.c.c.ount#gmail.com etc etc just try it out, google disregards all period characters in the email. you can enumerate/exhaust ~2^8 emails (in this example) if you just enumerate through the local-part of the e-mail address. but from your applications side, myaccount#gmail.com is not the same as my.account#gmail.com, ie they are different user accounts. Basically you can use one email to test out this feature of yours without having to delete the user.
Here is how I did it and finally got passed the pesky "concurrency failure" error message... This works in ASP.NET CORE 2.2
Obtain the user object through the FindByName method first.
Remove the user from their assigned Role (in this case I hard coded "Admin" because that is the role I'm interested in but fill in your own), then delete the user.
//Delete user.
//Obtain the user object through the FindByName method first.
//Remove the user from their assigned Role, then delete the user.
var userManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
ApplicationUser delAppUser = new ApplicationUser
{
Email = "SomeEmailForindividualAdminUser",
UserName = "SomeUsernameindividualAdminUser"
};
Task <ApplicationUser> taskGetUserAppUser = userManager.FindByNameAsync(delAppUser.UserName);
taskGetUserAppUser.Wait();
Task<IdentityResult> taskRemoveFromRoleAppUser = userManager.RemoveFromRoleAsync(taskGetUserAppUser.Result, "Admin");
taskRemoveFromRoleAppUser.Wait();
Task<IdentityResult> taskDeleteAppUser = userManager.DeleteAsync(taskGetUserAppUser.Result);
taskDeleteAppUser.Wait();

Adding authenticated attributes using MS CryptoApi

I'm struggling adding authenticated attributes (OCSP data) to my message using CryptoApi. I first used CryptoApi's simplified message functions, but now switch to the low-level message functions, thinking that I would be able to control the message structure better. But I am once again stuck. My process is as follows:
Initialize CMSG_SIGNER_ENCODE_INFO and CMSG_SIGNED_ENCODE_INFO structure
I create a CRYPT_ATTRIBUTE for the ocsp date and specifies it in the CMSG_SIGNER_ENCODE_INFO structure
I then call CryptMsgCalculateEncodedLength to get the size
CryptMsgOpenToEncode with CMSG_SIGNED as the message type
CryptMsgUpdate, to insert my content into the message
CryptMsgGetParam with CMSG_CONTENT_PARAM to get the encoded blob
CryptMsgClose, I'm done with the message for now.
I open the message again to get the CMSG_ENCRYPTED_DIGEST, which is sent to a TSA and the result is added as an unaunthenticated attribute using CryptMsgControl.
I'm using this to sign signature tags in Adobe. So when there is no authenticated attributes, I receive three green check from Adobe:
The document has not been modified...
The document is signed by the current user
The signature includes an embedded timestamp (and the timestamp is validate)
But as soon as the authenticated attribute is added the signer's identity is invalidated and the timestamp data in incorrect. The CMSG_COMPUTED_HASH_PARAM when authenticated attributes are added and when not, differs. Should this not be the same? Since the document digest is of the content of the document and not of the authenticated attribute.
Is there another way to add authenticated attributes? I've tried to add it as a signer using CryptMsgControl, but that did not help either...
how about this step on adding the authenticated attributes for signing, example time stamping,
CryptEncodeObject(PKCS_7_ASN_ENCODING, szOID_RSA_signingTime, &curtime, pTime, &szTime);
pTime = (BYTE *)LocalAlloc(GPTR, szTime);
CryptEncodeObject(PKCS_7_ASN_ENCODING, szOID_RSA_signingTime, &curtime, pTime, &szTime);
time_blob.cbData = szTime;
time_blob.pbData = pTime;
attrib[0].pszObjId = szOID_RSA_signingTime;
attrib[0].cValue = 1;
attrib[0].rgValue = &time_blob;
CosignerInfo.cAuthAttr = 1;
CosignerInfo.rgAuthAttr = attrib;
and that Cosigner params is from CMSG_SIGNER_ENCODE_INFO CosignerInfo;

Disqus - How to pass current logged in user?

I am using Disqus API to fetch details of the logged in user. I am not sure how to pass the current logged in user.
I have both api_key(public) and remote_auth and I am using Jquery ajax to send api request over http.
If I do something like this,
https://disqus.com/api/3.0/users/details.json?api_key=[apikey]
It says "You must either provide a user or authenticate the user." Now I have the loggedin users remote_auth.
FYI: This is how I am creating the remote_auth. Example User Id: 3096795, email = "a#a.com", Name="Test". Now when this user logs in to the website, it logs in to Disqus as well. I can see this user in http://disqus.com/api/sso/users/ with id = 3096795.
I have couple of questions:
1) Can I use jquery ajax to send a authenticated user and get user details? Or this can be done only via Server side? (Java/Php)
2) If I pass ?remote_auth=[remote_auth] as a query string, will it work?
3) if yes, remote_auth value has spaces in between HMAC->SHA1(secret_key, message + ' ' + timestamp) so how can I pass it as query string parameter?
4) If no, then how to pass a user to the listActivity.json endpoint? If I am passing the userid, then it returns me some other user and not the user I created.
The below request returns a different user.
https://disqus.com/api/3.0/users/details.json?api_key=[apikey]&user=3096795
How can I ensure the userid I am passing is unique and not already taken by a different disqus account?
Am I missing something?
Your remote_auth is a form of authentication, just like access_token, so you'll want to pass that in your request as remote_auth=<YOUR_PAYLOAD>.
If you pass "user=" that ID would have to be the Disqus user ID, which isn't the same as your remote_auth ID. Your remote_auth is a form of authentication, just like the access_token. However, keep in mind that we don't return as many details for SSO users as authenticated Disqus users. This is because the details are managed by you, the SSO site owner.
To answer your other questions:
You can use the client-side API to get these details, but we recommend the server-side API + caching the results to avoid bumping into API limits.
URL-encode the payload and this will work
Easier using https://github.com/anthavio/disquo
DisqusApplicationKeys keys = new DisqusApplicationKeys("...api_key...", "...secret_key...", "...access_token...");
DisqusApi disqus = new DisqusApi(keys);
//SSO is available only to premium accounts
SsoAuthData ssoauth = new SsoAuthData("custom-12345-id", "Firstname", "Surname");
//SSO User identity is used to create post
disqus.posts().create(ssoauth, keys.getApiSecret(), threadId, "Hello world " + new Date(), null);

Testing WCF with SoapUI

I need your help on one practical issue. I have created a WCF service with basic binding with two operation contact.
1- void StartRegistration - Anonymous member can fill the basic registration form and press submit. All the information will be stored into the database and one link with some random token will be send to user's email address.
2 - void CompleteRegistration - This method validates the token sent into the email address and if token is valid, user account will be activated.
Now I have issue here. Using SoapUI I can call StartRegistration method. Email is sent to destination but I want to pass the token to CompleteRegistration method.
Since it is a WCF service so can not do dependency injection to pass the SoapUI tests :).
Please help.
If I understand your question correctly, you have two WCF methods, one for creating a token and another for confirming it.
What I would do in this case is have the first method, StartRegistration, return the token. Then you could use that token to pass into the CompleteRegistration method quite easily in Soap UI.
Another, quite messy solution, would be to have a groovy script test step in Soap UI that actually connected to the mail account, read the link and parsed the contents.
Edited:
Here is part of the script you'll need. Place it in a groovy step, that will then return the token from your mail.
Note: This code assumes that mail is plain text, not multipart. It also assumes that the mail box only has a single mail. The API for JavaMail is pretty extensive, so if you want to do any magic with it, Google is your friend :) At least, this is somewhere to start.
import javax.mail.*;
import javax.mail.internet.*;
// setup connection
Properties props = new Properties();
def host = "pop3.live.com";
def username = "mymailadress#live.com";
def password = "myPassword";
def provider = "pop3s";
// Connect to the POP3 server
Session session = Session.getDefaultInstance props, null
Store store = session.getStore provider
Folder inbox = null
String content
try
{
store.connect host, username, password
// Open the folder
inbox = store.getFolder 'INBOX'
if (!inbox) {
println 'No INBOX'
System.exit 1
}
inbox.open(Folder.READ_ONLY)
Message[] messages = inbox.getMessages()
content = messages[0].getContent()
//Do some parsing of the content here, to find your token.
//Place the result in content
}
finally
{
inbox.close false
store.close()
}
return content; //return the parsed token