3

I am just learning a ASP.NET CORE. I have successfully implemented a openiddict to secure my api. After successful login user gets a token and that token is used for accessing web api but it is allowing unauthorized user too(i.e. the one who does't have token) This is how I have arranged by controller

namespace ISIA.Controllers
{
  [Authorize]
  [Route("api/[controller]")]
  public class PostController: Controller
  {
    private readonly IPostService _postService;
    private readonly PostToPostViewModelMapper _mapper;
    public PostController(
      IPostService postService
      )
    {
      _postService = postService;
      _mapper = new PostToPostViewModelMapper();
    }


    [HttpPost]
    public ObjectResult SavePost([FromBody] PostViewModel postViewModel)
    {
                 //method body
    }

    [HttpGet]
    public ObjectResult GetAllPost()
    {
       //method body  
    }
  }
}

in statup

 services.AddOpenIddict(options =>
      {
        options.AddEntityFrameworkCoreStores<ApplicationDbContext>();
        options.AddMvcBinders();
        options.EnableAuthorizationEndpoint("/connect/authorize")
                       .EnableLogoutEndpoint("/connect/logout")
                       .EnableTokenEndpoint("/connect/token")
                       .EnableUserinfoEndpoint("/api/userinfo");
        options.AllowAuthorizationCodeFlow();
        options.RequireClientIdentification();
        options.AllowPasswordFlow();
        options.AllowRefreshTokenFlow();
        options.DisableHttpsRequirement();
        options.UseRollingTokens(); //Uncomment to renew refresh tokens on every refreshToken request
                                    // options.AddSigningKey(new SymmetricSecurityKey(System.Text.Encoding.ASCII.GetBytes(Configuration["STSKey"])));
        options.Configure(
          config =>
          {
            // Enable sliding expiration
            config.UseSlidingExpiration = true;
            config.AccessTokenLifetime = TimeSpan.FromMinutes(240);
            config.RefreshTokenLifetime = TimeSpan.FromDays(15);
          });
      });

What I am doing wrong please help me out.

Chris Hadfield
  • 494
  • 1
  • 7
  • 34
  • Are you calling `app.UseAuthentication();`? I'm doing it before `app.UseMvc()` but the order might not be important. – ProgrammingLlama Oct 12 '18 at 02:21
  • 1
    Yes I have. It is just above the `app.UserMvc()` – Chris Hadfield Oct 12 '18 at 02:24
  • 2
    If your web app and api are on the same domain (same project) then cookies will be sent with each ajax request, therefore cookie auth is allowing the request even when you don't set the token in the `Authorization` header. – Brad Oct 12 '18 at 03:47

2 Answers2

4

Set the AuthenticationSchemes in the Authorize attribute like this:

[Authorize(AuthenticationSchemes = 
    OpenIddictValidationDefaults.AuthenticationScheme)]

That will ensure the authorization is done with OAuth tokens not with Cookies.

The OpenIddictValidationDefaults.AuthenticationScheme is defined here.

Authorizing with a specific scheme is documented here.

If that fails, which your comment suggests it did, then you also need to configure a token handler. That will look something like this:

services
    .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options => 
    {
        options.Audience = "https://localhost:5001/";
        options.Authority = "http://localhost:5000/";
    });
Shaun Luttin
  • 133,272
  • 81
  • 405
  • 467
  • `InvalidOperationException: No authentication handler is configured to authenticate for the scheme: Bearer`. How do I solve this – Chris Hadfield Oct 12 '18 at 04:56
  • Hmm. That error means that you have not configured a token authentication handler.. – Shaun Luttin Oct 12 '18 at 05:01
  • You might need to add `AddJwtBearer`. I've updated my answer. – Shaun Luttin Oct 12 '18 at 05:04
  • 1
    The details of the `Audience` and `Authority` depend on your specific configuration and requirements. The `Audience` is the expected consumer of the token, the `Authority` is the expected producer of the token. – Shaun Luttin Oct 12 '18 at 14:23
1

In my case, I foolishly tried to get slick and only roll with

services.AddMvcCore()
    .AddFormatterMappings()
    .AddJsonFormatters()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

in my ConfigureServices() in a misguided attempt to optimize and be lean. Well, that must have optimized away some core authentication plumbing. Although my handler was always called, every request still made it to the controller.

Solved by adding to the core plumbing:

services.AddMvcCore()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .AddFormatterMappings()
    .AddJsonFormatters()
    .AddAuthorization();
JasonCoder
  • 1,126
  • 2
  • 12
  • 24