TOTP Problem - Microsoft Authenticator is not matching the code generated on server - multi-factor-authentication

I am getting a not verified using the TOTP method I have found on the following link.
OTP code generation and validation with otp.net
!My! code is below.
The _2FAValue line at the top is embedded into the QR barcode that Microsoft Authenticator attaches too.
The _Check... Function is the server ajax call to the server which implements OTP.Net library exposing TOTP calculation.
MakeTOTPSecret creates an SHA1 version of a Guid which is applied to the User profile and stored in _gTOTPSecret. NB: This IS populated in the places it is used.
I think I must have missed something obvious to get a result, here.
loSetup2FAData._s2FAValue = $#"otpauth://totp/{loUser.UserName}?secret={loUser.MakeTOTPSecret()}&digits=6&issuer={Booking.Library.Classes.Constants._sCompanyName}&period=60&algorithm=SHA1";
[AllowAnonymous]
public JsonResult _CheckTOTPCodeOnServer([FromBody] Booking.Site.Models.Shared.CheckTotpData loCheckTotpData)
{
string lsMessage = "<ul>";
try
{
string lsEmail = this.Request.HttpContext.Session.GetString("Buku_sEmail");
Booking.Data.DB.Extensions.IdentityExtend.User loUser = this._oDbContext.Users.Where(U => U.UserName.ToLower() == lsEmail.ToLower() || U.Email == lsEmail).FirstOrDefault();
if (loUser != null && loUser.Load(this._oDbContext) && loUser._gTOTPSecret != Guid.Empty)
{
OtpNet.Totp loTotp = new Totp(Booking.Library.Classes.Utility.StringToBytes(loUser.MakeTOTPSecret()), 60, OtpHashMode.Sha1, 6);
loTotp.ComputeTotp(DateTime.Now);
long lnTimeStepMatched = 0;
bool lbVerify = loTotp.VerifyTotp(loCheckTotpData._nTotp.ToString("000000"), out lnTimeStepMatched, new VerificationWindow(2, 2));
if (lbVerify)
{
lsMessage += "<li>Successfully validated Totp code</li>";
lsMessage += "<li>Save is now activated</li>";
return this.Json(new { bResult = true, sMessage = lsMessage + "</ul>" });
}
}
}
catch (Exception loException)
{
lsMessage += "<li>" + Booking.Library.Classes.Utility.MakeExceptionMessage(true, loException, "\r\n", "_CheckTOTPCodeOnServer") + "</li>";
}
lsMessage += "<li>Unsuccessfully validated Totp code</li>";
return this.Json(new { bResult = false, sMessage = lsMessage + "</ul>" });
}
public string MakeTOTPSecret()
{
string lsReturn = String.Empty;
try
{
using (SHA1Managed loSha1 = new SHA1Managed())
{
var loHash = loSha1.ComputeHash(Encoding.UTF8.GetBytes(this._gTOTPSecret.ToString()));
var loSb = new StringBuilder(loHash.Length * 2);
foreach (byte b in loHash)
{
loSb.Append(b.ToString("X2"));
}
lsReturn = loSb.ToString();
}
}
catch (Exception loException)
{
Booking.Library.Classes.Utility.MakeExceptionMessage(true, loException, "\r\n", "Identity.MakeSHA1Secret");
}
return lsReturn;
}

Related

Ajax request fails in JBOSS EAP 7.1 in Java EAR application

