An implementation of OWIN middleware and ASP.NET Identity for LTI is available on Codeplex.
The Complete Story
Microsoft’s ASP.NET Identity now uses OWIN. Anders Abel has a great series of articles explaining the interaction between OWIN middleware and ASP.NET Identity. In this post, I will dig into my version of OWIN middleware for LTI and how to use it in an ASP.NET MVC application using ASP.NET Identity.
OWIN and One-Legged Authentication
LTI uses one-legged OAuth 1.0 authentication. One-legged refers to fact that the application (i.e. Tool Consumer) is authorized directly by the service provider (i.e. Tool Provider). There is no token exchange or third party authorization service.
All of the OWIN middleware that Microsoft writes (and all of the samples I have found) show three-legged authorizations such as that used by Google and Facebook. My OWIN middleware for LTI implements one-legged authentication.
Let’s look at the AuthenticationHandler first. LtiAuthenticationHandler inherits from the abstract Microsoft.Owin.Security.Infrastructure.AuthenticationHandler and implements AuthenticateCoreAsync() and InvokeAsync(). AuthenticateCoreAsync is never used (it only comes into play with three-legged schemes) and simply returns null.
The real work is done inside InvokeAsync() which is invoked on each request. The first step is to quickly determine if the request is authenticated with LTI.
If it is, the request is parsed into an LtiRequest object and then passed to the application so the application can look up the OAuth secret.
If the LtiRequest signature is valid, then the LtiRequest is passed back to the application again so the application can sign in using an application identity.
That’s really it for the OWIN pipeline. At this point, the request is authenticated and the application can provide the appropriate services (such as display the tool).
Next, let’s look at how the OWIN middleware talks to the application layer as shown above.
All of Microsoft’s OWIN middleware use something called a “Provider” to talk to the application layer. The “Provider” is instantiated when the middleware is created.
LtiAuthenticationProvider supports two events: Authenticate which is invoked just before LtiAuthenticationHandler checks the OAuth signature, Authenticated which is invoked just after. The application can hook into those events and perform any application layer actions required such as looking things up in the application database.
LtiAuthenticationProvider also supports an “event” called GenerateUserName, but this is really used by another application layer method that signs in the user. More on that later.
Everything shown above is in the OWIN middleware for LTI library called LtiLibrary.Owin.Security.Lti. This library is not tied to ASP.NET can can even be used by console apps.
Now let’s look at what goes on in the application layer, namely an MVC Tool Provider.
Startup.Auth.cs is where the MVC app pulls in the appropriate OWIN middleware. When you start a new ASP.NET Web App in Visual Studio, the application will be setup to use Microsoft’s CookieAuthentication OWIN middleware and the main authentication scheme.
To add support for LTI authentication, simply add the LtiAuthentication middleware.
Notice in this example, the OnAuthenticate event is handled by a lamda expression which only recognizes the OAuth key “12345” and returns “secret”. In a real application, you would look up the secret in a database.
OnAuthenticated and OnGenerateUserName use handlers in the SecurityHandler helper class. This is a helper class I wrote to ease the implementation in a typical MVC app. SecurityHandler.OnAuthenticated looks up the matching local user account for the user in the LTI request and signs them in. If a matching account cannot be found, one is created using the username created by SecurityHandler.OnGenerateUserName.
Peek at a Real-ish App
I’ve updated the sample Provider app to use the new OWIN middleware for LTI. As you might expect, the handlers in Startup.Auth.cs are a bit more complex. OnAuthenticate performs an extra security check on the LTI request, and then looks up the OAuth secret in the database.
OnAuthenticated records the LtiRequest in the database, then creates an Outcome if needed to handle future simple outcomes interactions with the Tool Consumer. The IDs of both objects are stored as claims in the application user identity.
Prior to OWIN middleware and Microsoft Identity, it was rather tricky to authenticate LTI requests and connect the external user with a local user. With OWIN middleware, it is easy to integrate with Microsoft Identity and make use of Claims to store LTI information relevant to the application.