JWT and CORS for cross-site API authentication

In my previous post on avoiding monolithic applications, I mentioned that JSON Web Tokens and CORS could be used to access protected web apis on other sites. Here’s the why and how. The requirement for accessing protected web apis on other sites Ideally (my ideal), each application that is developed would be relatively compact and include only the functionality that is unique to that application. Functionality from other applications would be provided by APIs in those applications and generic functionality (e.g. a staff lookup) would be provided by an application (or multiple) that all other applications can access (almost like a CDN for functionality). ...

April 10, 2015 · 5 min

HTTP Referer / Referrer and HTTPS

The rule for whether the HTTP referrer (incorrectly spelt in the original spec, so forever incorrectly spelt in headers) is sent along with a request has always been a bit odd. If the referring site uses https, the referrer isn’t sent, unless the site linked too also uses https. It isn’t sent because the originating URL may contain sensitive information but the browser happily sends the sensitive URL to any other site if it uses https. ...

March 27, 2015 · 2 min

Updated error handling

In Managing Errors in MVC I got close to having record level error handling working as I wanted but I had to create a view for each error when usually the error is a single line of text that could be stored in a config file. Based on my original code and http://weblogs.asp.net/gunnarpeipman/asp-net-mvc-3-creating-httpstatuscoderesult-with-view-based-body Helpers\ExceptionHelper.cs using System; using System.Linq.Expressions; using System.Net; using System.Web; using System.Web.Mvc; using System.Web.Routing; using System.Collections; using System.Collections.Generic; namespace MyProject { public class ExceptionHelper : ViewResult { private ExceptionName \_exceptionName; private HttpStatusCode? \_statusCode; private bool? \_logException; public ExceptionHelper(ExceptionName exceptionName, HttpStatusCode? statusCode = null, bool? logException = null) { \_exceptionName = exceptionName; \_statusCode = statusCode; \_logException = logException; } public override void ExecuteResult(ControllerContext context) { HttpStatusCode returnStatusCode = HttpStatusCode.BadRequest; bool returnLogException = true; string ExceptionDescription = string.Empty; string sViewName = "Exceptions/\_GenericException"; var httpContext = context.HttpContext; var response = httpContext.Response; // get the defaults for this exception ExceptionActions theseExceptionActions; if (ExceptionDefaults.TryGetValue(\_exceptionName, out theseExceptionActions)) { if (theseExceptionActions.UseCustomView) { sViewName = "Exceptions/" + \_exceptionName.ToString(); } ExceptionDescription = theseExceptionActions.ExceptionDescription; if (null == \_statusCode) { returnStatusCode = theseExceptionActions.StatusCode; } else { returnStatusCode = (HttpStatusCode)\_statusCode; } if (null == \_logException) { returnLogException = theseExceptionActions.LogException; } else { returnLogException = (bool)\_logException; } } response.StatusCode = (int)returnStatusCode; response.StatusDescription = ExceptionDescription; ViewBag.ExceptionDescription = ExceptionDescription; ViewName = sViewName; if (returnLogException) { // log the exception Elmah.ErrorSignal.FromCurrentContext().Raise(new Exception(\_exceptionName.ToString())); } base.ExecuteResult(context); } public enum ExceptionName { DataNotValid, NoPermissionToManageThisPerson, NoPermissionToManageThisProject, RecordNotFound, RecordNotSpecified }; /// <summary> /// Most exceptions will have UseCustomView=false, so the ExceptionDescription will be used for the error message that is displayed in the \_GenericException view /// If a custom view is required, it will have the name of the exception /// </summary> public struct ExceptionActions { public bool UseCustomView; public HttpStatusCode StatusCode; public bool LogException; public string ExceptionDescription; } public static Dictionary<ExceptionName, ExceptionActions\> ExceptionDefaults = new Dictionary<ExceptionName, ExceptionActions\>() { {ExceptionName.DataNotValid, new ExceptionActions {UseCustomView = false, StatusCode = HttpStatusCode.BadRequest, LogException = true, ExceptionDescription = "Data provided was not valid"}}, {ExceptionName.NoPermissionToManageThisPerson, new ExceptionActions {UseCustomView = false, StatusCode = HttpStatusCode.Forbidden, LogException = false, ExceptionDescription = "You don't have permission to manage this person"}}, {ExceptionName.NoPermissionToManageThisProject, new ExceptionActions {UseCustomView = false, StatusCode = HttpStatusCode.Forbidden, LogException = false, ExceptionDescription = "You don't have permission to manage this project"}}, {ExceptionName.RecordNotFound, new ExceptionActions {UseCustomView = false, StatusCode = HttpStatusCode.NotFound, LogException = false, ExceptionDescription = "Record was not found"}}, {ExceptionName.RecordNotSpecified, new ExceptionActions {UseCustomView = false, StatusCode = HttpStatusCode.BadRequest, LogException = false, ExceptionDescription = "Record not specified - one or more identifiers were missing"}}, }; } } Views\Shared\Exceptions\_GenericException.cshtml ...

