├── .gitattributes ├── .gitignore ├── HMACAuthentication.Client ├── App.config ├── HMACAuthentication.Client.csproj ├── Order.cs ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── HMACAuthentication.WebApi ├── App_Start │ └── WebApiConfig.cs ├── Controllers │ └── OrdersController.cs ├── Filters │ └── HMACAuthenticationAttribute.cs ├── Global.asax ├── Global.asax.cs ├── HMACAuthentication.WebApi.csproj ├── Properties │ └── AssemblyInfo.cs ├── Web.Debug.config ├── Web.Release.config ├── Web.config └── packages.config ├── README.md ├── WebApiHMACAuthentication.sln └── packages ├── Microsoft.AspNet.WebApi.5.1.2 └── Microsoft.AspNet.WebApi.5.1.2.nupkg ├── Microsoft.AspNet.WebApi.Client.5.1.2 ├── Microsoft.AspNet.WebApi.Client.5.1.2.nupkg └── lib │ ├── net45 │ ├── System.Net.Http.Formatting.dll │ └── System.Net.Http.Formatting.xml │ └── portable-wp8%2Bnetcore45%2Bnet45 │ ├── System.Net.Http.Formatting.dll │ └── System.Net.Http.Formatting.xml ├── Microsoft.AspNet.WebApi.Client.5.2.2 ├── Microsoft.AspNet.WebApi.Client.5.2.2.nupkg └── lib │ ├── net45 │ ├── System.Net.Http.Formatting.dll │ └── System.Net.Http.Formatting.xml │ └── portable-wp8+netcore45+net45+wp81+wpa81 │ ├── System.Net.Http.Formatting.dll │ └── System.Net.Http.Formatting.xml ├── Microsoft.AspNet.WebApi.Core.5.1.2 ├── Content │ └── web.config.transform ├── Microsoft.AspNet.WebApi.Core.5.1.2.nupkg └── lib │ └── net45 │ ├── System.Web.Http.dll │ └── System.Web.Http.xml ├── Microsoft.AspNet.WebApi.WebHost.5.1.2 ├── Microsoft.AspNet.WebApi.WebHost.5.1.2.nupkg └── lib │ └── net45 │ ├── System.Web.Http.WebHost.dll │ └── System.Web.Http.WebHost.xml ├── Newtonsoft.Json.5.0.6 ├── Newtonsoft.Json.5.0.6.nupkg └── lib │ ├── net20 │ ├── Newtonsoft.Json.dll │ └── Newtonsoft.Json.xml │ ├── net35 │ ├── Newtonsoft.Json.dll │ └── Newtonsoft.Json.xml │ ├── net40 │ ├── Newtonsoft.Json.dll │ └── Newtonsoft.Json.xml │ ├── net45 │ ├── Newtonsoft.Json.dll │ └── Newtonsoft.Json.xml │ ├── netcore45 │ ├── Newtonsoft.Json.dll │ └── Newtonsoft.Json.xml │ ├── portable-net40%2Bsl4%2Bwp7%2Bwin8 │ ├── Newtonsoft.Json.dll │ └── Newtonsoft.Json.xml │ └── portable-net45%2Bwp80%2Bwin8 │ ├── Newtonsoft.Json.dll │ └── Newtonsoft.Json.xml ├── Newtonsoft.Json.6.0.4 ├── Newtonsoft.Json.6.0.4.nupkg ├── lib │ ├── net20 │ │ ├── Newtonsoft.Json.dll │ │ └── Newtonsoft.Json.xml │ ├── net35 │ │ ├── Newtonsoft.Json.dll │ │ └── Newtonsoft.Json.xml │ ├── net40 │ │ ├── Newtonsoft.Json.dll │ │ └── Newtonsoft.Json.xml │ ├── net45 │ │ ├── Newtonsoft.Json.dll │ │ └── Newtonsoft.Json.xml │ ├── netcore45 │ │ ├── Newtonsoft.Json.dll │ │ └── Newtonsoft.Json.xml │ ├── portable-net40+sl5+wp80+win8+wpa81 │ │ ├── Newtonsoft.Json.dll │ │ └── Newtonsoft.Json.xml │ └── portable-net45+wp80+win8+wpa81 │ │ ├── Newtonsoft.Json.dll │ │ └── Newtonsoft.Json.xml └── tools │ └── install.ps1 └── repositories.config /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | 11 | [Dd]ebug/ 12 | [Rr]elease/ 13 | x64/ 14 | build/ 15 | [Bb]in/ 16 | [Oo]bj/ 17 | 18 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 19 | !packages/*/build/ 20 | 21 | # MSTest test Results 22 | [Tt]est[Rr]esult*/ 23 | [Bb]uild[Ll]og.* 24 | 25 | *_i.c 26 | *_p.c 27 | *.ilk 28 | *.meta 29 | *.obj 30 | *.pch 31 | *.pdb 32 | *.pgc 33 | *.pgd 34 | *.rsp 35 | *.sbr 36 | *.tlb 37 | *.tli 38 | *.tlh 39 | *.tmp 40 | *.tmp_proj 41 | *.log 42 | *.vspscc 43 | *.vssscc 44 | .builds 45 | *.pidb 46 | *.log 47 | *.scc 48 | 49 | # Visual C++ cache files 50 | ipch/ 51 | *.aps 52 | *.ncb 53 | *.opensdf 54 | *.sdf 55 | *.cachefile 56 | 57 | # Visual Studio profiler 58 | *.psess 59 | *.vsp 60 | *.vspx 61 | 62 | # Guidance Automation Toolkit 63 | *.gpState 64 | 65 | # ReSharper is a .NET coding add-in 66 | _ReSharper*/ 67 | *.[Rr]e[Ss]harper 68 | 69 | # TeamCity is a build add-in 70 | _TeamCity* 71 | 72 | # DotCover is a Code Coverage Tool 73 | *.dotCover 74 | 75 | # NCrunch 76 | *.ncrunch* 77 | .*crunch*.local.xml 78 | 79 | # Installshield output folder 80 | [Ee]xpress/ 81 | 82 | # DocProject is a documentation generator add-in 83 | DocProject/buildhelp/ 84 | DocProject/Help/*.HxT 85 | DocProject/Help/*.HxC 86 | DocProject/Help/*.hhc 87 | DocProject/Help/*.hhk 88 | DocProject/Help/*.hhp 89 | DocProject/Help/Html2 90 | DocProject/Help/html 91 | 92 | # Click-Once directory 93 | publish/ 94 | 95 | # Publish Web Output 96 | *.Publish.xml 97 | 98 | # NuGet Packages Directory 99 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 100 | #packages/ 101 | 102 | # Windows Azure Build Output 103 | csx 104 | *.build.csdef 105 | 106 | # Windows Store app package directory 107 | AppPackages/ 108 | 109 | # Others 110 | sql/ 111 | *.Cache 112 | ClientBin/ 113 | [Ss]tyle[Cc]op.* 114 | ~$* 115 | *~ 116 | *.dbmdl 117 | *.[Pp]ublish.xml 118 | *.pfx 119 | *.publishsettings 120 | 121 | # RIA/Silverlight projects 122 | Generated_Code/ 123 | 124 | # Backup & report files from converting an old project file to a newer 125 | # Visual Studio version. Backup files are not needed, because we have git ;-) 126 | _UpgradeReport_Files/ 127 | Backup*/ 128 | UpgradeLog*.XML 129 | UpgradeLog*.htm 130 | 131 | # SQL Server files 132 | App_Data/*.mdf 133 | App_Data/*.ldf 134 | 135 | 136 | #LightSwitch generated files 137 | GeneratedArtifacts/ 138 | _Pvt_Extensions/ 139 | ModelManifest.xml 140 | 141 | # ========================= 142 | # Windows detritus 143 | # ========================= 144 | 145 | # Windows image file caches 146 | Thumbs.db 147 | ehthumbs.db 148 | 149 | # Folder config file 150 | Desktop.ini 151 | 152 | # Recycle Bin used on file shares 153 | $RECYCLE.BIN/ 154 | 155 | # Mac desktop service store files 156 | .DS_Store 157 | -------------------------------------------------------------------------------- /HMACAuthentication.Client/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /HMACAuthentication.Client/HMACAuthentication.Client.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {B9CECCA4-C107-41DE-BB3D-CBE7E5561059} 8 | Exe 9 | Properties 10 | HMACAuthentication.Client 11 | HMACAuthentication.Client 12 | v4.5 13 | 512 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | False 37 | ..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll 38 | 39 | 40 | 41 | 42 | 43 | False 44 | ..\packages\Microsoft.AspNet.WebApi.Client.5.2.2\lib\net45\System.Net.Http.Formatting.dll 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 70 | -------------------------------------------------------------------------------- /HMACAuthentication.Client/Order.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace HMACAuthentication.Client 8 | { 9 | public class Order 10 | { 11 | public int OrderID { get; set; } 12 | public string CustomerName { get; set; } 13 | public string ShipperCity { get; set; } 14 | public Boolean IsShipped { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /HMACAuthentication.Client/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net.Http; 5 | using System.Net.Http.Headers; 6 | using System.Security.Cryptography; 7 | using System.Text; 8 | using System.Threading; 9 | using System.Threading.Tasks; 10 | 11 | namespace HMACAuthentication.Client 12 | { 13 | class Program 14 | { 15 | static void Main(string[] args) 16 | { 17 | RunAsync().Wait(); 18 | } 19 | 20 | static async Task RunAsync() 21 | { 22 | 23 | Console.WriteLine("Calling the back-end API"); 24 | 25 | string apiBaseAddress = "http://localhost:43326/"; 26 | 27 | CustomDelegatingHandler customDelegatingHandler = new CustomDelegatingHandler(); 28 | 29 | HttpClient client = HttpClientFactory.Create(customDelegatingHandler); 30 | 31 | var order = new Order { OrderID = 10248, CustomerName = "Taiseer Joudeh", ShipperCity = "Amman", IsShipped = true }; 32 | 33 | HttpResponseMessage response = await client.PostAsJsonAsync(apiBaseAddress + "api/orders", order); 34 | 35 | if (response.IsSuccessStatusCode) 36 | { 37 | string responseString = await response.Content.ReadAsStringAsync(); 38 | Console.WriteLine(responseString); 39 | Console.WriteLine("HTTP Status: {0}, Reason {1}. Press ENTER to exit", response.StatusCode, response.ReasonPhrase); 40 | } 41 | else 42 | { 43 | Console.WriteLine("Failed to call the API. HTTP Status: {0}, Reason {1}", response.StatusCode, response.ReasonPhrase); 44 | } 45 | 46 | Console.ReadLine(); 47 | } 48 | 49 | public class CustomDelegatingHandler : DelegatingHandler 50 | { 51 | //Obtained from the server earlier, APIKey MUST be stored securly and in App.Config 52 | private string APPId = "4d53bce03ec34c0a911182d4c228ee6c"; 53 | private string APIKey = "A93reRTUJHsCuQSHR+L3GxqOJyDmQpCgps102ciuabc="; 54 | 55 | protected async override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 56 | { 57 | 58 | HttpResponseMessage response = null; 59 | string requestContentBase64String = string.Empty; 60 | 61 | string requestUri = System.Web.HttpUtility.UrlEncode(request.RequestUri.AbsoluteUri.ToLower()); 62 | 63 | string requestHttpMethod = request.Method.Method; 64 | 65 | //Calculate UNIX time 66 | DateTime epochStart = new DateTime(1970, 01, 01, 0, 0, 0, 0, DateTimeKind.Utc); 67 | TimeSpan timeSpan = DateTime.UtcNow - epochStart; 68 | string requestTimeStamp = Convert.ToUInt64(timeSpan.TotalSeconds).ToString(); 69 | 70 | //create random nonce for each request 71 | string nonce = Guid.NewGuid().ToString("N"); 72 | 73 | //Checking if the request contains body, usually will be null wiht HTTP GET and DELETE 74 | if (request.Content != null) 75 | { 76 | byte[] content = await request.Content.ReadAsByteArrayAsync(); 77 | MD5 md5 = MD5.Create(); 78 | //Hashing the request body, any change in request body will result in different hash, we'll incure message integrity 79 | byte[] requestContentHash = md5.ComputeHash(content); 80 | requestContentBase64String = Convert.ToBase64String(requestContentHash); 81 | } 82 | 83 | //Creating the raw signature string 84 | string signatureRawData = String.Format("{0}{1}{2}{3}{4}{5}", APPId, requestHttpMethod, requestUri, requestTimeStamp, nonce, requestContentBase64String); 85 | 86 | var secretKeyByteArray = Convert.FromBase64String(APIKey); 87 | 88 | byte[] signature = Encoding.UTF8.GetBytes(signatureRawData); 89 | 90 | using (HMACSHA256 hmac = new HMACSHA256(secretKeyByteArray)) 91 | { 92 | byte[] signatureBytes = hmac.ComputeHash(signature); 93 | string requestSignatureBase64String = Convert.ToBase64String(signatureBytes); 94 | //Setting the values in the Authorization header using custom scheme (amx) 95 | request.Headers.Authorization = new AuthenticationHeaderValue("amx", string.Format("{0}:{1}:{2}:{3}", APPId, requestSignatureBase64String, nonce, requestTimeStamp)); 96 | } 97 | 98 | response = await base.SendAsync(request, cancellationToken); 99 | 100 | return response; 101 | } 102 | } 103 | 104 | private void GenerateAPPKey() 105 | { 106 | using (var cryptoProvider = new RNGCryptoServiceProvider()) 107 | { 108 | byte[] secretKeyByteArray = new byte[32]; //256 bit 109 | cryptoProvider.GetBytes(secretKeyByteArray); 110 | var APIKey = Convert.ToBase64String(secretKeyByteArray); 111 | } 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /HMACAuthentication.Client/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("HMACAuthentication.Client")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("HMACAuthentication.Client")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("651613b5-5996-4172-ad76-c01412e328bb")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /HMACAuthentication.Client/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /HMACAuthentication.WebApi/App_Start/WebApiConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web.Http; 5 | 6 | namespace HMACAuthentication.WebApi 7 | { 8 | public static class WebApiConfig 9 | { 10 | public static void Register(HttpConfiguration config) 11 | { 12 | config.MapHttpAttributeRoutes(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /HMACAuthentication.WebApi/Controllers/OrdersController.cs: -------------------------------------------------------------------------------- 1 | using HMACAuthentication.WebApi.Filters; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Net; 6 | using System.Net.Http; 7 | using System.Security.Claims; 8 | using System.Web.Http; 9 | 10 | namespace HMACAuthentication.WebApi.Controllers 11 | { 12 | [HMACAuthentication] 13 | [RoutePrefix("api/Orders")] 14 | public class OrdersController : ApiController 15 | { 16 | [Route("")] 17 | public IHttpActionResult Get() 18 | { 19 | ClaimsPrincipal principal = Request.GetRequestContext().Principal as ClaimsPrincipal; 20 | 21 | var Name = ClaimsPrincipal.Current.Identity.Name; 22 | 23 | return Ok(Order.CreateOrders()); 24 | } 25 | 26 | [Route("")] 27 | public IHttpActionResult Post(Order order) 28 | { 29 | return Ok(order); 30 | } 31 | 32 | } 33 | 34 | #region Helpers 35 | 36 | public class Order 37 | { 38 | public int OrderID { get; set; } 39 | public string CustomerName { get; set; } 40 | public string ShipperCity { get; set; } 41 | public Boolean IsShipped { get; set; } 42 | 43 | 44 | public static List CreateOrders() 45 | { 46 | List OrderList = new List 47 | { 48 | new Order {OrderID = 10248, CustomerName = "Taiseer Joudeh", ShipperCity = "Amman", IsShipped = true }, 49 | new Order {OrderID = 10249, CustomerName = "Ahmad Hasan", ShipperCity = "Dubai", IsShipped = false}, 50 | new Order {OrderID = 10250,CustomerName = "Tamer Yaser", ShipperCity = "Jeddah", IsShipped = false }, 51 | new Order {OrderID = 10251,CustomerName = "Lina Majed", ShipperCity = "Abu Dhabi", IsShipped = false}, 52 | new Order {OrderID = 10252,CustomerName = "Yasmeen Rami", ShipperCity = "Kuwait", IsShipped = true} 53 | }; 54 | 55 | return OrderList; 56 | } 57 | } 58 | 59 | #endregion 60 | } 61 | -------------------------------------------------------------------------------- /HMACAuthentication.WebApi/Filters/HMACAuthenticationAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Net.Http; 6 | using System.Net.Http.Headers; 7 | using System.Security.Cryptography; 8 | using System.Security.Principal; 9 | using System.Text; 10 | using System.Threading; 11 | using System.Threading.Tasks; 12 | using System.Web; 13 | using System.Web.Http; 14 | using System.Web.Http.Filters; 15 | using System.Web.Http.Results; 16 | 17 | namespace HMACAuthentication.WebApi.Filters 18 | { 19 | public class HMACAuthenticationAttribute : Attribute, IAuthenticationFilter 20 | { 21 | private static Dictionary allowedApps = new Dictionary(); 22 | private readonly UInt64 requestMaxAgeInSeconds = 300; //5 mins 23 | private readonly string authenticationScheme = "amx"; 24 | 25 | public HMACAuthenticationAttribute() 26 | { 27 | if (allowedApps.Count == 0) 28 | { 29 | allowedApps.Add("4d53bce03ec34c0a911182d4c228ee6c", "A93reRTUJHsCuQSHR+L3GxqOJyDmQpCgps102ciuabc="); 30 | } 31 | } 32 | 33 | public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken) 34 | { 35 | var req = context.Request; 36 | 37 | if (req.Headers.Authorization != null && authenticationScheme.Equals(req.Headers.Authorization.Scheme, StringComparison.OrdinalIgnoreCase)) 38 | { 39 | var rawAuthzHeader = req.Headers.Authorization.Parameter; 40 | 41 | var autherizationHeaderArray = GetAutherizationHeaderValues(rawAuthzHeader); 42 | 43 | if (autherizationHeaderArray != null) 44 | { 45 | var APPId = autherizationHeaderArray[0]; 46 | var incomingBase64Signature = autherizationHeaderArray[1]; 47 | var nonce = autherizationHeaderArray[2]; 48 | var requestTimeStamp = autherizationHeaderArray[3]; 49 | 50 | var isValid = isValidRequest(req, APPId, incomingBase64Signature, nonce, requestTimeStamp); 51 | 52 | if (isValid.Result) 53 | { 54 | var currentPrincipal = new GenericPrincipal(new GenericIdentity(APPId), null); 55 | context.Principal = currentPrincipal; 56 | } 57 | else 58 | { 59 | context.ErrorResult = new UnauthorizedResult(new AuthenticationHeaderValue[0], context.Request); 60 | } 61 | } 62 | else 63 | { 64 | context.ErrorResult = new UnauthorizedResult(new AuthenticationHeaderValue[0], context.Request); 65 | } 66 | } 67 | else 68 | { 69 | context.ErrorResult = new UnauthorizedResult(new AuthenticationHeaderValue[0], context.Request); 70 | } 71 | 72 | return Task.FromResult(0); 73 | } 74 | 75 | public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken) 76 | { 77 | context.Result = new ResultWithChallenge(context.Result); 78 | return Task.FromResult(0); 79 | } 80 | 81 | public bool AllowMultiple 82 | { 83 | get { return false; } 84 | } 85 | 86 | private string[] GetAutherizationHeaderValues(string rawAuthzHeader) 87 | { 88 | 89 | var credArray = rawAuthzHeader.Split(':'); 90 | 91 | if (credArray.Length == 4) 92 | { 93 | return credArray; 94 | } 95 | else 96 | { 97 | return null; 98 | } 99 | 100 | } 101 | 102 | private async Task isValidRequest(HttpRequestMessage req, string APPId, string incomingBase64Signature, string nonce, string requestTimeStamp) 103 | { 104 | string requestContentBase64String = ""; 105 | string requestUri = HttpUtility.UrlEncode(req.RequestUri.AbsoluteUri.ToLower()); 106 | string requestHttpMethod = req.Method.Method; 107 | 108 | if (!allowedApps.ContainsKey(APPId)) 109 | { 110 | return false; 111 | } 112 | 113 | var sharedKey = allowedApps[APPId]; 114 | 115 | if (isReplayRequest(nonce, requestTimeStamp)) 116 | { 117 | return false; 118 | } 119 | 120 | byte[] hash = await ComputeHash(req.Content); 121 | 122 | if (hash != null) 123 | { 124 | requestContentBase64String = Convert.ToBase64String(hash); 125 | } 126 | 127 | string data = String.Format("{0}{1}{2}{3}{4}{5}", APPId, requestHttpMethod, requestUri, requestTimeStamp, nonce, requestContentBase64String); 128 | 129 | var secretKeyBytes = Convert.FromBase64String(sharedKey); 130 | 131 | byte[] signature = Encoding.UTF8.GetBytes(data); 132 | 133 | using (HMACSHA256 hmac = new HMACSHA256(secretKeyBytes)) 134 | { 135 | byte[] signatureBytes = hmac.ComputeHash(signature); 136 | 137 | return (incomingBase64Signature.Equals(Convert.ToBase64String(signatureBytes), StringComparison.Ordinal)); 138 | } 139 | 140 | } 141 | 142 | private bool isReplayRequest(string nonce, string requestTimeStamp) 143 | { 144 | if (System.Runtime.Caching.MemoryCache.Default.Contains(nonce)) 145 | { 146 | return true; 147 | } 148 | 149 | DateTime epochStart = new DateTime(1970, 01, 01, 0, 0, 0, 0, DateTimeKind.Utc); 150 | TimeSpan currentTs = DateTime.UtcNow - epochStart; 151 | 152 | var serverTotalSeconds = Convert.ToUInt64(currentTs.TotalSeconds); 153 | var requestTotalSeconds = Convert.ToUInt64(requestTimeStamp); 154 | 155 | if ((serverTotalSeconds - requestTotalSeconds) > requestMaxAgeInSeconds) 156 | { 157 | return true; 158 | } 159 | 160 | System.Runtime.Caching.MemoryCache.Default.Add(nonce, requestTimeStamp, DateTimeOffset.UtcNow.AddSeconds(requestMaxAgeInSeconds)); 161 | 162 | return false; 163 | } 164 | 165 | private static async Task ComputeHash(HttpContent httpContent) 166 | { 167 | using (MD5 md5 = MD5.Create()) 168 | { 169 | byte[] hash = null; 170 | var content = await httpContent.ReadAsByteArrayAsync(); 171 | if (content.Length != 0) 172 | { 173 | hash = md5.ComputeHash(content); 174 | } 175 | return hash; 176 | } 177 | } 178 | } 179 | 180 | public class ResultWithChallenge : IHttpActionResult 181 | { 182 | private readonly string authenticationScheme = "amx"; 183 | private readonly IHttpActionResult next; 184 | 185 | public ResultWithChallenge(IHttpActionResult next) 186 | { 187 | this.next = next; 188 | } 189 | 190 | public async Task ExecuteAsync(CancellationToken cancellationToken) 191 | { 192 | var response = await next.ExecuteAsync(cancellationToken); 193 | 194 | if (response.StatusCode == HttpStatusCode.Unauthorized) 195 | { 196 | response.Headers.WwwAuthenticate.Add(new AuthenticationHeaderValue(authenticationScheme)); 197 | } 198 | 199 | return response; 200 | } 201 | } 202 | } -------------------------------------------------------------------------------- /HMACAuthentication.WebApi/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="HMACAuthentication.WebApi.WebApiApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /HMACAuthentication.WebApi/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Http; 6 | using System.Web.Routing; 7 | 8 | namespace HMACAuthentication.WebApi 9 | { 10 | public class WebApiApplication : System.Web.HttpApplication 11 | { 12 | protected void Application_Start() 13 | { 14 | GlobalConfiguration.Configure(WebApiConfig.Register); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /HMACAuthentication.WebApi/HMACAuthentication.WebApi.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | 8 | 9 | 2.0 10 | {C34ED7DB-C840-42AA-889F-D2F64DD2D0A8} 11 | {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} 12 | Library 13 | Properties 14 | HMACAuthentication.WebApi 15 | HMACAuthentication.WebApi 16 | v4.5 17 | true 18 | 19 | 20 | 21 | 22 | 23 | 24 | true 25 | full 26 | false 27 | bin\ 28 | DEBUG;TRACE 29 | prompt 30 | 4 31 | 32 | 33 | pdbonly 34 | true 35 | bin\ 36 | TRACE 37 | prompt 38 | 4 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | ..\packages\Newtonsoft.Json.5.0.6\lib\net45\Newtonsoft.Json.dll 64 | 65 | 66 | ..\packages\Microsoft.AspNet.WebApi.Client.5.1.2\lib\net45\System.Net.Http.Formatting.dll 67 | 68 | 69 | ..\packages\Microsoft.AspNet.WebApi.Core.5.1.2\lib\net45\System.Web.Http.dll 70 | 71 | 72 | ..\packages\Microsoft.AspNet.WebApi.WebHost.5.1.2\lib\net45\System.Web.Http.WebHost.dll 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | Global.asax 85 | 86 | 87 | 88 | 89 | 90 | 91 | Web.config 92 | 93 | 94 | Web.config 95 | 96 | 97 | 98 | 99 | 10.0 100 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | True 110 | True 111 | 43326 112 | / 113 | http://localhost:43326/ 114 | False 115 | False 116 | 117 | 118 | False 119 | 120 | 121 | 122 | 123 | 130 | -------------------------------------------------------------------------------- /HMACAuthentication.WebApi/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("HMACAuthentication.WebApi")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("HMACAuthentication.WebApi")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("36630be0-9e53-4d1b-8b92-da6d60118b89")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /HMACAuthentication.WebApi/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /HMACAuthentication.WebApi/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /HMACAuthentication.WebApi/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /HMACAuthentication.WebApi/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ASP.NET Web API HMAC Authentication (API Key Authentication) 2 | ======================== 3 | 4 | Project shows how to secure ASP.NET Web API using API Keys, this technique is useful when TLS protocol is not an option and transmitting data should be done securely. 5 | -------------------------------------------------------------------------------- /WebApiHMACAuthentication.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30501.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HMACAuthentication.Client", "HMACAuthentication.Client\HMACAuthentication.Client.csproj", "{B9CECCA4-C107-41DE-BB3D-CBE7E5561059}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HMACAuthentication.WebApi", "HMACAuthentication.WebApi\HMACAuthentication.WebApi.csproj", "{C34ED7DB-C840-42AA-889F-D2F64DD2D0A8}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {B9CECCA4-C107-41DE-BB3D-CBE7E5561059}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {B9CECCA4-C107-41DE-BB3D-CBE7E5561059}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {B9CECCA4-C107-41DE-BB3D-CBE7E5561059}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {B9CECCA4-C107-41DE-BB3D-CBE7E5561059}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {C34ED7DB-C840-42AA-889F-D2F64DD2D0A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {C34ED7DB-C840-42AA-889F-D2F64DD2D0A8}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {C34ED7DB-C840-42AA-889F-D2F64DD2D0A8}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {C34ED7DB-C840-42AA-889F-D2F64DD2D0A8}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /packages/Microsoft.AspNet.WebApi.5.1.2/Microsoft.AspNet.WebApi.5.1.2.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Microsoft.AspNet.WebApi.5.1.2/Microsoft.AspNet.WebApi.5.1.2.nupkg -------------------------------------------------------------------------------- /packages/Microsoft.AspNet.WebApi.Client.5.1.2/Microsoft.AspNet.WebApi.Client.5.1.2.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Microsoft.AspNet.WebApi.Client.5.1.2/Microsoft.AspNet.WebApi.Client.5.1.2.nupkg -------------------------------------------------------------------------------- /packages/Microsoft.AspNet.WebApi.Client.5.1.2/lib/net45/System.Net.Http.Formatting.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Microsoft.AspNet.WebApi.Client.5.1.2/lib/net45/System.Net.Http.Formatting.dll -------------------------------------------------------------------------------- /packages/Microsoft.AspNet.WebApi.Client.5.1.2/lib/portable-wp8%2Bnetcore45%2Bnet45/System.Net.Http.Formatting.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Microsoft.AspNet.WebApi.Client.5.1.2/lib/portable-wp8%2Bnetcore45%2Bnet45/System.Net.Http.Formatting.dll -------------------------------------------------------------------------------- /packages/Microsoft.AspNet.WebApi.Client.5.2.2/Microsoft.AspNet.WebApi.Client.5.2.2.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Microsoft.AspNet.WebApi.Client.5.2.2/Microsoft.AspNet.WebApi.Client.5.2.2.nupkg -------------------------------------------------------------------------------- /packages/Microsoft.AspNet.WebApi.Client.5.2.2/lib/net45/System.Net.Http.Formatting.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Microsoft.AspNet.WebApi.Client.5.2.2/lib/net45/System.Net.Http.Formatting.dll -------------------------------------------------------------------------------- /packages/Microsoft.AspNet.WebApi.Client.5.2.2/lib/portable-wp8+netcore45+net45+wp81+wpa81/System.Net.Http.Formatting.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Microsoft.AspNet.WebApi.Client.5.2.2/lib/portable-wp8+netcore45+net45+wp81+wpa81/System.Net.Http.Formatting.dll -------------------------------------------------------------------------------- /packages/Microsoft.AspNet.WebApi.Core.5.1.2/Content/web.config.transform: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /packages/Microsoft.AspNet.WebApi.Core.5.1.2/Microsoft.AspNet.WebApi.Core.5.1.2.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Microsoft.AspNet.WebApi.Core.5.1.2/Microsoft.AspNet.WebApi.Core.5.1.2.nupkg -------------------------------------------------------------------------------- /packages/Microsoft.AspNet.WebApi.Core.5.1.2/lib/net45/System.Web.Http.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Microsoft.AspNet.WebApi.Core.5.1.2/lib/net45/System.Web.Http.dll -------------------------------------------------------------------------------- /packages/Microsoft.AspNet.WebApi.WebHost.5.1.2/Microsoft.AspNet.WebApi.WebHost.5.1.2.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Microsoft.AspNet.WebApi.WebHost.5.1.2/Microsoft.AspNet.WebApi.WebHost.5.1.2.nupkg -------------------------------------------------------------------------------- /packages/Microsoft.AspNet.WebApi.WebHost.5.1.2/lib/net45/System.Web.Http.WebHost.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Microsoft.AspNet.WebApi.WebHost.5.1.2/lib/net45/System.Web.Http.WebHost.dll -------------------------------------------------------------------------------- /packages/Microsoft.AspNet.WebApi.WebHost.5.1.2/lib/net45/System.Web.Http.WebHost.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | System.Web.Http.WebHost 5 | 6 | 7 | 8 | Provides a global for ASP.NET applications. 9 | 10 | 11 | 12 | 13 | 14 | Gets the global . 15 | 16 | 17 | Extension methods for 18 | 19 | 20 | Maps the specified route template. 21 | A reference to the mapped route. 22 | A collection of routes for the application. 23 | The name of the route to map. 24 | The route template for the route. 25 | 26 | 27 | Maps the specified route template and sets default route. 28 | A reference to the mapped route. 29 | A collection of routes for the application. 30 | The name of the route to map. 31 | The route template for the route. 32 | An object that contains default route values. 33 | 34 | 35 | Maps the specified route template and sets default route values and constraints. 36 | A reference to the mapped route. 37 | A collection of routes for the application. 38 | The name of the route to map. 39 | The route template for the route. 40 | An object that contains default route values. 41 | A set of expressions that specify values for routeTemplate. 42 | 43 | 44 | Maps the specified route template and sets default route values, constraints, and end-point message handler. 45 | A reference to the mapped route. 46 | A collection of routes for the application. 47 | The name of the route to map. 48 | The route template for the route. 49 | An object that contains default route values. 50 | A set of expressions that specify values for routeTemplate. 51 | The handler to which the request will be dispatched. 52 | 53 | 54 | A that passes ASP.NET requests into the pipeline and write the result back. 55 | 56 | 57 | Initializes a new instance of the class. 58 | The route data. 59 | 60 | 61 | Initializes a new instance of the class. 62 | The route data. 63 | The message handler to dispatch requests to. 64 | 65 | 66 | Provides code that handles an asynchronous task 67 | The asynchronous task. 68 | The HTTP context. 69 | 70 | 71 | A that returns instances of that can pass requests to a given instance. 72 | 73 | 74 | Initializes a new instance of the class. 75 | 76 | 77 | Provides the object that processes the request. 78 | An object that processes the request. 79 | An object that encapsulates information about the request. 80 | 81 | 82 | Gets the singleton instance. 83 | 84 | 85 | Provides the object that processes the request. 86 | An object that processes the request. 87 | An object that encapsulates information about the request. 88 | 89 | 90 | Provides a registration point for the simple membership pre-application start code. 91 | 92 | 93 | Registers the simple membership pre-application start code. 94 | 95 | 96 | Represents the web host buffer policy selector. 97 | 98 | 99 | Initializes a new instance of the class. 100 | 101 | 102 | Gets a value that indicates whether the host should buffer the entity body of the HTTP request. 103 | true if buffering should be used; otherwise a streamed request should be used. 104 | The host context. 105 | 106 | 107 | Uses a buffered output stream for the web host. 108 | A buffered output stream. 109 | The response. 110 | 111 | 112 | Provides the catch blocks used within this assembly. 113 | 114 | 115 | Gets the label for the catch block in System.Web.Http.WebHost.HttpControllerHandler.WriteBufferedResponseContentAsync. 116 | The label for the catch block in System.Web.Http.WebHost.HttpControllerHandler.WriteBufferedResponseContentAsync. 117 | 118 | 119 | Gets the label for the catch block in System.Web.Http.WebHost.HttpControllerHandler.WriteErrorResponseContentAsync. 120 | The label for the catch block in System.Web.Http.WebHost.HttpControllerHandler.WriteErrorResponseContentAsync. 121 | 122 | 123 | Gets the label for the catch block in System.Web.Http.WebHost.HttpControllerHandler.ComputeContentLength. 124 | The label for the catch block in System.Web.Http.WebHost.HttpControllerHandler.ComputeContentLength. 125 | 126 | 127 | Gets the label for the catch block in System.Web.Http.WebHost.HttpControllerHandler.WriteStreamedResponseContentAsync. 128 | The label for the catch block in System.Web.Http.WebHost.HttpControllerHandler.WriteStreamedResponseContentAsync. 129 | 130 | 131 | Gets the label for the catch block in System.Web.Http.WebHost.WebHostExceptionCatchBlocks.HttpWebRoute.GetRouteData. 132 | The catch block in System.Web.Http.WebHost.WebHostExceptionCatchBlocks.HttpWebRoute.GetRouteData. 133 | 134 | 135 | -------------------------------------------------------------------------------- /packages/Newtonsoft.Json.5.0.6/Newtonsoft.Json.5.0.6.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Newtonsoft.Json.5.0.6/Newtonsoft.Json.5.0.6.nupkg -------------------------------------------------------------------------------- /packages/Newtonsoft.Json.5.0.6/lib/net20/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Newtonsoft.Json.5.0.6/lib/net20/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /packages/Newtonsoft.Json.5.0.6/lib/net35/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Newtonsoft.Json.5.0.6/lib/net35/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /packages/Newtonsoft.Json.5.0.6/lib/net40/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Newtonsoft.Json.5.0.6/lib/net40/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /packages/Newtonsoft.Json.5.0.6/lib/net45/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Newtonsoft.Json.5.0.6/lib/net45/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /packages/Newtonsoft.Json.5.0.6/lib/netcore45/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Newtonsoft.Json.5.0.6/lib/netcore45/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /packages/Newtonsoft.Json.5.0.6/lib/portable-net40%2Bsl4%2Bwp7%2Bwin8/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Newtonsoft.Json.5.0.6/lib/portable-net40%2Bsl4%2Bwp7%2Bwin8/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /packages/Newtonsoft.Json.5.0.6/lib/portable-net45%2Bwp80%2Bwin8/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Newtonsoft.Json.5.0.6/lib/portable-net45%2Bwp80%2Bwin8/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /packages/Newtonsoft.Json.6.0.4/Newtonsoft.Json.6.0.4.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Newtonsoft.Json.6.0.4/Newtonsoft.Json.6.0.4.nupkg -------------------------------------------------------------------------------- /packages/Newtonsoft.Json.6.0.4/lib/net20/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Newtonsoft.Json.6.0.4/lib/net20/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /packages/Newtonsoft.Json.6.0.4/lib/net35/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Newtonsoft.Json.6.0.4/lib/net35/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /packages/Newtonsoft.Json.6.0.4/lib/net40/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Newtonsoft.Json.6.0.4/lib/net40/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /packages/Newtonsoft.Json.6.0.4/lib/net45/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Newtonsoft.Json.6.0.4/lib/net45/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /packages/Newtonsoft.Json.6.0.4/lib/netcore45/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Newtonsoft.Json.6.0.4/lib/netcore45/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /packages/Newtonsoft.Json.6.0.4/lib/portable-net40+sl5+wp80+win8+wpa81/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Newtonsoft.Json.6.0.4/lib/portable-net40+sl5+wp80+win8+wpa81/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /packages/Newtonsoft.Json.6.0.4/lib/portable-net45+wp80+win8+wpa81/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjoudeh/WebApiHMACAuthentication/adb24234389f55962b1a68f53b091add2029e4a7/packages/Newtonsoft.Json.6.0.4/lib/portable-net45+wp80+win8+wpa81/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /packages/Newtonsoft.Json.6.0.4/tools/install.ps1: -------------------------------------------------------------------------------- 1 | param($installPath, $toolsPath, $package, $project) 2 | 3 | # open json.net splash page on package install 4 | # don't open if json.net is installed as a dependency 5 | 6 | try 7 | { 8 | $url = "http://james.newtonking.com/json" 9 | $dte2 = Get-Interface $dte ([EnvDTE80.DTE2]) 10 | 11 | if ($dte2.ActiveWindow.Caption -eq "Package Manager Console") 12 | { 13 | # user is installing from VS NuGet console 14 | # get reference to the window, the console host and the input history 15 | # show webpage if "install-package newtonsoft.json" was last input 16 | 17 | $consoleWindow = $(Get-VSComponentModel).GetService([NuGetConsole.IPowerConsoleWindow]) 18 | 19 | $props = $consoleWindow.GetType().GetProperties([System.Reflection.BindingFlags]::Instance -bor ` 20 | [System.Reflection.BindingFlags]::NonPublic) 21 | 22 | $prop = $props | ? { $_.Name -eq "ActiveHostInfo" } | select -first 1 23 | if ($prop -eq $null) { return } 24 | 25 | $hostInfo = $prop.GetValue($consoleWindow) 26 | if ($hostInfo -eq $null) { return } 27 | 28 | $history = $hostInfo.WpfConsole.InputHistory.History 29 | 30 | $lastCommand = $history | select -last 1 31 | 32 | if ($lastCommand) 33 | { 34 | $lastCommand = $lastCommand.Trim().ToLower() 35 | if ($lastCommand.StartsWith("install-package") -and $lastCommand.Contains("newtonsoft.json")) 36 | { 37 | $dte2.ItemOperations.Navigate($url) | Out-Null 38 | } 39 | } 40 | } 41 | else 42 | { 43 | # user is installing from VS NuGet dialog 44 | # get reference to the window, then smart output console provider 45 | # show webpage if messages in buffered console contains "installing...newtonsoft.json" in last operation 46 | 47 | $instanceField = [NuGet.Dialog.PackageManagerWindow].GetField("CurrentInstance", [System.Reflection.BindingFlags]::Static -bor ` 48 | [System.Reflection.BindingFlags]::NonPublic) 49 | $consoleField = [NuGet.Dialog.PackageManagerWindow].GetField("_smartOutputConsoleProvider", [System.Reflection.BindingFlags]::Instance -bor ` 50 | [System.Reflection.BindingFlags]::NonPublic) 51 | if ($instanceField -eq $null -or $consoleField -eq $null) { return } 52 | 53 | $instance = $instanceField.GetValue($null) 54 | if ($instance -eq $null) { return } 55 | 56 | $consoleProvider = $consoleField.GetValue($instance) 57 | if ($consoleProvider -eq $null) { return } 58 | 59 | $console = $consoleProvider.CreateOutputConsole($false) 60 | 61 | $messagesField = $console.GetType().GetField("_messages", [System.Reflection.BindingFlags]::Instance -bor ` 62 | [System.Reflection.BindingFlags]::NonPublic) 63 | if ($messagesField -eq $null) { return } 64 | 65 | $messages = $messagesField.GetValue($console) 66 | if ($messages -eq $null) { return } 67 | 68 | $operations = $messages -split "==============================" 69 | 70 | $lastOperation = $operations | select -last 1 71 | 72 | if ($lastOperation) 73 | { 74 | $lastOperation = $lastOperation.ToLower() 75 | 76 | $lines = $lastOperation -split "`r`n" 77 | 78 | $installMatch = $lines | ? { $_.StartsWith("------- installing...newtonsoft.json ") } | select -first 1 79 | 80 | if ($installMatch) 81 | { 82 | $dte2.ItemOperations.Navigate($url) | Out-Null 83 | } 84 | } 85 | } 86 | } 87 | catch 88 | { 89 | # stop potential errors from bubbling up 90 | # worst case the splash page won't open 91 | } 92 | 93 | # yolo -------------------------------------------------------------------------------- /packages/repositories.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | --------------------------------------------------------------------------------