-
-
Save barryokane/2718191 to your computer and use it in GitHub Desktop.
protected void Page_Load(object sender, EventArgs e) | |
{ | |
string url = GetSsoUrl(ConfigurationManager.AppSettings["FreshDesk.BaseUrl"], //including trailing slash | |
ConfigurationManager.AppSettings["FreshDesk.Secert"], user.UserName, user.Email); | |
Response.Redirect(url); | |
} | |
string GetSsoUrl(string baseUrl, string secert, string name, string email) | |
{ | |
return String.Format("{0}login/sso/?name={1}&email={2}&hash={3}", baseUrl, Server.UrlEncode(name), | |
Server.UrlEncode(email), GetHash(secert, name, email)); | |
} | |
static string GetHash(string secert, string name, string email) | |
{ | |
string input = name + email + secert; | |
MD5 md5 = System.Security.Cryptography.MD5.Create(); | |
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input); | |
byte[] hash = md5.ComputeHash(inputBytes); | |
StringBuilder sb = new StringBuilder(); | |
foreach (byte b in hash) | |
{ | |
string hexValue = b.ToString("X").ToLower(); // Lowercase for compatibility on case-sensitive systems | |
sb.Append((hexValue.Length == 1 ? "0" : "") + hexValue); | |
} | |
return sb.ToString(); | |
} |
Hi Barryokane,
i think this is what i am looking for. I have logged in www.abc.com. and by clicking on a link say "generate ticket" from abc website i want to get log-in in freshdesk portal automatically with help of enabling simple SSO.
but in freshdesk support portal in SSO portion there are 2 textboxes. i dont know what url should i write in those text boxes.
1.) Remote login URL 2.)Remote logout URL
How do I set remote login url dynamically through code....for example if its abc.com then abc.support.com
I believe GetHash needs to be updated for the recent changes:
hash value:
"An HMAC-MD5 encryption of Name, Secret key, Email and Timestamp done using the shared secret key."
https://support.freshdesk.com/support/solutions/articles/31166
shouldn't it be string input = name + secretKey + email + timems
Seconded @parlesz, this example code needs update. We've just received an email giving us 28 hours to update our implementation before cutoff (it came in at midnight, wasting a third of our time), and the example code doesn't work. The documentation states:
The UTC timestamp of when the user attempts to log in remotely in seconds since epoch.
Which epoch? Unix? .NET? Cocoa? Excel? Wiki lists 16 different notable epochs. Time for trial-and-error...
Some other comments on the code.
You are using the "X" as a format string for ToString() and then you are calling ToLower() when you could have just used "x" to get the lower-case hexadecimal value.
You are also then creating a leading zero in the loop, when you could have just used a format string "x2" (hexadecimal padded with leading zeroes to a minimum length of 2).
Here is some updated code (also adding the new hash and URL requirements):
string GetSsoUrl(string baseUrl, string secret, string name, string email)
{
var timems = (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds.ToString();
return String.Format("{0}login/sso?name={1}&email={2}×tamp={3}&hash={4}",
baseUrl,
Server.UrlEncode(name),
Server.UrlEncode(email),
timems,
GetHash(secret, name, email, timems));
}
private static string GetHash(string secret, string name, string email, string timems)
{
var input = name + secret + email + timems;
var keybytes = Encoding.Default.GetBytes(secret);
var inputBytes = Encoding.Default.GetBytes(input);
var crypto = new HMACMD5(keybytes);
var hash = crypto.ComputeHash(inputBytes);
return hash.Select(b => b.ToString("x2"))
.Aggregate(new StringBuilder(),
(current, next) => current.Append(next),
current => current.ToString());
}
@42degrees a small bug in your code. you forgot to add timestamp in the string interpolation parameters for generating the url.
@barryokane can you please update the gist to reflect the new code ? (my fork with the fixed code https://gist.github.com/darkpssngr/726162ed0bd67ffdd616370c65a17e68 )
static string GetSsoUrl(string baseUrl, string secret, string name, string email) {
var timems = (DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds.ToString();
return String.Format("{0}/login/sso?name={1}&email={2}×tamp={3}&hash={4}",
baseUrl, Server.UrlEncode(name), Server.UrlEncode(email), timems, GetHash(secret, name, email, timems));
}
private static string GetHash(string secret, string name, string email, string timems) {
var input = name + secret + email + timems;
var keybytes = Encoding.Default.GetBytes(secret);
var inputBytes = Encoding.Default.GetBytes(input);
var crypto = new HMACMD5(keybytes);
var hash = crypto.ComputeHash(inputBytes);
return hash.Select(b => b.ToString("x2"))
.Aggregate(new StringBuilder(),
(current, next) => current.Append(next),
current => current.ToString());
}
I've dropped Freshdesk an email to see how we can test etc. This all seems very rushed, so my guess is they are plugging a security hole, but right now we need a test rig to know if our implementations will work once they flick the Big Red Switch!
If we have a test rig, we can just see what works. Really appreciate the comments above, hopefully one of them is the solution.
Thanks @darkpssngr, fixed.
Well, they gave us a test environment by flicking the Big Red Switch and letting us test in a live environment whilst our users couldn't login! Nice.
I'm now up and running, borrowing code from above, but very slightly different. Just in case it helps anyone, but the harder work was done by those people above, not me!
I have timestamp in the return url, not tamp.
const string key = "XXXXXXXXXXXXXXXXXXXXXXX";
const string pathTemplate = "https://support.XXXX.com/login/sso?name={0}&email={1}×tamp={2}&hash={3}";
string timems = (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds.ToString();
var hash = GetHash(key, alias, tbEmail.Text, timems);
var path = String.Format(pathTemplate, Server.UrlEncode(alias), Server.UrlEncode(tbEmail.Text), timems, hash);
Response.Redirect(path);
Same GetHash as above:
private static string GetHash(string secret, string name, string email, string timems)
{
var input = name + secret + email + timems;
var keybytes = Encoding.Default.GetBytes(secret);
var inputBytes = Encoding.Default.GetBytes(input);
var crypto = new HMACMD5(keybytes);
var hash = crypto.ComputeHash(inputBytes);
return hash.Select(b => b.ToString("x2"))
.Aggregate(new StringBuilder(),
(current, next) => current.Append(next),
current => current.ToString());
}
I had some Encoding trouble with European Culture and Special Characters.
Here is a "Global" working version of @GrahamEHughes Code.
There are two Changes:
- Usage of Encoding.UTF8 instead of Encoding.Default in GetHash
private static string GetHash(string secret, string name, string email, string timems)
{
var input = name + secret + email + timems;
var keybytes = Encoding.UTF8.GetBytes(secret);
var inputBytes = Encoding.UTF8.GetBytes(input);
var crypto = new HMACMD5(keybytes);
var hash = crypto.ComputeHash(inputBytes);
return hash.Select(b => b.ToString("x2"))
.Aggregate(new StringBuilder(),
(current, next) => current.Append(next),
current => current.ToString());
}
- Change of datetime Calculation:
string timems = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
Here is an updated version with the latest requirements => https://gist.github.com/kellyelton/8776309