February 10, 2015 · 3 min

Catching up on accessibility techniques

Concern over whether my modal dialogs are accessible led on this series of articles: A great starting point if you don’t know why your sites should be accessible: http://alistapart.com/article/reframing-accessibility-for-the-web https://www.marcozehe.de/2015/02/05/advanced-aria-tip-2-accessible-modal-dialogs/ http://accessibility.oit.ncsu.edu/training/aria/modal-window/version-2/ http://www.paciellogroup.com/blog/2014/09/web-components-punch-list/ The very dry formal stuff http://www.w3.org/TR/wai-aria/ Some examples http://www.w3.org/WAI/PF/aria-practices/#aria_ex These link to real examples e.g. http://www.oaa-accessibility.org/examplep/grid1/ http://www.paciellogroup.com/resources/ http://www.paciellogroup.com/blog/2015/01/the-browser-accessibility-tree/ http://www.paciellogroup.com/blog/2014/12/using-aria-describedby-to-provide-helpful-form-hints/ http://www.paciellogroup.com/blog/2014/08/using-the-tabindex-attribute/ Screen readers http://webaim.org/projects/screenreadersurvey5/ Free screen reader http://www.nvaccess.org/ (donate if you can) You can change the voice from the notifications area and Preferences > Synthesizer

February 9, 2015 · 1 min

Getting a WebApi2 controller to return HttpStatusCode.Forbidden

If your WebApi controller is checking that the user has permission to view a particular record and it turns out that they don’t then you will want to return a status of Forbidden, rather than Unauthorized as discussed here: http://stackoverflow.com/questions/238437/why-does-authorizeattribute-redirect-to-the-login-page-for-authentication-and-au/5844884#5844884 (You might also want to override the AuthorizeAttribute class as described there) WebApi2 controllers now return IHttpActionResult rather than HttpResponseMessage (see http://stackoverflow.com/questions/21758615/why-should-i-use-ihttpactionresult-instead-of-httpresponsemessage). It’s easy to return a result from the System.Web.Http.Results Namespace e.g. return Unauthorized(); But the namespace doesn’t contain Forbidden, so instead use: ...

January 14, 2015 · 1 min

Managing errors in MVC

Error logging Elmah seems to be the most popular tool for error logging but the Elmah website doesn’t have much up to date information on how to get started. To get Elmah installed, secured and logging to somewhere more permanent than keeping the log in-memory, follow this guide: http://www.erikojebo.se/Code/Details/607 Error handling Elmah just logs error, it doesn’t help the user. So you also need to handle the errors, which this article covers nicely: https://www.simple-talk.com/dotnet/asp.net/handling-errors-effectively-in-asp.net-mvc/ ...

January 14, 2015 · 4 min

ASP.Net MVC and URLs ending in a decimal or float

In your MVC site, you might want this URL to purchase 2.5 kilos of cheese for you https://www.mysite.com/cheese/purchase/2.5 Unfortunately it won’t be recognised as a route to the purchase method within the cheese controller. The good news is that this will work: https://www.mysite.com/cheese/purchase/2.5/ Note the extra slash at the end This is an explanation why: http://stackoverflow.com/questions/21387974/why-is-my-web-api-method-with-double-args-not-getting-called It’s fairly unusual to have a valid reason for a URL like this. If you want to pass a parameter that’s a float, it’s more likely that you would want to post the data.

November 14, 2014 · 1 min

What could go wrong with a simple jQuery value selector?

In this case the value selector is used like this: $(“.pPlacement select option\[value='” + PlacementId + “‘\]”).attr(‘selected’, true); When PlacementId changes from a number to text and that text then contains an apostrophe, then it breaks! To explain the code above, thee’s a dropdown list of placements and from somewhere we have the value of the one that we want to have as the selected option. The selector picks the option with the value equal to PlacementId and selects it. ...

November 7, 2014 · 1 min

Adding a stylesheet to an iframe

If your page contains an iframe and you need to dynamically add a stylesheet, you can do it like this: var $head = $(“#myIframe”).contents().find(“head”); $head.append($(“<link/>”, { rel: “stylesheet”, href: window.location.protocol + “//” + window.location.host + “/mystyles/mystylesheet.css”, type: “text/css” })); Even if the domain for the stylesheet is the same as the parent page and the iframe, you still need to include the host address of the stylesheet (the protocol and host bit) or IE will ignore it. from http://stackoverflow.com/questions/6960406/add-css-to-iframe and http://css-tricks.com/snippets/javascript/get-url-and-url-parts-in-javascript/

September 22, 2014 · 1 min

EntityFramework Reverse POCO Generator and Views

EntityFramework’s own tool to generate a model from a database is slow and buggy. It’s particularly a problem if you update your database (change table names, field names etc.). EntityFramework Reverse POCO Generator is a great, lightweight replacement – it’s fast, configurable and just works. Also, the entities created can be the same as those created by the built in tool, so it is possible to switch to it part way through developing a project. ...

September 20, 2014 · 1 min