Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WsFederation authentication in Service Fabric Owin Pipeline not working

G'day!

I haven't seen much on this because its all very new at the time of this writing. I am trying to write a service fabric application that serves a web app (html/js) after the user has been authenticated via ACS. I can easily get this to work with OWIN in a non service fabric environment, i.e. a traditional Asp Net application behind IIS. I'm trying to use token authentication with Azure Access Control.

So something to do with the fact that I am now using service fabric has changed the way OWIN works? Below is my OWIN ConfigureApp() function within my Startup.cs in my service fabric application:

public static void ConfigureApp(IAppBuilder appBuilder)
    {                           
        appBuilder.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

        appBuilder.UseCookieAuthentication(new CookieAuthenticationOptions());

        appBuilder.UseWsFederationAuthentication(
            new WsFederationAuthenticationOptions
            {
                Wtrealm = _realm,
                MetadataAddress = _acsXmlMetaDataUrl
            });

        // Configure Web API for self-host. 
        HttpConfiguration config = new HttpConfiguration();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        appBuilder.UseWebApi(config);
    }

Notice how I inject the WsFederation middleware before the web api middleware that will eventually be used to serve my browser html/js application. Now when this launches and I do a sanity test like navigating to a REST url my content is served instantly rather than being redirected to Azure Access Control to sign in and get an auth token. In my traditional Asp Net application with the same OWIN configuration I am indeed redirected to Azure Access Control before any resources are served.

So my question is how do I inject WsFed middleware into the OWIN pipeline such that this will work in a service fabric context?

Any assistance would be much appreciated, thank you for your time!

like image 445
Mil Avatar asked Aug 11 '16 17:08

Mil


1 Answers

I don't know why this code is working for MVC and not for Service Fabric. I had the same issue, but I found a way to make it work for SF.

This article gives a tutorial.

Basically, in your code, you're not telling it to authenticate. You're setting everything up but you're not starting it.

app.Map("/login", map =>
            {
                map.Run(async ctx =>
                {
                    if (ctx.Authentication.User == null ||
                        !ctx.Authentication.User.Identity.IsAuthenticated)
                    {
                        ctx.Response.StatusCode = 401;
                    }
                    else
                    {
                        ctx.Response.Redirect("/");
                    }
                });
            });

app.Run(async ctx =>
            {
                var user = ctx.Authentication.User;
                var response = ctx.Response;

                response.ContentType = "text/html";

                if (user != null && user.Identity.IsAuthenticated)
                {
                    await response.WriteAsync(string.Format("<h2>{0}</h2>",
                        user.Claims.First().Issuer));

                    await response.WriteAsync("<dl>");
                    foreach (var claim in user.Claims)
                    {
                        await response.WriteAsync(string.Format(
                            "<dt>{0}</dt> <dd>{1}</dd>",
                            claim.Type,
                            claim.Value));
                    }
                    await response.WriteAsync("</dl>");
                }
                else
                {
                    await ctx.Response.WriteAsync("<h2>anonymous</h2>");
                }
            });

When you're accessing a link on your website, the code in app.Run starts executing to check if you're logged in. If you're not, in this case, it will write "anonymous" on the page instead of loading your content. To authenticate, go to yourwesite/login and it will redirect you to whatever auth provider you have in the configuration.

Conclusion: add the login, logout and app.Run snippets, give it a final tweak if you have to and that should be it.

like image 89
Maria Stoica Avatar answered Oct 30 '22 03:10

Maria Stoica