OWIN multi-app bearer token authentication

Viewed 11324

I want to make a modification to the default single page application template for ASP.NET in VS 2013, which currently uses bearer token authentication. The sample uses app.UseOAuthBearerTokens to create both the token server and the middleware to validate tokens for requests in the same app.

What I'd like to do is leave that in place, but add a second application (bound in IIS to the same domain, different path - e.g. /auth/* for the authentication server, and /app1/* for the app). For the second app, I want it to accept tokens issued by the authentication server in the first app. How could this be accomplished? I have tried the following in Startup.Auth.cs just going off of the code in UseOAuthBearerTokens, but I get 401 responses to any requests with the [Authorize] attribute:

public partial class Startup
{
    static Startup()
    {
        PublicClientId = "self";

        UserManagerFactory = () => new UserManager<IdentityUser>(new UserStore<IdentityUser>());

        OAuthOptions = new OAuthAuthorizationServerOptions
        {
            //TokenEndpointPath = new PathString("/Token"),
            Provider = new ApplicationOAuthProvider(PublicClientId, UserManagerFactory),
            //AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
            //AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
            AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
            AuthenticationType = "ExternalBearer",
            AllowInsecureHttp = true,
        };
    }

    public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }

    public static Func<UserManager<IdentityUser>> UserManagerFactory { get; set; }

    public static string PublicClientId { get; private set; }

    // For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
    public void ConfigureAuth(IAppBuilder app)
    {
        //// Enable the application to use a cookie to store information for the signed in user
        //// and to use a cookie to temporarily store information about a user logging in with a third party login provider
        //app.UseCookieAuthentication(new CookieAuthenticationOptions());
        //app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        OAuthBearerAuthenticationOptions bearerOptions = new OAuthBearerAuthenticationOptions();
        bearerOptions.AccessTokenFormat = OAuthOptions.AccessTokenFormat;
        bearerOptions.AccessTokenProvider = OAuthOptions.AccessTokenProvider;
        bearerOptions.AuthenticationMode = OAuthOptions.AuthenticationMode;
        bearerOptions.AuthenticationType = OAuthOptions.AuthenticationType;
        bearerOptions.Description = OAuthOptions.Description;
        bearerOptions.Provider = new CustomBearerAuthenticationProvider();
        bearerOptions.SystemClock = OAuthOptions.SystemClock;
        OAuthBearerAuthenticationExtensions.UseOAuthBearerAuthentication(app, bearerOptions);
    }
}

public class CustomBearerAuthenticationProvider : OAuthBearerAuthenticationProvider
    {
        public override Task ValidateIdentity(OAuthValidateIdentityContext context)
        {
            var claims = context.Ticket.Identity.Claims;
            if (claims.Count() == 0 || claims.Any(claim => claim.Issuer != "LOCAL AUTHORITY"))
                context.Rejected();
            return Task.FromResult<object>(null);
        }
    }

Obviously I'm missing the part where the second app has some way of validating that the tokens came from the first app. A public signing key of some kind?

This is just for a proof of concept.

Edit: The machine key suggestion worked well enough for the POC demo, and it's good to know there are AS implementation options that support other key scenarios.

I was able to generate a DEMO key (do not use for production) using this site: http://aspnetresources.com/tools/machineKey

And placed the result under the <system.web> element in the web.config of each app hosted in the IIS site. I also had to remove some of the AS-specific config options in the Startup class of the resource server.

4 Answers
Related