I'm looking to secure an API based on a shared key and a given username and datetime. The API gives access to trusted third parties and does not require the input from a user in order to access their account (i.e. no OAuth user interaction flow). The third party does not know, nor should require, the user's password.
/// <summary>
/// Generate a Time/String based Hash from the given DateTimeStamp, Authentication Details
/// and (Pre-Shared) API Key.
/// </summary>
/// <param name="datetimeStamp">The DateTimeStamp that is to be used to generate the Hash</param>
/// <param name="userName">The UserName that is to be used to generate the Hash</param>
/// <returns>A string based Hash generated from the DateTimeStamp, Username and
/// Pre-Agreed API Hash Key</returns>
public string GenerateHash(DateTimeOffset dateTimeStamp, string userName)
{
string hash = string.Empty;
DateTimeOffset DateStamp = dateTimeStamp.ToUniversalTime();
string input = string.Format("{0}{1}{2}", DateStamp, userName, PreSharedKey);
var sha1 = System.Security.Cryptography.SHA1.Create();
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
byte[] hashArray = sha1.ComputeHash(inputBytes);
var hashOutput = new StringBuilder();
for (int i = 0; i < hashArray.Length; i++)
hash += hashArray[i].ToString("X2");
return hash;
}
A POST is made to an authentication API like so:
{
Hash : "9B970DD40DB803EDB301C5B1CC23DF7B2C5B5FF5",
DateTimeStamp : "yyyyMMddHHmmss",
UserName : "admin"
}
The Hash is made up of the following: SHA1(datetime + username + presharedkey).
An authentication token is then generated and returned to the third party (session token that has an expiry date).
Are there any obvious problems with such an approach? Is there a better way to do such authentication when the third party is semi-trusted, and the user shouldn't be required to authorise access to their account?