static void Main(string[] args) { var host = new WebServiceHost2(typeof(CustomerDataService), true, new Uri("http://localhost:8090/CustomerOData")); var credential = new HawkCredential { Id = "id", Key = "werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn", Algorithm = "hmacsha256", User = "******" }; Func<string, HawkCredential> credentials = (id) => credential; host.Interceptors.Add(new HawkRequestInterceptor( credentials, false, (message) => !message.Properties.Via.AbsoluteUri.EndsWith("$metadata"))); host.Open(); foreach (ServiceEndpoint endpoint in host.Description.Endpoints) { Console.WriteLine("Listening at " + endpoint.Address.Uri.AbsoluteUri); } Thread.Sleep(1000); MakeCall(credential); Console.WriteLine("Press a key to exit"); Console.ReadLine(); }
/// <summary> /// Adds the Hawk Authorization header to a HttpWebRequest instance /// </summary> /// <param name="request">Request instance</param> /// <param name="credential">Hawk credentials</param> /// <param name="ext">Optional extension</param> /// <param name="ts">Timestamp</param> /// <param name="nonce">Random nonce</param> /// <param name="payloadHash">Request payload hash</param> public static void SignRequest(this HttpWebRequest request, HawkCredential credential, string ext, DateTime? ts, string nonce, string payloadHash) { #if NET45 var host = (request.Host != null) ? request.Host : request.RequestUri.Host + ((request.RequestUri.Port != 80) ? ":" + request.RequestUri.Port : ""); #else var host = request.RequestUri.Host + ((request.RequestUri.Port != 80) ? ":" + request.RequestUri.Port : ""); #endif var hawk = Hawk.GetAuthorizationHeader(host, request.Method, request.RequestUri, credential, ext, ts, nonce, payloadHash); request.Headers.Add("Authorization", "Hawk " + hawk); }
static void MakeCall(HawkCredential credential) { var requestUri = new Uri("http://localhost:8090/CustomerOData/Customers"); var request = (HttpWebRequest)WebRequest.Create(requestUri); var hawk = Hawk.GetAuthorizationHeader("localhost:8090", "GET", requestUri, credential); request.Headers.Add("Authorization", "Hawk " + hawk); var response = (HttpWebResponse)request.GetResponse(); if (response.StatusCode == HttpStatusCode.OK) { using (var sr = new StreamReader(response.GetResponseStream())) { var content = sr.ReadToEnd(); Console.WriteLine("Received " + content); } } else { Console.WriteLine("Http Status code " + response.StatusCode); } response.Close(); }
static void Main(string[] args) { using (WebApp.Start<Startup>(new StartOptions { Port = 5000 })) { Console.WriteLine("Press Enter to quit."); var credentials = new HawkCredential { Id = "dh37fgj492je", Key = "werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn", Algorithm = "sha256", User = "******" }; var request = (HttpWebRequest)HttpWebRequest.Create("http://localhost:5000/api/HelloWorld"); request.SignRequest(credentials); request.Method = "GET"; using (var response = (HttpWebResponse)request.GetResponse()) { using(var sr = new StreamReader(response.GetResponseStream())) { var content = sr.ReadToEnd(); Console.WriteLine("Call made. Status Code " + response.StatusCode + ". Response " + content); } } Console.ReadKey(); } }
/// <summary> /// Adds the Hawk Authorization header to a HttpWebRequest instance /// </summary> /// <param name="request">Request instance</param> /// <param name="credential">Hawk credentials</param> /// <param name="ext">Optional extension</param> /// <param name="ts">Timestamp</param> /// <param name="nonce">Random nonce</param> /// <param name="payloadHash">Request payload hash</param> public static void SignRequest(this HttpWebRequest request, HawkCredential credential, string ext, DateTime?ts, string nonce, string payloadHash) { #if NET45 var host = (request.Host != null) ? request.Host : request.RequestUri.Host + ((request.RequestUri.Port != 80) ? ":" + request.RequestUri.Port : ""); #else var host = request.RequestUri.Host + ((request.RequestUri.Port != 80) ? ":" + request.RequestUri.Port : ""); #endif var hawk = Hawk.GetAuthorizationHeader(host, request.Method, request.RequestUri, credential, ext, ts, nonce, payloadHash); request.Headers.Add("Authorization", "Hawk " + hawk); }
private static void Main() { const string address = "http://localhost:925/"; var config = new HttpSelfHostConfiguration(address); config.MapHttpAttributeRoutes(); var handler = new HawkMessageHandler( async id => new HawkCredential { Id = id, Key = "abcdefghijkl", Algorithm = "sha256", User = "******" }, 4, true); config.MessageHandlers.Add(handler); using (var server = new HttpSelfHostServer(config)) { server.OpenAsync().Wait(); var client = new HttpClient(); //this will fail var request = new HttpRequestMessage(HttpMethod.Get, address + "test"); var response = client.SendAsync(request).Result; Console.WriteLine(response.StatusCode); Console.WriteLine(); var credential = new HawkCredential { Id = "this-is-my-id", Key = "abcdefghijkl", Algorithm = "sha256", User = "******" }; var clientHandler = new HawkClientMessageHandler(new HttpClientHandler(), credential, ts: DateTime.Now); var client2 = new HttpClient(clientHandler); //this will succeed request = new HttpRequestMessage(HttpMethod.Get, address + "test"); var response2 = client2.SendAsync(request).Result; Console.WriteLine(response2.StatusCode); Console.WriteLine(response2.Content.ReadAsStringAsync().Result); Console.WriteLine(); Console.WriteLine("Sleeping to get outside of the timestamp window. Next request will fail - replay protection."); Thread.Sleep(5000); //this will fail request = new HttpRequestMessage(HttpMethod.Get, address + "test"); var response3 = client2.SendAsync(request).Result; Console.WriteLine(response3.StatusCode); Console.WriteLine(); Console.ReadLine(); } }
static void Main(string[] args) { string baseAddress = "http://localhost:8091/"; //TODO: It looks like there is a bug in the OWIN implementation. The Request URL does not receive // the port number // Start OWIN host using (WebApp.Start<Startup>(url: baseAddress)) { Console.WriteLine("Press Enter to quit."); var credential = new HawkCredential { Id = "dh37fgj492je", Key = "werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn", Algorithm = "sha256", User = "******" }; var clientHandler = new HawkClientMessageHandler(new HttpClientHandler(), credential, "some-app-data"); var client = new HttpClient(clientHandler); var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:8091/Api/HelloWorld"); request.Headers.Host = "localhost:8091"; var response = client.SendAsync(request).Result; string message = response.Content.ReadAsStringAsync().Result; Console.WriteLine("Response {0} - Http Status Code {1}", message, response.StatusCode); var client2 = new HttpClient(); request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:8091/Api/HelloWorldAnonymous"); request.Headers.Host = "localhost:8091"; response = client2.SendAsync(request).Result; message = response.Content.ReadAsStringAsync().Result; Console.WriteLine("Response {0} - Http Status Code {1}", message, response.StatusCode); var client3 = new HttpClient(); var bewit = Hawk.GetBewit("localhost", new Uri("http://localhost:8091/Api/HelloWorld"), credential, 60000); request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:8091/Api/HelloWorld?bewit=" + bewit); request.Headers.Host = "localhost:8091"; response = client3.SendAsync(request).Result; message = response.Content.ReadAsStringAsync().Result; Console.WriteLine("Response {0} - Http Status Code {1}", message, response.StatusCode); Console.WriteLine("Press a key to close the app"); Console.ReadLine(); } }
public HawkCredential Get(string identifier) { var credential = new HawkCredential { Id = "dh37fgj492je", Key = "werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn", Algorithm = "hmacsha256", User = "******" }; return credential; }
/// <summary> /// Gets a new Bewit for Single URI authorization /// </summary> /// <param name="host">Host name</param> /// <param name="uri">Request uri</param> /// <param name="credential">Hawk credential</param> /// <param name="ttlSec">Time to live in seconds for the Bewit</param> /// <param name="ext">Extension attributes</param> /// <returns>A fresh Bewit</returns> public static string GetBewit(string host, Uri uri, HawkCredential credential, int ttlSec, string ext = null) { var now = ConvertToUnixTimestamp(DateTime.Now); var expiration = Math.Floor(now) + ttlSec; var mac = CalculateMac(host, "GET", uri, ext, expiration.ToString(), "", credential, "bewit"); var bewit = Convert.ToBase64String( Encoding.UTF8.GetBytes(credential.Id + '\\' + expiration + '\\' + mac + '\\' + ext)); return(bewit); }
/// <summary> /// Generates a mac hash using the supplied payload and credentials /// </summary> /// <param name="payload"></param> /// <param name="credential"></param> /// <returns></returns> public static string CalculatePayloadHash(string payload, string mediaType, HawkCredential credential) { var normalized = "hawk.1.payload\n" + mediaType + "\n" + payload + "\n"; var algorithm = HashAlgorithm.Create(credential.Algorithm); var encodedMac = Convert.ToBase64String(algorithm .ComputeHash(Encoding.UTF8.GetBytes(normalized))); return(encodedMac); }
/// <summary> /// Authenticates a request message using a bewit /// </summary> /// <param name="bewit"></param> /// <param name="host"></param> /// <param name="uri"></param> /// <param name="credentials"></param> /// <param name="timestampSkewSec"></param> /// <returns></returns> public static IPrincipal AuthenticateBewit(string bewit, string host, Uri uri, Func <string, HawkCredential> credentials, int timestampSkewSec = 60) { if (Trace.CorrelationManager.ActivityId == Guid.Empty) { Trace.CorrelationManager.ActivityId = Guid.NewGuid(); } var bewitParts = ValidateBewit(bewit); HawkCredential credential = null; try { credential = credentials(bewitParts[0]); } catch (Exception ex) { TraceSource.TraceData(TraceEventType.Warning, 0, string.Format("{0} - Unknow user {1} in bewit", Trace.CorrelationManager.ActivityId, bewitParts[0])); throw new SecurityException("Unknown user", ex); } ValidateCredentials(credential); var mac = CalculateMac(uri.Host, "GET", RemoveBewitFromQuery(uri), bewitParts[3], bewitParts[1], "", credential, "bewit"); if (!IsEqual(mac, bewitParts[2])) { TraceSource.TraceData(TraceEventType.Warning, 0, string.Format("{0} - Bad mac in bewit. Received mac {1}. Calculated mac {2}", Trace.CorrelationManager.ActivityId, bewitParts[2], mac)); throw new SecurityException("Bad mac"); } #if NET45 var userClaim = new Claim(ClaimTypes.Name, credential.User); var allClaims = Enumerable.Concat(new Claim[] { userClaim }, (credential.AdditionalClaims != null) ? credential.AdditionalClaims : Enumerable.Empty <Claim>()); var identity = new ClaimsIdentity(allClaims, "Hawk"); var principal = new ClaimsPrincipal(new ClaimsIdentity[] { identity }); #else var identity = new GenericIdentity(credential.User, "Hawk"); var principal = new GenericPrincipal(identity, credential.Roles); #endif return(principal); }
static void MakeCall(HawkCredential credential) { var requestUri = new Uri("http://localhost:8090/CustomerOData/Customers"); var request = (HttpWebRequest)WebRequest.Create(requestUri); var hawk = Hawk.GetAuthorizationHeader("localhost:8090", "GET", requestUri, new HawkCredential { Algorithm = "sha256", Key = "werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn" }); request.Headers.Add("Authorization", "Hawk " + hawk); try { var response = (HttpWebResponse)request.GetResponse(); using (var sr = new StreamReader(response.GetResponseStream())) { var content = sr.ReadToEnd(); Console.WriteLine("Received " + content); } response.Close(); } catch(WebException ex) { var response = ((HttpWebResponse)ex.Response); using (var sr = new StreamReader(response.GetResponseStream())) { var content = sr.ReadToEnd(); Console.WriteLine("Received " + content); } response.Close(); } }
private static void ValidatePayload(HawkCredential credential, string receivedHash, Func <byte[]> requestPayload) { var hmac = System.Security.Cryptography.HMAC.Create(credential.Algorithm); hmac.Key = Encoding.UTF8.GetBytes(credential.Key); var hash = Convert.ToBase64String(hmac.ComputeHash(requestPayload())); if (receivedHash != hash) { TraceSource.TraceData(TraceEventType.Warning, 0, string.Format("{0} - Bad payload hash. Received hash {1}. Calculated hash {2}", Trace.CorrelationManager.ActivityId, receivedHash, hash)); throw new SecurityException("Bad payload hash"); } }
/// <summary> /// Generates a mac hash using the supplied payload and credentials /// </summary> /// <param name="payload"></param> /// <param name="credential"></param> /// <returns></returns> public static string CalculatePayloadHash(string payload, string mediaType, HawkCredential credential) { var normalized = "hawk.1.payload\n" + mediaType + "\n" + payload + "\n"; TraceSource.TraceInformation(string.Format("Normalized Payload String: {0}", normalized)); var algorithm = HashAlgorithm.Create(credential.Algorithm); var encodedMac = Convert.ToBase64String(algorithm .ComputeHash(Encoding.UTF8.GetBytes(normalized))); TraceSource.TraceInformation(string.Format("Calculated payload hash: {0}", encodedMac)); return(encodedMac); }
private static void ValidateCredentials(HawkCredential credential) { if (credential == null) { throw new SecurityException("Missing credentials"); } if (string.IsNullOrEmpty(credential.Algorithm) || string.IsNullOrEmpty(credential.Key)) { throw new SecurityException("Invalid credentials"); } if (!SupportedAlgorithms.Any(a => string.Equals(a, credential.Algorithm, StringComparison.InvariantCultureIgnoreCase))) { throw new SecurityException("Unknown algorithm"); } }
static void MakeCall(HawkCredential credential) { var requestUri = new Uri("http://localhost:1337/hello/john"); var request = (HttpWebRequest)WebRequest.Create(requestUri); var hawk = Hawk.GetAuthorizationHeader("localhost", "GET", requestUri, credential); request.Headers.Add("Authorization", "Hawk " + hawk); var response = (HttpWebResponse)request.GetResponse(); Console.WriteLine("Http Status code " + response.StatusCode); response.Close(); }
/// <summary> /// Adds the Hawk authorization header to request message /// </summary> /// <param name="request">Request instance</param> /// <param name="credential">Hawk credentials</param> /// <param name="ext">Optional extension</param> /// <param name="ts">Timestamp</param> /// <param name="nonce">Random nonce</param> /// <param name="payloadHash">Request payload hash</param> public static void SignRequest(this HttpRequestMessage request, HawkCredential credential, string ext = null, DateTime? ts = null, string nonce = null, string payloadHash = null) { var host = (request.Headers.Host != null) ? request.Headers.Host : request.RequestUri.Host + ((request.RequestUri.Port != 80) ? ":" + request.RequestUri.Port : ""); var hawk = Hawk.GetAuthorizationHeader(host, request.Method.ToString(), request.RequestUri, credential, ext, ts, nonce, payloadHash); request.Headers.Authorization = new AuthenticationHeaderValue("Hawk", hawk); }
/// <summary> /// Adds the Hawk authorization header to request message /// </summary> /// <param name="request">Request instance</param> /// <param name="credential">Hawk credentials</param> /// <param name="ext">Optional extension</param> /// <param name="ts">Timestamp</param> /// <param name="nonce">Random nonce</param> /// <param name="payloadHash">Request payload hash</param> public static void SignRequest(this HttpRequestMessage request, HawkCredential credential, string ext = null, DateTime?ts = null, string nonce = null, string payloadHash = null) { var host = (request.Headers.Host != null) ? request.Headers.Host : request.RequestUri.Host + ((request.RequestUri.Port != 80) ? ":" + request.RequestUri.Port : ""); var hawk = Hawk.GetAuthorizationHeader(host, request.Method.ToString(), request.RequestUri, credential, ext, ts, nonce, payloadHash); request.Headers.Authorization = new AuthenticationHeaderValue("Hawk", hawk); }
public void ShouldSignRequest() { var credential = new HawkCredential { Id = "456", Algorithm = "sha256", Key = "werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn", User = "******" }; var date = DateTime.Now; var ts = (int)Math.Floor(Hawk.ConvertToUnixTimestamp(date)); var mac = Hawk.CalculateMac("example.com:8080", "get", new Uri("http://example.com:8080/resource/4?filter=a"), "hello", ts.ToString(), "k3j4h2", credential, "header"); var authorization = string.Format("id=\"456\", ts=\"{0}\", nonce=\"k3j4h2\", mac=\"{1}\", ext=\"hello\"", ts, mac); var request = (HttpWebRequest)HttpWebRequest.Create("http://example.com:8080/resource/4?filter=a"); request.SignRequest(credential, "hello", date, "k3j4h2", null); Assert.IsNotNull(request.Headers[HttpRequestHeader.Authorization]); Assert.AreEqual(request.Headers[HttpRequestHeader.Authorization], "Hawk " + authorization); }
/// <summary> /// Generates a mac hash using the supplied payload and credentials /// </summary> /// <param name="payload"></param> /// <param name="credential"></param> /// <returns></returns> public static string GeneratePayloadHash(byte[] payload, HawkCredential credential) { var hmac = System.Security.Cryptography.HMAC.Create(credential.Algorithm); hmac.Key = Encoding.UTF8.GetBytes(credential.Key); var hash = Convert.ToBase64String(hmac.ComputeHash(payload)); return hash; }
public HawkCredentials(Uri originServer, HawkCredential hawkCredential) : base("Hawk",originServer) { _hawkCredential = hawkCredential; }
/// <summary> /// Computes a mac following the Hawk rules /// </summary> /// <param name="host">Host header</param> /// <param name="method">Request method</param> /// <param name="uri">Request uri</param> /// <param name="ext">Extesion attribute</param> /// <param name="ts">Timestamp</param> /// <param name="nonce">Nonce</param> /// <param name="credential">Credential</param> /// <param name="payload">Hash of the request payload</param> /// <returns>Generated mac</returns> public static string CalculateMac(string host, string method, Uri uri, string ext, string ts, string nonce, HawkCredential credential, string type, string payloadHash = null) { HMAC hmac = null; if (credential.Algorithm.Equals("sha1", StringComparison.InvariantCultureIgnoreCase)) { hmac = new HMACSHA1(); } else if (credential.Algorithm.Equals("sha256", StringComparison.InvariantCultureIgnoreCase)) { hmac = new HMACSHA256(); } else { throw new Exception("Not supported algorithm"); } hmac.Key = Encoding.UTF8.GetBytes(credential.Key); var sanitizedHost = (host.IndexOf(':') > 0) ? host.Substring(0, host.IndexOf(':')) : host; var normalized = "hawk.1." + type + "\n" + ts + "\n" + nonce + "\n" + method.ToUpper() + "\n" + uri.PathAndQuery + "\n" + sanitizedHost + "\n" + uri.Port.ToString() + "\n" + ((!string.IsNullOrEmpty(payloadHash)) ? payloadHash : "") + "\n" + ((!string.IsNullOrEmpty(ext)) ? ext : "") + "\n"; TraceSource.TraceInformation(string.Format("Normalized String: {0}", normalized)); var messageBytes = Encoding.UTF8.GetBytes(normalized); var mac = hmac.ComputeHash(messageBytes); var encodedMac = Convert.ToBase64String(mac); TraceSource.TraceInformation(string.Format("Calculated mac: {0}", encodedMac)); return(encodedMac); }
/// <summary> /// Authenticates an upcoming request message /// </summary> /// <param name="authorization">Authorization header</param> /// <param name="host">Host header</param> /// <param name="method">Request method</param> /// <param name="uri">Request Uri</param> /// <param name="credentials">A method for searching across the available credentials</param> /// <param name="timestampSkewSec">Accepted Time skew for timestamp verification</param> /// <param name="payloadHash">Hash of the request payload</param> /// <returns></returns> public static async Task <IPrincipal> AuthenticateAsync(string authorization, string host, string method, Uri uri, Func <string, Task <HawkCredential> > credentials, int timestampSkewSec = 60, Func <Task <string> > requestPayload = null, string mediaType = null) { if (Trace.CorrelationManager.ActivityId == Guid.Empty) { Trace.CorrelationManager.ActivityId = Guid.NewGuid(); } TraceSource.TraceInformation(string.Format("{0} - Received Auth header: {1}", Trace.CorrelationManager.ActivityId, authorization)); if (string.IsNullOrEmpty(authorization)) { TraceSource.TraceData(TraceEventType.Warning, 0, string.Format("{0} - Authorization parameter can not be null or empty", Trace.CorrelationManager.ActivityId)); throw new ArgumentException("Authorization parameter can not be null or empty", "authorization"); } if (string.IsNullOrEmpty(host)) { TraceSource.TraceData(TraceEventType.Warning, 0, string.Format("{0} - Host header can not be null or empty", Trace.CorrelationManager.ActivityId)); throw new ArgumentException("Host header can not be null or empty", "host"); } var attributes = ParseAttributes(authorization); ValidateAttributes(timestampSkewSec, attributes); HawkCredential credential = null; try { credential = await credentials(attributes["id"]); } catch (Exception ex) { TraceSource.TraceData(TraceEventType.Warning, 0, string.Format("{0} - Unknown user", Trace.CorrelationManager.ActivityId)); throw new SecurityException("Unknown user", ex); } ValidateCredentials(credential); if (!string.IsNullOrEmpty(attributes["hash"])) { if (requestPayload != null && string.IsNullOrEmpty(mediaType)) { TraceSource.TraceData(TraceEventType.Warning, 0, string.Format("{0} - Media Type can not be null when the payload hash must be calculated", Trace.CorrelationManager.ActivityId)); throw new ArgumentException("MediaType can not be null or empty", "mediaType"); } var hash = CalculatePayloadHash(await requestPayload(), mediaType, credential); if (attributes["hash"] != hash) { TraceSource.TraceData(TraceEventType.Warning, 0, string.Format("{0} - Bad payload hash. Received hash {1}. Calculated hash {2}", Trace.CorrelationManager.ActivityId, attributes["hash"], hash)); throw new SecurityException("Bad payload hash"); } } var mac = CalculateMac(host, method, uri, attributes["ext"], attributes["ts"], attributes["nonce"], credential, "header", attributes["hash"]); if (!IsEqual(mac, attributes["mac"])) { TraceSource.TraceData(TraceEventType.Warning, 0, string.Format("{0} - Bad Mac. Received mac {1}. Calculated Mac {2}", Trace.CorrelationManager.ActivityId, attributes["mac"], mac)); throw new SecurityException("Bad mac"); } var userClaim = new Claim(ClaimTypes.Name, credential.User); var allClaims = Enumerable.Concat(new Claim[] { userClaim }, (credential.AdditionalClaims != null) ? credential.AdditionalClaims : Enumerable.Empty <Claim>()); var identity = new ClaimsIdentity(allClaims, "Hawk"); var principal = new ClaimsPrincipal(new ClaimsIdentity[] { identity }); return(principal); }
static void Main(string[] args) { var config = new HttpSelfHostConfiguration("http://localhost:8091"); //config.Filters.Add(new RequiresHawkAttribute(typeof(HawkRepository))); var handler = new HawkMessageHandler(new HttpControllerDispatcher(config), (id) => { return new HawkCredential { Id = id, Key = "werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn", Algorithm = "hmacsha256", User = "******" }; }); config.Routes.MapHttpRoute( "Filter", "api/filter", new { controller = "HelloWorldWithFilter" }); config.Routes.MapHttpRoute( "API Default", "api/{controller}/{id}", new { id = RouteParameter.Optional, controller = "HelloWorld" }, null, handler ); using (HttpSelfHostServer server = new HttpSelfHostServer(config)) { server.OpenAsync().Wait(); Console.WriteLine("Press Enter to quit."); var credential = new HawkCredential { Id = "dh37fgj492je", Key = "werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn", Algorithm = "hmacsha256", User = "******" }; var clientHandler = new HawkClientMessageHandler(new HttpClientHandler(), credential, "some-app-data"); var client = new HttpClient(clientHandler); var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:8091/Api/HelloWorld"); request.Headers.Host = "localhost"; var response = client.SendAsync(request).Result; string message = response.Content.ReadAsStringAsync().Result; Console.WriteLine("Response {0} - Http Status Code {1}", message, response.StatusCode); var client2 = new HttpClient(); request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:8091/Api/HelloWorldAnonymous"); request.Headers.Host = "localhost"; response = client2.SendAsync(request).Result; message = response.Content.ReadAsStringAsync().Result; Console.WriteLine("Response {0} - Http Status Code {1}", message, response.StatusCode); var client3 = new HttpClient(); var bewit = Hawk.GetBewit("localhost", new Uri("http://localhost:8091/Api/HelloWorld"), credential, 60000); request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:8091/Api/HelloWorld?bewit=" + bewit); request.Headers.Host = "localhost"; response = client3.SendAsync(request).Result; message = response.Content.ReadAsStringAsync().Result; Console.WriteLine("Response {0} - Http Status Code {1}", message, response.StatusCode); var client4 = new HttpClient(clientHandler); var request4 = new HttpRequestMessage(HttpMethod.Get, "http://localhost:8091/api/filter"); request4.Headers.Host = "localhost"; var response4 = client4.SendAsync(request4).Result; string message4 = response4.Content.ReadAsStringAsync().Result; Console.WriteLine("Response {0} - Http Status Code {1}", message4, response4.StatusCode); Console.WriteLine("Press a key to close the app"); Console.ReadLine(); } }
/// <summary> /// Computes a mac following the Hawk rules /// </summary> /// <param name="host">Host header</param> /// <param name="method">Request method</param> /// <param name="uri">Request uri</param> /// <param name="ext">Extesion attribute</param> /// <param name="ts">Timestamp</param> /// <param name="nonce">Nonce</param> /// <param name="credential">Credential</param> /// <param name="payload">Hash of the request payload</param> /// <returns>Generated mac</returns> public static string CalculateMac(string host, string method, Uri uri, string ext, string ts, string nonce, HawkCredential credential, string type, string payloadHash = null) { var hmac = HMAC.Create("hmac" + credential.Algorithm); hmac.Key = Encoding.UTF8.GetBytes(credential.Key); var sanitizedHost = (host.IndexOf(':') > 0) ? host.Substring(0, host.IndexOf(':')) : host; var normalized = "hawk.1." + type + "\n" + ts + "\n" + nonce + "\n" + method.ToUpper() + "\n" + uri.PathAndQuery.ToLower() + "\n" + sanitizedHost.ToLower() + "\n" + //uri.Port.ToString() + "\n" + ((!string.IsNullOrEmpty(payloadHash)) ? payloadHash : "") + "\n" + ((!string.IsNullOrEmpty(ext)) ? ext : "") + "\n"; TraceSource.TraceInformation(string.Format("Normalized String: {0}", normalized)); var messageBytes = Encoding.UTF8.GetBytes(normalized); var mac = hmac.ComputeHash(messageBytes); var encodedMac = Convert.ToBase64String(mac); TraceSource.TraceInformation(string.Format("Calculated mac: {0}", encodedMac)); return(encodedMac); }
/// <summary> /// Generates a mac hash using the supplied payload and credentials /// </summary> /// <param name="payload"></param> /// <param name="credential"></param> /// <returns></returns> public static string CalculatePayloadHash(string payload, string mediaType, HawkCredential credential) { var normalized = "hawk.1.payload\n" + mediaType + "\n" + payload + "\n"; TraceSource.TraceInformation(string.Format("Normalized Payload String: {0}", normalized)); var algorithm = HashAlgorithm.Create(credential.Algorithm); var encodedMac = Convert.ToBase64String(algorithm .ComputeHash(Encoding.UTF8.GetBytes(normalized))); TraceSource.TraceInformation(string.Format("Calculated payload hash: {0}", encodedMac)); return encodedMac; }
/// <summary> /// Authenticates an upcoming request message /// </summary> /// <param name="authorization">Authorization header</param> /// <param name="host">Host header</param> /// <param name="method">Request method</param> /// <param name="uri">Request Uri</param> /// <param name="credentials">A method for searching across the available credentials</param> /// <param name="timestampSkewSec">Accepted Time skew for timestamp verification</param> /// <param name="payloadHash">Hash of the request payload</param> /// <returns></returns> public static IPrincipal Authenticate(string authorization, string host, string method, Uri uri, Func <string, HawkCredential> credentials, int timestampSkewSec = 60, Func <byte[]> requestPayload = null) { if (Trace.CorrelationManager.ActivityId == Guid.Empty) { Trace.CorrelationManager.ActivityId = Guid.NewGuid(); } TraceSource.TraceInformation(string.Format("{0} - Received Auth header: {1}", Trace.CorrelationManager.ActivityId, authorization)); if (string.IsNullOrEmpty(authorization)) { TraceSource.TraceData(TraceEventType.Warning, 0, "{0} - Authorization parameter can not be null or empty", Trace.CorrelationManager.ActivityId); throw new ArgumentException("Authorization parameter can not be null or empty", "authorization"); } if (string.IsNullOrEmpty(host)) { TraceSource.TraceData(TraceEventType.Warning, 0, "{0} - Host header can not be null or empty", Trace.CorrelationManager.ActivityId); throw new ArgumentException("Host header can not be null or empty", "host"); } var attributes = ParseAttributes(authorization); ValidateAttributes(timestampSkewSec, attributes); HawkCredential credential = null; try { credential = credentials(attributes["id"]); } catch (Exception ex) { TraceSource.TraceData(TraceEventType.Warning, 0, "{0} - Unknown user", Trace.CorrelationManager.ActivityId); throw new SecurityException("Unknown user", ex); } ValidateCredentials(credential); if (!string.IsNullOrEmpty(attributes["hash"])) { ValidatePayload(credential, attributes["hash"], requestPayload); } var mac = CalculateMac(host, method, uri, attributes["ext"], attributes["ts"], attributes["nonce"], credential, "header", attributes["hash"]); if (!IsEqual(mac, attributes["mac"])) { TraceSource.TraceData(TraceEventType.Warning, 0, "{0} - Bad Mac. Received mac {1}. Calculated Mac {2}", Trace.CorrelationManager.ActivityId, attributes["mac"], mac); throw new SecurityException("Bad mac"); } #if NET45 var userClaim = new Claim(ClaimTypes.Name, credential.User); var allClaims = Enumerable.Concat(new Claim[] { userClaim }, (credential.AdditionalClaims != null) ? credential.AdditionalClaims : Enumerable.Empty <Claim>()); var identity = new ClaimsIdentity(allClaims, "Hawk"); var principal = new ClaimsPrincipal(new ClaimsIdentity[] { identity }); #else var identity = new GenericIdentity(credential.User, "Hawk"); var principal = new GenericPrincipal(identity, credential.Roles); #endif return(principal); }
/// <summary> /// Gets a new Bewit for Single URI authorization /// </summary> /// <param name="host">Host name</param> /// <param name="uri">Request uri</param> /// <param name="credential">Hawk credential</param> /// <param name="ttlSec">Time to live in seconds for the Bewit</param> /// <param name="ext">Extension attributes</param> /// <returns>A fresh Bewit</returns> public static string GetBewit(string host, Uri uri, HawkCredential credential, int ttlSec, string ext = null) { var now = ConvertToUnixTimestamp(DateTime.Now); var expiration = Math.Floor(now) + ttlSec; var mac = CalculateMac(host, "GET", uri, ext, expiration.ToString(), "", credential, "bewit"); var bewit = Convert.ToBase64String( Encoding.UTF8.GetBytes(credential.Id + '\\' + expiration + '\\' + mac + '\\' + ext)); return bewit; }
/// <summary> /// Computes a mac following the Hawk rules /// </summary> /// <param name="host">Host header</param> /// <param name="method">Request method</param> /// <param name="uri">Request uri</param> /// <param name="ext">Extesion attribute</param> /// <param name="ts">Timestamp</param> /// <param name="nonce">Nonce</param> /// <param name="credential">Credential</param> /// <param name="payload">Hash of the request payload</param> /// <returns>Generated mac</returns> public static string CalculateMac(string host, string method, Uri uri, string ext, string ts, string nonce, HawkCredential credential, string type, string payloadHash = null) { var hmac = new HMAC("hmac" + credential.Algorithm); hmac.Key = BinaryHelper.FromHexString(credential.Key); var sanitizedHost = (host.IndexOf(':') > 0) ? host.Substring(0, host.IndexOf(':')) : host; var normalized = "hawk.1." + type + "\n" + ts + "\n" + nonce + "\n" + method.ToUpper() + "\n" + uri.PathAndQuery + "\n" + sanitizedHost.ToLower() + "\n" + uri.Port.ToString() + "\n" + ((!string.IsNullOrEmpty(payloadHash)) ? payloadHash : "") + "\n" + "\n"; var messageBytes = Encoding.UTF8.GetBytes(normalized); var mac = hmac.ComputeHash(messageBytes); var encodedMac = Convert.ToBase64String(mac); return(encodedMac); }
/// <summary> /// Creates a new Hawk Authorization header based on the provided parameters /// </summary> /// <param name="host">Host header</param> /// <param name="method">Request method</param> /// <param name="uri">Request uri</param> /// <param name="credential">Credential used to calculate the MAC</param> /// <param name="ext">Optional extension attribute</param> /// <param name="ts">Timestamp</param> /// <param name="nonce">Random Nonce</param> /// <param name="payloadHash">Hash of the request payload</param> /// <param name="type">Type used as header for the normalized string. Default value is 'header'</param> /// <returns>Hawk authorization header</returns> public static string GetAuthorizationHeader(string host, string method, Uri uri, HawkCredential credential, string ext = null, DateTime? ts = null, string nonce = null, string payloadHash = null, string type = null) { if(string.IsNullOrEmpty(host)) throw new ArgumentException("The host can not be null or empty", "host"); if (string.IsNullOrEmpty(method)) throw new ArgumentException("The method can not be null or empty", "method"); if(credential == null) throw new ArgumentNullException("The credential can not be null", "credential"); if (string.IsNullOrEmpty(nonce)) { nonce = GetRandomString(6); } if (string.IsNullOrEmpty(type)) { type = "header"; } var normalizedTs = ((int)Math.Floor((ConvertToUnixTimestamp((ts.HasValue) ? ts.Value : DateTime.UtcNow)))).ToString(); var mac = CalculateMac(host, method, uri, ext, normalizedTs, nonce, credential, type, payloadHash); var authorization = string.Format("id=\"{0}\", ts=\"{1}\", nonce=\"{2}\", mac=\"{3}\", ext=\"{4}\"", credential.Id, normalizedTs, nonce, mac, ext); if (!string.IsNullOrEmpty(payloadHash)) { authorization += string.Format(", hash=\"{0}\"", payloadHash); } return authorization; }
/// <summary> /// Adds the Hawk authorization header to a request message /// </summary> /// <param name="request">Request instance</param> /// <param name="credential">Hawk credentials</param> public static void SignRequest(this HttpWebRequest request, HawkCredential credential) { SignRequest(request, credential, null, null, null, null); }
/// <summary> /// Computes a mac following the Hawk rules /// </summary> /// <param name="host">Host header</param> /// <param name="method">Request method</param> /// <param name="uri">Request uri</param> /// <param name="ext">Extesion attribute</param> /// <param name="ts">Timestamp</param> /// <param name="nonce">Nonce</param> /// <param name="credential">Credential</param> /// <param name="payload">Hash of the request payload</param> /// <returns>Generated mac</returns> public static string CalculateMac(string host, string method, Uri uri, string ext, string ts, string nonce, HawkCredential credential, string type, string payloadHash = null) { var hmac = HMAC.Create(credential.Algorithm); hmac.Key = Encoding.UTF8.GetBytes(credential.Key); var sanitizedHost = (host.IndexOf(':') > 0) ? host.Substring(0, host.IndexOf(':')) : host; var normalized = "hawk.1." + type + "\n" + ts + "\n" + nonce + "\n" + method.ToUpper() + "\n" + uri.PathAndQuery + "\n" + sanitizedHost.ToLower() + "\n" + uri.Port.ToString() + "\n" + ((!string.IsNullOrEmpty(payloadHash)) ? payloadHash : "") + "\n" + ((!string.IsNullOrEmpty(ext)) ? ext : "") + "\n"; TraceSource.TraceInformation(string.Format("Normalized String: {0}", normalized)); var messageBytes = Encoding.UTF8.GetBytes(normalized); var mac = hmac.ComputeHash(messageBytes); var encodedMac = Convert.ToBase64String(mac); TraceSource.TraceInformation(string.Format("Calculated mac: {0}", encodedMac)); return encodedMac; }
private static void ValidatePayload(HawkCredential credential, string receivedHash, Func<byte[]> requestPayload) { var hmac = System.Security.Cryptography.HMAC.Create(credential.Algorithm); hmac.Key = Encoding.UTF8.GetBytes(credential.Key); var hash = Convert.ToBase64String(hmac.ComputeHash(requestPayload())); if (receivedHash != hash) { throw new SecurityException("Bad payload hash"); } }
/// <summary> /// Creates a new Hawk Authorization header based on the provided parameters /// </summary> /// <param name="host">Host header</param> /// <param name="method">Request method</param> /// <param name="uri">Request uri</param> /// <param name="credential">Credential used to calculate the MAC</param> /// <param name="ext">Optional extension attribute</param> /// <param name="ts">Timestamp</param> /// <param name="nonce">Random Nonce</param> /// <param name="payloadHash">Hash of the request payload</param> /// <param name="type">Type used as header for the normalized string. Default value is 'header'</param> /// <returns>Hawk authorization header</returns> public static string GetAuthorizationHeader(string host, string method, Uri uri, HawkCredential credential, string ext = null, DateTime?ts = null, string nonce = null, string payloadHash = null, string type = null) { if (string.IsNullOrEmpty(host)) { throw new ArgumentException("The host can not be null or empty", "host"); } if (string.IsNullOrEmpty(method)) { throw new ArgumentException("The method can not be null or empty", "method"); } if (credential == null) { throw new ArgumentNullException("The credential can not be null", "credential"); } if (string.IsNullOrEmpty(nonce)) { nonce = GetRandomString(6); } if (string.IsNullOrEmpty(type)) { type = "header"; } var normalizedTs = ((int)Math.Floor((ConvertToUnixTimestamp((ts.HasValue) ? ts.Value : DateTime.UtcNow)))).ToString(); var mac = CalculateMac(host, method, uri, ext, normalizedTs, nonce, credential, type, payloadHash); var authorization = string.Format("id=\"{0}\", ts=\"{1}\", nonce=\"{2}\", mac=\"{3}\", ext=\"{4}\"", credential.Id, normalizedTs, nonce, mac, ext); if (!string.IsNullOrEmpty(payloadHash)) { authorization += string.Format(", hash=\"{0}\"", payloadHash); } return(authorization); }
/// <summary> /// Computes a mac following the Hawk rules /// </summary> /// <param name="host">Host header</param> /// <param name="method">Request method</param> /// <param name="uri">Request uri</param> /// <param name="ext">Extesion attribute</param> /// <param name="ts">Timestamp</param> /// <param name="nonce">Nonce</param> /// <param name="credential">Credential</param> /// <param name="payload">Hash of the request payload</param> /// <returns>Generated mac</returns> public static string CalculateMac(string host, string method, Uri uri, string ext, string ts, string nonce, HawkCredential credential, string type, string payloadHash = null) { HMAC hmac = null; if (credential.Algorithm.Equals("sha1", StringComparison.InvariantCultureIgnoreCase)) hmac = new HMACSHA1(); else if (credential.Algorithm.Equals("sha256", StringComparison.InvariantCultureIgnoreCase)) hmac = new HMACSHA256(); else throw new Exception("Not supported algorithm"); hmac.Key = Encoding.UTF8.GetBytes(credential.Key); var sanitizedHost = (host.IndexOf(':') > 0) ? host.Substring(0, host.IndexOf(':')) : host; var normalized = "hawk.1." + type + "\n" + ts + "\n" + nonce + "\n" + method.ToUpper() + "\n" + uri.PathAndQuery + "\n" + sanitizedHost + "\n" + uri.Port.ToString() + "\n" + ((!string.IsNullOrEmpty(payloadHash)) ? payloadHash : "") + "\n" + ((!string.IsNullOrEmpty(ext)) ? ext : "") + "\n"; TraceSource.TraceInformation(string.Format("Normalized String: {0}", normalized)); var messageBytes = Encoding.UTF8.GetBytes(normalized); var mac = hmac.ComputeHash(messageBytes); var encodedMac = Convert.ToBase64String(mac); TraceSource.TraceInformation(string.Format("Calculated mac: {0}", encodedMac)); return encodedMac; }