IdentityServer 2.0.1 on Mono

At my current gig we use IdentityServer to help us manage security for our API. Our aim is to run quite a few virtual machines in the cloud, so pricing is key. Linux machines are much cheaper than Windows boxes, so getting the IdentityServer running happily on Mono is crucial.

Requirements

This blog assumes you are running a Debian based Linux distro. This example specifically is using Debian/Jessie. The concepts should easily translate though to other distributions including Ubunutu.

For quick iterations, I would also recommend running a local VM via Vagrant or Docker. It makes testing from scratch much easier. (Make sure to open up port 44319 if you go down this route!)

Installing Mono

Installing Mono can be surprisingly tricky. The package references change from time to time. The following works at the time of the blog posting:

vagrant@vagrant-debian-jessie:~$ mono --version
Mono JIT compiler version 4.0.4 (Stable 4.0.4.1/5ab4c0d Tue Aug 25 23:11:51 UTC 2015)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
	TLS:           __thread
	SIGSEGV:       altstack
	Notifications: epoll
	Architecture:  amd64
	Disabled:      none
	Misc:          softdebug
	LLVM:          supported, not enabled.
	GC:            sgen

Installing DNX (beta7)

Use the following (taken from the Docker repo) to install DNX beta7:

(Run each command as root)

root@vagrant-debian-jessie:~# dnx --version
Microsoft .NET Execution environment
 Version:      1.0.0-beta7-15532
 Type:         Mono
 Architecture: x64
 OS Name:      Linux

Installing libuv

Libuv is the node.js asynchronous I/O library that Kestrel is based off of. Kestrel needs this to serve the IdentityServer over HTTP.

(Run each command as root)

Installing IDP

We are going to take a simple example from the IdentityServer Samples repo and start it up. There are a few minor changes that need to be made, so make sure to read the last section before trying to start the identity server.

(Run as root)

Now we need to edit project.json to add the Kestrel package and a command to run Kestrel.

Add a dependency for Kestrel so that your dependencies look like this:

  "dependencies": {
    "Microsoft.AspNet.Server.Kestrel": "1.0.0-beta7",
    "Microsoft.AspNet.Server.IIS": "1.0.0-beta7",
    "Microsoft.AspNet.Server.WebListener": "1.0.0-beta7",
    "Microsoft.Owin": "3.0.1",
    "Microsoft.AspNet.DataProtection": "1.0.0-beta7",
    "Microsoft.AspNet.Owin": "1.0.0-beta7",
    "IdentityServer3": "2.0.1"
  },

Also add a command to start Kestrel so that your commands look like this:

  "commands": {
    "web": "Microsoft.AspNet.Hosting --config hosting.ini",
    "kestrel": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:44319"
  },

Finally we need to edit Startup.cs.

using Microsoft.AspNet.Builder;
using Microsoft.Framework.DependencyInjection;
using System.Security.Cryptography.X509Certificates;
using IdentityServer3.Core.Configuration;
using Microsoft.Dnx.Runtime;

namespace IdentityServerAspNet5
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDataProtection();
        }

        public void Configure(IApplicationBuilder app, IApplicationEnvironment env)
        {
            var certFile = env.ApplicationBasePath + "/idsrv3test.pfx";

            var idsrvOptions = new IdentityServerOptions
            {
                Factory = new IdentityServerServiceFactory()
                                .UseInMemoryUsers(Users.Get())
                                .UseInMemoryClients(Clients.Get())
                                .UseInMemoryScopes(Scopes.Get()),
                RequireSsl = false,
                SigningCertificate = new X509Certificate2(certFile, "idsrv3test")
            };

            app.UseIdentityServer(idsrvOptions);
        }
    }
}

I changed the path for the pfx file so that Linux was happy with it, and I added the RequireSsl flag to make testing easier up front. You’ll of course want to take this out later!

Running the IDP

Finally we are ready to start the identity server.

Simply run dnx kestrel and you should be set!

root:/var/lib/dnx/.../IdentityServerAspNet5# dnx kestrel

You can now browse to http://localhost:44319 to see the welcome page of the application.

IdentityServer 2.0.1 on Mono

4 thoughts on “IdentityServer 2.0.1 on Mono

    1. ryan1234 says:

      We have a Web API on DNX beta7 that works with the IdentityServer. Currently we’re doing more or less the following:

      public void Configure(IApplicationBuilder app, ILoggerFactory loggingFactory, IApplicationEnvironment env, IHostingEnvironment hostEnv)
      {
      ...
          string idpHost = _configuration["IDP_HOST"];
          _idpSigningCertificate = new X509Certificate2(env.ApplicationBasePath + "/cert.pfx", "test");
          _idpIssuerName = $"{_scheme}://{idpHost}/core";
          _idpIssuerAudience = _idpIssuerName + "/resources";
      
          app.UseOAuthBearerAuthentication(options =>
          {
              options.AutomaticAuthentication = true;
              options.SecurityTokenValidators = new []
                  { new SessionTokenValidator(app.ApplicationServices.GetService<ISessionProvider>(), loggingFactory.CreateLogger<SessionTokenValidator>()) };
          });
      ...
      }
      
      public void ConfigureServices(IServiceCollection services)
      {
      ...
          services.AddAuthentication();
          services.AddSingleton((provider) => new JwtValidator(_idpIssuerName, _idpIssuerAudience, _idpSigningCertificate));
      ...
      }
      

      We are consuming the JWT’s server side and doing some manual work around processing them. We’ve had to roll our own XYZ several times because of issues with Mono.

      Hope that helps?

      1. Ah you’re using DNX. I’m pretty new to IdSrv, how does your WebAPI know where to connect to your IdSrv service? I don’t see it in your UseOAuthBearerAuthentication MW

      2. ryan1234 says:

        We have a single page application so we’re sending users that aren’t authenticated over to the IDP on the front end (via Javascript). Then after they login, a bunch of redirects happen and eventually we have a JWT we can process and use.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s