2

I have a web app MVC,using auth0 owin regular web app cookie based authentication.

This web app also has webapis which is used internally in the application. However i have a requirement to call this webapis from outside the application. So i created a restclient and tried to implement jwtbearerauthentication in application (but cookie based on authentication still in place).

Now when i call the webapi from other application it validates the bearer token gives no error however it redirects to login page due to cookie based authentication.

startup file:

 public partial class Startup
{
    private IPlatform platform;
    public void ConfigureAuth(IAppBuilder app, IPlatform p, IContainer container)
    {
        platform = p;


        // Enable the application to use a cookie to store information for the signed in user
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),
            ExpireTimeSpan = System.TimeSpan.FromDays(2),
            SlidingExpiration = true
        });

        // Use a cookie to temporarily store information about a user logging in with a third party login provider
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
        var provider = new Auth0.Owin.Auth0AuthenticationProvider
        {
            OnReturnEndpoint = (context) =>
            {
                // xsrf validation
                if (context.Request.Query["state"] != null && context.Request.Query["state"].Contains("xsrf="))
                {
                    var state = HttpUtility.ParseQueryString(context.Request.Query["state"]);
                    AntiForgery.Validate(context.Request.Cookies["__RequestVerificationToken"], state["xsrf"]);
                }

                return System.Threading.Tasks.Task.FromResult(0);
            },
            OnAuthenticated = (context) =>
            {
                var identity = context.Identity;
                //Add claims
                var authenticationManager = container.Resolve<IAuthenticationManager>();
                authenticationManager.AddClaims(identity);

                if (context.Request.Query["state"] != null)
                {
                    authenticationManager.AddReturnUrlInClaims(identity, context.Request.Query["state"]);
                }

                return System.Threading.Tasks.Task.FromResult(0);
            }
        };

        var issuer = "https://" + ConfigurationManager.AppSettings["auth0:Domain"] + "/";
        var audience = ConfigurationManager.AppSettings["auth0:ClientId"];
        var secret = TextEncodings.Base64.Encode(TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["auth0:ClientSecret"]));
        app.UseJwtBearerAuthentication(
            new JwtBearerAuthenticationOptions
            {
                AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
                AllowedAudiences = new[] { audience },
                IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
                {
                    new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret)
                }
            });

        app.UseAuth0Authentication(
            clientId: platform.ServerRole.GetConfigurationSettingValue("auth0:ClientId"),
            clientSecret: platform.ServerRole.GetConfigurationSettingValue("auth0:ClientSecret"),
            domain: platform.ServerRole.GetConfigurationSettingValue("auth0:Domain"),
            provider: provider);
    }
}

webapiconfig file:

     public static void Register(HttpConfiguration config)
    {

        // Web API routes
        config.MapHttpAttributeRoutes();
        config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new {id = RouteParameter.Optional});
        config.Filters.Add(new AuthorizeAttribute());
        ODataConfig.Setup(config);

        var clientID = WebConfigurationManager.AppSettings["auth0:ClientId"];
        var clientSecret = WebConfigurationManager.AppSettings["auth0:ClientSecret"];

        config.MessageHandlers.Add(new JsonWebTokenValidationHandler()
        {
            Audience = clientID,
            SymmetricKey = clientSecret
        });
    }

Currently creating the jwt token from below code and posting using postman in header just to check if it works.. but redirects to login page.

  string token = JWT.Encode(payload, secretKey, JwsAlgorithm.HS256);
5
  • Show us the code. How your have configured the auth for the WebAPI, and how you get the token from the calling application as well. Commented Sep 28, 2016 at 6:50
  • updated the question.. hope that helps Commented Sep 28, 2016 at 7:47
  • Did you get this issue solved? Commented Nov 29, 2016 at 15:42
  • Did you solved the problem?. Opened up an identical thread on Auth0 forum. If I receive any updates on that I'll write an answer here Commented Feb 21, 2017 at 9:26
  • Did you resolve? I have similar scenario and can't believe there is not more documentation/blog/SO entries on this approach? Commented Oct 4, 2019 at 17:10

2 Answers 2

1

A few years late i know, but i recently came across the same requirement in a project, and found this sample put together by a dev at Auth0.

https://github.com/auth0-samples/aspnet-core-mvc-plus-webapi

The example in the link allows for cookie authentication OR token authentication for the API endpoints.

The key takeaway for me was using attributes on your routes to tell the pipline what authentication mechanism to use. In my case i wanted cookie authentication for the UI and token authentication for the endpoints. i had no requirement to use both for any single area of the project.

controller:

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]        
[HttpGet]
[Route("api")]
public string TestAuth()
{
    return "All good " + this.User.FindFirst(ClaimTypes.NameIdentifier).Value + ". You only get this message if you are authenticated.";
}
Sign up to request clarification or add additional context in comments.

Comments

0

I suspect what's happening is that your call to the API has a bearer token which fails validation (or there is no Authorize token at all), your API controller has an Authorize attribute, which, since there is no valid ClaimsPrincipal on the call throws 401. Auth0AuthenticationProvider picks that and assumes the call was to UI so redirects for user authentication. You may want to add an override in the Oauth0Provider to trap OnRedirectToIdP (or something like that), inspect the request and if it is to API, abot further handling and return Unauthorized. Remove any [Authorize] from your API and see whether it works then. Also make sure your startup does not require Authorize for all controllers. You may want to remove the authn part of your code (cookie and Oauth2Provider) and see whether you are getting to the API then.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.