Reputation: 470
I am using OpenIdDict 3.0 and it works great however I have one controller that uses the AllowAnonymous attribute and I am still receiving "The request was rejected because the access token was missing". I am assuming it could be something with the ordering in my Startup which makes it not get hit in the pipeline but I am not sure. Here is my startup class:
public async void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
{
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseMvcWithDefaultRoute();
}
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.EnableEndpointRouting = false;
}).AddNewtonsoftJson();
services.AddAutoMapper(typeof(Startup));
services.AddDbContext<MyDbContext>(options =>
{
options.UseSqlServer(WebConfig.ConnectionString, x => x.MigrationsAssembly("X.Api.DataAccess"));
options.UseLazyLoadingProxies();
options.UseOpenIddict();
});
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
options.Password.RequireLowercase = true;
})
.AddEntityFrameworkStores<MyDbContext>()
.AddUserStore<ApplicationUserStore>()
.AddDefaultTokenProviders();
services.Configure<IdentityOptions>(options =>
{
options.ClaimsIdentity.UserNameClaimType = Claims.Name;
options.ClaimsIdentity.UserIdClaimType = Claims.Subject;
options.ClaimsIdentity.RoleClaimType = Claims.Role;
});
services.AddOpenIddict()
.AddCore(options =>
{
options.UseEntityFrameworkCore()
.UseDbContext<MyDbContext>();
})
.AddServer(options =>
{
options.SetAuthorizationEndpointUris("/connect/authorize")
.SetLogoutEndpointUris("/connect/logout")
.SetTokenEndpointUris("/connect/token");
options.AllowAuthorizationCodeFlow()
.AllowRefreshTokenFlow();
scopes.
options.RegisterScopes(Scopes.Email, Scopes.OpenId, Scopes.OfflineAccess);
// Register the signing and encryption credentials.
options.AddDevelopmentEncryptionCertificate()
.AddDevelopmentSigningCertificate();
options.UseAspNetCore()
.EnableTokenEndpointPassthrough();
})
.AddValidation(options =>
{
// Import the configuration from the local OpenIddict server instance.
options.UseLocalServer();
// Register the ASP.NET Core host.
options.UseAspNetCore();
});
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme;
});
}
Any help would be much appreciated!
Upvotes: 1
Views: 604
Reputation: 177
In my case, I wanted to get rid of the DB context creation using [AllowAnonymous]
attribute. But it doesn't work that way. So I had to create my own replacement for AuthenticationMiddleware
and add the necessary paths to the exceptions.
Now step by step.
First. Create middleware:
public class CustomAuthenticationMiddleware
{
private readonly RequestDelegate _nextWithoutAuth;
private readonly AuthenticationMiddleware _nextWithAuth;
private List<PathString> _withoutAuth = new List<PathString>
{
"/url/1", "/url/2"
};
public CustomAuthenticationMiddleware(RequestDelegate next,
IServiceProvider sp)
{
_nextWithoutAuth = next;
_nextWithAuth = ActivatorUtilities
.CreateInstance<AuthenticationMiddleware>(sp, next);
}
public async Task Invoke(HttpContext context)
{
var path = context.Request.Path.HasValue ?
context.Request.Path.Value : null;
var withoutAuth = context.Request.Path.HasValue
&& _withoutAuth.Any(it => path.StartsWith(it, StringComparison.OrdinalIgnoreCase));
if (withoutAuth)
{
await _nextWithoutAuth.Invoke(context);
}
else
{
await _nextWithAuth.Invoke(context);
}
}
}
Second. Fill array _withoutAuth
with required values.
Third. In Startup.cs replace app.UseAuthentication();
with app.UseMiddleware<CustomAuthenticationMiddleware>();
.
p.s. I use .net core 2.1
p.s.s. I assume you can improve my solution if get all controllers and their methods with [AllowAnonymous]
attribute and than add them into _withoutAuth
array.
Upvotes: 0
Reputation: 42010
The behavior you see is actually "normal": when you set DefaultAuthenticateScheme
, the authentication middleware (aka app.UseAuthentication()
) - which is usually added very early in the ASP.NET Core pipeline - automatically invokes the corresponding authentication handler to populate HttpContext.User
.
This mechanism always happens independently of whether your MVC actions are decorated with [Authorize]
or [AllowAnonymous]
. If OpenIddict cannot find the access token in the Authorization
header, it logs an error and tells the authentication stack it couldn't provide the AuthenticateResult
it requested.
If your MVC actions are decorated with [Authorize]
, the authentication stack will ask OpenIddict to return a 401 challenge (unless [AllowAnonymous]
is used).
That said, while it doesn't prevent things from working normally, I agree it may be an important source of noise, so I'll consider removing this log message. I opened https://github.com/openiddict/openiddict-core/issues/941 to track that.
Cheers.
Upvotes: 1