2
votes

I have added a Web API service to a 'legacy' MVC project (not vNext), still using Membership and the forms authentication module. All OK, until I decided to make the web api a mobile service using the latest SDKs for Azure App Services for Mobile.

I have so far narrowed the problem to this

  //app.UseAppServiceAuthentication(new AppServiceAuthenticationOptions()
            //{

            //    SigningKey = CloudConfigurationManager.GetSetting("authSigningKey"),
            //    ValidAudiences = new[] { CloudConfigurationManager.GetSetting("authAudience") },
            //    ValidIssuers = new[] { CloudConfigurationManager.GetSetting("authIssuer") },
            //    TokenHandler = GlobalConfiguration.Configuration.GetAppServiceTokenHandler()
            //});

This changes the rest of the app so that MVC + forms auth doesn't work. Running out of time to research the problem. Any clues??

1
Got the same problem. Could you find a solution?Florian

1 Answers

1
votes

The following solution is working for me: In your Startup register call UseCookieAuthentication, UseExternalSignInCookie or UseOAuthAuthorizationServer before calling UseAppServiceAuthentication.

Second step: Add the following class to your project:

private sealed class CustomAppServiceAuthenticationMiddleware : AppServiceAuthenticationMiddleware
{
    private readonly ILogger _logger;

    public CustomAppServiceAuthenticationMiddleware(OwinMiddleware next, IAppBuilder appBuilder, AppServiceAuthenticationOptions options) : base(next, appBuilder, options)
    {
        _logger = (ILogger)GetType().BaseType.GetField("logger", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(this);
    }

    protected override AuthenticationHandler<AppServiceAuthenticationOptions> CreateHandler()
    {
        return new AppServiceAuthenticationHandler(_logger);
    }

    public override Task Invoke(IOwinContext context)
    {
        string logLine = $"AppServiceAuthMiddleware: {context.Request.Path}";

        if (context.Request.Headers.TryGetValue("Authorization", out var values))
            logLine += $"; Authorization: {values.First().Split(' ').FirstOrDefault()}";
        if (context.Request.Headers.TryGetValue("X-ZUMO-AUTH", out values))
            logLine += $"; X-ZUMO-AUTH: {values.First()}";

        _logger.WriteVerbose(logLine);
        Debug.WriteLine(logLine);

        if (IsZumoAuth(context))
        {
            return base.Invoke(context);
        }

        return Next.Invoke(context);
    }

    private bool IsZumoAuth(IOwinContext context)
    {
        return context.Request.Headers.ContainsKey("X-ZUMO-AUTH");
    }
}

Thrid step: Replace the app.UseAppServiceAuthentication with the following:

        app.Use(typeof(CustomAppServiceAuthenticationMiddleware), app, new AppServiceAuthenticationOptions
        {
            SigningKey = ...,
            ValidAudiences = ...,
            ValidIssuers = ...,
            TokenHandler = ...
        });

This will the owin pipline make call the AppServiceAuthenticationMiddleware just for ZUMO-AUTH auth.

I've got a mixed web & mobile app. With this approach the membership auth on the web app is working. In the app, some custom oauth (refresh token based) plus the azure auth (facebook, google, ...) is working too. All that within the same asp.net application.