I've EAR applications which run fine in JBOSS EAP 6.3. When I run this application in EAP 7, then ajax call response is empty after few call. Mainly jsp page calls servlet using ajax. I use common code snippet for AJAX call. I can get response properly first 3/4 times. After that it is not working. The whole thing is working fine in EAP 6.3.
The ajax code snippet is as follows:
try{
objXMLHTTP = new XMLHttpRequest();
}catch(e){
try {
objXMLHTTP = new ActiveXObject("MSXML2.XMLHTTP.3.0");
}
catch(e){
try {
objXMLHTTP = new ActiveXObject("MSXML2.XMLHTTP");
}
catch(e) {
try {
objXMLHTTP = new ActiveXObject("Microsoft.XMLHTTP");
}
catch(e) {
alert("XMLHTTP Not Supported On Your Browser");
return;
}
}
}
}
var urlstr = "" ;
var key = "";
var j = 0;
//dataStore is an array of key/value pair.
for(key in dataStore){
if(j == 0) {
urlstr += key + "=" + dataStore[key];
j = 1;
} else {
urlstr += "&" + key + "=" + dataStore[key];
}
}
var _dateTime = new Date().getTime();
urlstr += "&CALLTIME=" + _dateTime + "-";
var requNumber = "?requNumber=" + _dateTime;
// http request has been changed as Parameterised
var _AsyncRequest = true;
try{
if(_httpMode == "undefined")
_httpMode = "0";
}catch(e){
_httpMode = "0";
}
if((_httpMode != "undefined") && (_httpMode != null) && (_httpMode == "1"))
{
_AsyncRequest = false;
}
if(!document.all)
{
_AsyncRequest = false;
}
if(urlstr.length<=1000) {
objXMLHTTP.open("POST","XMLDHTTPServlet" + requNumber + "&" + urlstr,false);
} else {
objXMLHTTP.open("POST","XMLDHTTPServlet" + requNumber,false);
}
urlstr = URLEncode(urlstr);
objXMLHTTP.setRequestHeader("content-type", "application/x-www-form-urlencoded") ;
//The following is not working after few calls
if(urlstr.length<=1000) {
objXMLHTTP.send("");
} else {
objXMLHTTP.send(urlstr);
}
rtnXML = objXMLHTTP.responseText;
if (objXMLHTTP.statusText == "OK" )
// This condition fails after successive requests
{
//Code
}
Following is in JSP page to call the AJAX. Most importantly, when I put the character **|**, then response in empty and objXMLHTTP.statusText shows Bad Request in EAP 7. But EAP 6, it is working fine.
var objXMLApplet = new xmlHTTPValidator();
objXMLApplet.clearMap();
objXMLApplet.setValue("Package", "panaceaFLweb.getMenuInfo.ReadInfo");
objXMLApplet.setValue("ValidateToken","true");
objXMLApplet.setValue("Method", "chkEODStatus");
objXMLApplet.setValue("BRNCH_CODE",BranCode);
objXMLApplet.setValue("CURR_BUSS_DATE",CBD);
objXMLApplet.setValue("DataTypes","S|S");
objXMLApplet.sendAndReceive();
It is because character | present in URL post request and didn't encode the string which length is less than 1000. Just use
urlstr = URLEncode(urlstr);
before if/else condition of connection open.
Code snippet are as follows:
urlstr = URLEncode(urlstr);
if(urlstr.length<=1000) {
objXMLHTTP.open("POST","XMLDHTTPServlet" + requNumber + "&" + urlstr,false);
} else {
objXMLHTTP.open("POST","XMLDHTTPServlet" + requNumber,false);
}
objXMLHTTP.setRequestHeader("content-type", "application/x-www-form-urlencoded") ;
if(urlstr.length<=1000) {
objXMLHTTP.send("");
} else {
objXMLHTTP.send(urlstr);
}
rtnXML = objXMLHTTP.responseText;
And URLEncode function definition are as follows:
function URLEncode(urlstr ){
var SAFECHARS = "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "-_.!~*'()=?&";
var HEX = "0123456789ABCDEF";
var plaintext = urlstr;
var encoded = "";
for (var i = 0; i < plaintext.length; i++ ) {
var ch = plaintext.charAt(i);
if (ch == " "){
encoded += "+";
}else if (SAFECHARS.indexOf(ch) != -1) {
encoded += ch;
}else {
var charCode = ch.charCodeAt(0);
if (charCode > 255) {
encoded += "+";
}else {
encoded += "%";
encoded += HEX.charAt((charCode >> 4) & 0xF);
encoded += HEX.charAt(charCode & 0xF);
}
}
}
return encoded;
}

