AlexeyBobrovich
AlexeyBobrovich

Reputation: 37

OpenIdDict: Interactive user consent is required. AuthenticationScheme: OpenIddict.Server.AspNetCore was forbidden

I have Server and Webassembly Client project, the client is hosted on the server. My project uses OpenIDDict auth. Suddenly, when I trying get to the client, I get error: Interactive user consent is required

My Program.cs:

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Notes.Web.Server;
using Notes.Web.Server.Logging;
using Notes.Web.Server.Models;
using Notes.Web.Server.Models.Data;
using static OpenIddict.Abstractions.OpenIddictConstants;

#region WebApplication Builder

var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
    WebRootPath = "WebRoot",
    Args = args
});
builder.WebHost.ConfigureLogging(loggingBuilder =>
{
    loggingBuilder.ClearProviders();
    loggingBuilder.AddPrettyConsoleLogger();
});
builder.Services.AddHostedService<OAuthWorker>();

#endregion

#region Razor and MVC Setup

builder.Services.AddMvc();
builder.Services.AddRazorPages().AddRazorRuntimeCompilation();

#endregion

#region Database Setup

builder.Services.AddDbContext<PrettyNotesApplicationDBContext>(options =>
{
    //options.UseInMemoryDatabase("Server=(localdb)\\mssqllocaldb;Database=TestDB;Trusted_Connection=True;");
    options.UseSqlServer("****");
    options.UseOpenIddict();
}); 

#endregion

#region Identity Setup

builder.Services.AddIdentity<PNUser, IdentityRole>(options =>
{
    options.Password.RequiredLength = 8;
    options.Password.RequireNonAlphanumeric = false;
    options.Password.RequireDigit = true;
}).AddEntityFrameworkStores<PrettyNotesApplicationDBContext>().AddDefaultTokenProviders();

builder.Services.Configure<IdentityOptions>(options =>
{
    options.ClaimsIdentity.UserNameClaimType = Claims.Name;
    options.ClaimsIdentity.UserIdClaimType = Claims.Subject;
    options.ClaimsIdentity.RoleClaimType = Claims.Role;
});

builder.Services.PostConfigure<CookieAuthenticationOptions>(IdentityConstants.ApplicationScheme,
    opt =>
    {
        opt.LoginPath = "/auth/login";
        opt.LogoutPath = "/auth/logout";
    });

#endregion

#region OpenIdDict Setup

builder.Services.AddOpenIddict().AddCore(options =>
{
    options.UseEntityFrameworkCore().UseDbContext<PrettyNotesApplicationDBContext>();
}).AddServer(options =>
{
    options.SetAuthorizationEndpointUris("/connect/authorize")
        .SetLogoutEndpointUris("/connect/logout")
        .SetTokenEndpointUris("/connect/token")
        .SetUserinfoEndpointUris("/connect/userinfo");
    options.RegisterScopes(Scopes.Email, Scopes.Profile, Scopes.Roles, Scopes.OpenId);
    options.AddDevelopmentEncryptionCertificate().AddDevelopmentSigningCertificate();
    options.AllowAuthorizationCodeFlow()
        .AllowRefreshTokenFlow();
    options.UseAspNetCore()
        .EnableAuthorizationEndpointPassthrough()
        .EnableLogoutEndpointPassthrough()
        .EnableStatusCodePagesIntegration()
        .EnableTokenEndpointPassthrough();
}).AddValidation(options =>
{
    options.UseLocalServer();
    options.UseAspNetCore();
});

#endregion

builder.Services.AddRemoteAuthentication<RemoteAuthenticationState, RemoteUserAccount, OidcProviderOptions>();
builder.Services.AddScoped<AuthenticationStateProvider, RemoteAuthenticationService>()
    .AddScoped<SignOutSessionStateManager>()
    .AddTransient<IAccessTokenProvider, AccessTokenProvider>()
    .AddTransient<Microsoft.JSInterop.IJSRuntime, JSRuntime>();

var app = builder.Build();

if (app.Environment.IsDevelopment()) app.UseDeveloperExceptionPage();

app.UseRouting();

app.UseStaticFiles();
app.UseHttpsRedirection();
app.UseBlazorFrameworkFiles();

app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
    endpoints.MapRazorPages();
    endpoints.MapFallbackToController("/client/{**segment}", "Index", "Client");
    endpoints.MapControllerRoute("Default", "{controller=Home}/{action=Index}/{id?}");
});

app.Run();

After starting application and accessing Client, I get next error:

[Information] - [0] - [OpenIddict.Server.OpenIddictServerDispatcher] - [2022-02-06] - [20:34:46]
        The authorization response was successfully returned to 'https://localhost:7000/client/security/oauth/login-callback' using the query response mode: {
  "error": "consent_required",
  "error_description": "Interactive user consent is required.",
  "error_uri": "https://documentation.openiddict.com/errors/ID2015",
  "state": "25b73e28b98140ae9f0b88267828fd68"
}.
[Information] - [13] - [OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandler] - [2022-02-06] - [20:34:46]
        AuthenticationScheme: OpenIddict.Server.AspNetCore was forbidden.

What does this error means and how to solve it?

Upvotes: 2

Views: 1231

Answers (1)

Andrew
Andrew

Reputation: 404

I guess you are seeding your DB with application details for auth. In OpenIddictApplicationDescriptor there is a field ConsentType which must be set to ConsentTypes.Implicit. It usually happens after library upgrade. E.g. I'm using code like this:


    private static async Task SeedApplications(IServiceScope scope, CancellationToken cancellationToken)
    {
      var manager = scope.ServiceProvider.GetRequiredService<OpenIddictApplicationManager<OpenIddictEntityFrameworkCoreApplication>>();
      var applications = new[] { CreateNativeClient(), CreateWebClient() };
      foreach (var client in applications)
      {
        if (await manager.FindByClientIdAsync(client.ClientId, cancellationToken) == null)
        {
          await manager.CreateAsync(client, cancellationToken);
        }
      }
    }

and in CreateWebClient you are setting:


    return new OpenIddictApplicationDescriptor {
      ClientId = clientId,
      DisplayName = "Web Client",
      RedirectUris = {...},
      Permissions = {...},
      Type = OpenIddictConstants.ClientTypes.Public,
      ConsentType = ConsentTypes.Implicit // <-- this must be set
    };

Upvotes: 2

Related Questions