pass string to server side with ajax in tapestry

<t:if test="needsSetName">
<label for="userfunction">${message:setname}</label>
<t:textfield
t:mixins="zoneUpdater"
tabindex="-1"
autofocus="false"
ZoneUpdater.clientEvent="keyup"
ZoneUpdater.event="valueChangedSetName"
ZoneUpdater.zone="transferZone"
ZoneUpdater.timeout="3000"
t:id="setName"
value="setName"/>
</t:if>
#OnEvent(value = "valueChangedSetName")
protected void onValueChangedSetName(#RequestParameter(value = "param", allowBlank = true) String setName)
{
TransferOrder to = baskets.getTransferOrder();
this.setName = setName;
to.setComment("Rename from " + this.setName + " to " + setName);
nextSetName = setName;
zoneHubService.updatePendingTransfer();
zoneHubService.addCallback(new JavaScriptCallback()
{
#Override
public void run(JavaScriptSupport javascriptSupport)
{
javascriptSupport.addScript(
String.format("var thing=jQuery('#%s'); thing.focus();thing[0].setSelectionRange(10000, 10000);",
setNameField.getClientId()));
}
});
}
So my problem is, when i type some text into the textfield, it removes symbols like #,&,.. and everything else that comes after these symbols
When i use +, it turns into space.
The string that i get from the server in my method is already "edited".
I'm new to tapestry and ajax and i don't know how to solve this problem.
What do i have to do, so that i get the string back from the server without the server removing these symbols?
I solved my problem.
In my zone-updater.js I had to use encodeURIComponent on my string.
For anyone who has the same problem here is the link to the zoneUpdater.js code.
http://tinybits.blogspot.com/2010/03/new-and-better-zoneupdater.html
The link I, that I found to solve the bug is down.
define([ "jquery", "t5/core/zone" ], function($, zoneManager) {
return function(elementId, clientEvent, listenerURI, zoneElementId, timeout) {
var $element = $("#" + elementId);
var mytimeout;
if (clientEvent) {
$element.on(clientEvent, updateZone);
}
function updateZone() {
jQuery($element).removeClass('saved');
if (mytimeout != null) {
clearTimeout(mytimeout);
}
mytimeout = setTimeout(function() {
var listenerURIWithValue = listenerURI;
if ($element.val()) {
listenerURIWithValue = appendQueryStringParameter(
listenerURIWithValue, 'param', $element.val());
listenerURIWithValue = appendQueryStringParameter(
listenerURIWithValue, 'element', elementId);
}
zoneManager.deferredZoneUpdate(zoneElementId,
listenerURIWithValue);
}, timeout);
}
}
function appendQueryStringParameter(url, name, value) {
if (url.indexOf('?') < 0) {
url += '?'
} else {
url += '&';
}
value = encodeURIComponent(value);
url += name + '=' + value;
return url;
}
});

Catch incoming emails and send them to a web service (rather than just to a mail server)

I would like to catch incoming emails and send them a web service (rather than just to a mail server).
--
After some searching I found a way of getting new emails via polling - see below: This may be of some help to others. Is there a way to receive messages by SMTP? Perhaps by ISAPI ???
using Limilabs.Mail;
using Limilabs.Client.IMAP;
public ActionResult checkIMAPmail()
{
string rval = "not a sausage";
using (Imap imap = new Imap())
{
imap.Connect(<mail server>);
imap.Login(<username>, <password>);
imap.SelectInbox();
List<long> uids = imap.Search(Flag.Unseen);
foreach (long uid in uids)
{
byte[] ourBytes = imap.GetMessageByUID(uid);
IMail email = new MailBuilder().CreateFromEml(ourBytes);
rval = email.Subject + " [" + email.From + "][" + email.Text + "]";
}
imap.Close();
}
return Content(rval, "text/html");
}
See also http://stackoverflow.com/questions/670183/accessing-imap-in-c-sharp
for other IMAP packages, although note the change to using byte[], above.
Given that Limilabs.Mail is a paid service, I finally used MailKit:
using MailKit;
public int checkIMAPmail()
{
int numEmails = 0;
try {
using (var client = new MailKit.Net.Imap.ImapClient())
{
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
client.Connect(ourSmtpClient);
// disable the XOAUTH2 authentication mechanism.
client.AuthenticationMechanisms.Remove("XOAUTH2");
client.Authenticate(ourSmtpAdminUser, ourSmtpAdminUserPwd);
// The Inbox folder is always available on all IMAP servers...
var inboxFolder = client.Inbox;
var savedFolder = client.GetFolder("saved");
inboxFolder.Open(FolderAccess.ReadWrite);
for (int ii = 0; ii < inboxFolder.Count; ii++)
{
var query = MailKit.Search.SearchQuery.NotSeen;
foreach (var uid in inboxFolder.Search(query))
{
var thisMsg = inboxFolder.GetMessage(uid);
string thisDate = notNullString(thisMsg.Date);
string thisSubject = notNullString( thisMsg.Subject);
string thisBody = notNullString(thisMsg.GetTextBody(0)); // plain text
string thisFromName = "";
string thisFromEmail = "";
if ( thisMsg.From != null)
{
// just get the first
foreach( var mb in thisMsg.From.Mailboxes)
{
thisFromName = notNullString( mb.Name);
thisFromEmail = notNullString( mb.Address);
break;
}
}
numEmails += 1;
// move email to saved
inboxFolder.MoveTo(uid, savedFolder);
}
}
client.Disconnect(true);
}
}
catch (Exception exc)
{
log2file("checkIMAPmail Error: " + exc.ToString());
}
return numEmails;
}

Process gets stuck in oSession.Logoff()

Pstcreation works properly with outlook installed.
Now, I am trying to create a pst file with standalone version of MAPI . But my process is stuck in oSession.LogOff(). Further if a comment that oSession.LogOff() line and subsequently call the CreatePstWithRedemption function to create an other pst, the process gets stuck in oSession.LogonPstStore
private bool CreatePstWithRedemption(EmailJTableArgs objJTablArgs, EmailFilterArgs objFilterArgs,
EmailExportRequestParams emailExportRequestParams)
{
RDOSession oSession = null;
IRDOStore store = null;
RDOFolder fFOlder = null;
RDOFolder childFolder = null;
IRDOItems folderItems = null;
var pstCreationStatus = false;
try
{
oSession = new RDOSession();
store = oSession.LogonPstStore(_fileName, 1, "PST");
var folderName = Path.GetFileNameWithoutExtension(_fileName);
if (store != null)
{
fFOlder = store.IPMRootFolder;
foreach (RDOFolder folder in fFOlder.Folders)
{
folder.Delete();
}
childFolder = fFOlder.Folders.Add(folderName, Type.Missing);
folderItems = childFolder.Items;
var resultOfGetEmails = new ResultGetEmails();
resultOfGetEmails.TotalCount = -1;
do
{
var journalEmails = GetEmailList(objFilterArgs, objJTablArgs, emailExportRequestParams,
resultOfGetEmails);
for (var i = 0; i < journalEmails.Count; i++)
{
IRDOMail mail = null;
try
{
mail = folderItems.Add(rdoItemType.olMailItem);
// populate mail fields
mail.Sent = true;
mail.Save();
}
finally
{
if (mail != null)
Marshal.ReleaseComObject(mail);
}
}
resultOfGetEmails.TotalCount -= BatchSize;
objJTablArgs.PageStartIndex += BatchSize;
} while (resultOfGetEmails.TotalCount > 0);
pstCreationStatus = true;
}
}
finally
{
// Do cleanup
if (oSession != null && oSession.LoggedOn)
{
try
{
oSession.Logoff();
Marshal.ReleaseComObject(oSession);
}
catch
{
}
}
}
return pstCreationStatus;
}
Note: The same thing works well when run in an environment where outlook is installed.

How do I retrieve global contacts with Exchange Web Services (EWS)?

I am using EWS and wish to obtain the global address list from exchange for the company. I know how to retrieve the personal contact list.
All the samples in the API documentation deal with updating user information but not specifically how to retrieve them.
I've even tried the following to list the folders but it doesn't yeild the correct results.
private static void ListFolder(ExchangeService svc, FolderId parent, int depth) {
string s;
foreach (var v in svc.FindFolders(parent, new FolderView(int.MaxValue))) {
Folder f = v as Folder;
if (f != null) {
s = String.Format("[{0}]", f.DisplayName);
Console.WriteLine(s.PadLeft(s.Length + (depth * 2)));
ListFolder(svc, f.Id, depth + 1);
try {
foreach (Item i in f.FindItems(new ItemView(20))) {
Console.WriteLine(
i.Subject.PadLeft(i.Subject.Length + ((depth + 1) * 2)));
}
} catch (Exception) {
}
}
}
}
While the question has already been raised (How to get contact list from Exchange Server?) this question deals specifically with using EWS to get the global address list while this question asks for advice on a general level.
you may got ItemType objects in a specifiedfolder with the code snippet below
and then cast ItemType objects to ContactItemType (for contact objects) ....
/// <summary>
/// gets list of ItemType objects with maxreturncriteria specicification
/// </summary>
/// <param name="esb">ExchangeServiceBinding object</param>
/// <param name="folder">FolderIdType to get items inside</param>
/// <param name="maxEntriesReturned">the max count of items to return</param>
public static List<ItemType> FindItems(ExchangeServiceBinding esb, FolderIdType folder, int maxEntriesReturned)
{
List<ItemType> returnItems = new List<ItemType>();
// Form the FindItem request
FindItemType request = new FindItemType();
request.Traversal = ItemQueryTraversalType.Shallow;
request.ItemShape = new ItemResponseShapeType();
request.ItemShape.BaseShape = DefaultShapeNamesType.AllProperties;
request.ParentFolderIds = new FolderIdType[] { folder };
IndexedPageViewType indexedPageView = new IndexedPageViewType();
indexedPageView.BasePoint = IndexBasePointType.Beginning;
indexedPageView.Offset = 0;
indexedPageView.MaxEntriesReturned = 100;
indexedPageView.MaxEntriesReturnedSpecified = true;
request.Item = indexedPageView;
FindItemResponseType response = esb.FindItem(request);
foreach (FindItemResponseMessageType firmtMessage in response.ResponseMessages.Items)
{
if (firmtMessage.ResponseClass == ResponseClassType.Success)
{
if (firmtMessage.RootFolder.TotalItemsInView > 0)
foreach (ItemType item in ((ArrayOfRealItemsType)firmtMessage.RootFolder.Item).Items)
returnItems.Add(item);
//Console.WriteLine(item.GetType().Name + ": " + item.Subject + ", " + item.DateTimeReceived.Date.ToString("dd/MM/yyyy"));
}
else
{
//handle error log here
}
}
return returnItems;
}
I just did a similiar thing. However, I was unable to get the list of contacts via Exchange since that only gets users that have mailboxes, and not necessarily all users or groups. I eventually ended up getting all the users via AD
here is code to get all the contacts in AD. All you need is the folderID of the global address list which can be gotten from using the ADSI.msc tool on your AD server and browsing to the Global address list folder, look at properties and grab the value of the "purported search". In my system the searchPath for the global address list is"(&(objectClass=user)(objectCategory=person)(mailNickname=)(msExchHomeServerName=))"
public List<ListItem> SearchAD(string keyword, XmlDocument valueXml)
{
List<ListItem> ewsItems = new List<ListItem>();
using (DirectoryEntry ad = Utils.GetNewDirectoryEntry("LDAP://yourdomain.com"))
{
Trace.Info("searcherをつくる");
using (DirectorySearcher searcher = new DirectorySearcher(ad))
{
if (this.EnableSizeLimit)
{
searcher.SizeLimit = GetMaxResultCount();
if (Utils.maxResultsCount > 1000)
{
searcher.PageSize = 100;
}
}
else
{
searcher.SizeLimit = 1000;
searcher.PageSize = 10;
}
string sisya = Utils.DecodeXml(valueXml.SelectSingleNode("Folder/SearchPath").InnerText); //this is the folder to grab your contacts from. In your case Global Address list
//Container
if(String.IsNullOrEmpty(sisya))
{
return null;
}
keyword = Utils.EncodeLdap(keyword);
string text = Utils.DecodeXml(valueXml.SelectSingleNode("Folder/Text").InnerText);
searcher.Filter = this.CreateFilter(keyword, sisya);
searcher.Sort = new SortOption("DisplayName", System.DirectoryServices.SortDirection.Ascending);
//一つのPropertyをロードすると、全Propertyを取らないようになる
searcher.PropertiesToLoad.Add("SAMAccountName"); //どのPropertyでもいい。
SearchResultCollection searchResults = searcher.FindAll();
foreach (SearchResult searchResult in searchResults)
{
//ListItem contact = null;
using (DirectoryEntry userEntry = searchResult.GetDirectoryEntry())
{
try
{
string schemaClassName = userEntry.SchemaClassName;
switch (schemaClassName)
{
case "user":
case "contact":
string fname = userEntry.Properties["GivenName"].Value == null ? "" : userEntry.Properties["GivenName"].Value.ToString();
string lname = userEntry.Properties["sn"].Value == null ? "" : userEntry.Properties["sn"].Value.ToString();
string dname = userEntry.Properties["DisplayName"][0] == null ? lname + " " + fname : userEntry.Properties["DisplayName"][0].ToString();
//No Mail address
if ((userEntry.Properties["mail"] != null) && (userEntry.Properties["mail"].Count > 0))
{
string sAMAccountName = "";
if(userEntry.Properties["SAMAccountName"].Value != null){
sAMAccountName = userEntry.Properties["SAMAccountName"].Value.ToString();
}
else{
sAMAccountName = userEntry.Properties["cn"].Value.ToString();
}
string contactXml = Utils.ListViewXml(sAMAccountName, UserType.User, Utils.UserXml(fname, lname, userEntry.Properties["mail"].Value.ToString(), dname, null), ServerType.Ad);
ewsItems.Add(new ListItem(dname + "<" + userEntry.Properties["mail"].Value.ToString() + ">", contactXml));
}
else
{
ListItem contact = new ListItem(dname, null);
contact.Enabled = false;
ewsItems.Add(contact);
Trace.Info("追加できないユーザ: " + searchResult.Path);
}
break;
case "group":
ewsItems.Add(new ListItem(userEntry.Properties["DisplayName"].Value.ToString(), Utils.ListViewXml(userEntry.Properties["SAMAccountName"].Value.ToString(), UserType.Group, null, ServerType.Ad)));
break;
default:
userEntry.Properties["SAMAccountName"].Value.ToString());
ewsItems.Add(new ListItem(userEntry.Properties["name"].Value.ToString(), Utils.ListViewXml(userEntry.Properties["SAMAccountName"].Value.ToString(), UserType.Group, null, ServerType.Ad)));
break;
}
}
catch (Exception ex)
{
Trace.Error("User data取得失敗", ex);
}
}
}
searchResults.Dispose();
}
}
return ewsItems;
}

Resources