'Trying the sample code in my app: connect works but after the success and token access redirects to login?

I'm trying to implement the sample client server in my current MVC apps to use openiddict.

I have a client App, that I configured to the best of my knowledge the same way as the MvcClient app in the samples project (mortis.client).

This seems to work.

I have an authentication app, which is used to authenticate our users across multiple applications, I integrated the mortis.server example in it. But I'm pretty sure I missed some stuff, here is what happens:

The client app requests access to the server app, it works, the connect/authorize method is called in the AuthorizeController of the server app, then, it requests the login of the user first (if not loggued in). After that, connect/authorize is called again, logs signs in the user and builds the identity and it passes in the implicit consent type switch/case.

After that, there is a redirect to the connect/token method but my McvServer apps redirects to login (seems the user is not really logued in?)

What am I doing wrong?

This is my Client App setup

public void ConfigureAuth(IAppBuilder app)
{
    IdentityModelEventSource.ShowPII = true;

    app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

    app.UseCookieAuthentication(new CookieAuthenticationOptions());

    app.UseOpenIdConnectAuthentication(
        new OpenIdConnectAuthenticationOptions
        {
            Authority = "https://url/serverapp/"                    

            ClientId = "MyClient.MVC",
            ClientSecret = "myclientsecret",

            RedirectUri = $"https://url/clientapp/signin-oidc",

            RedeemCode = true,

            ResponseMode = OpenIdConnectResponseMode.Query,
            ResponseType = OpenIdConnectResponseType.Code,

            Scope = "openid profile email roles",

            SecurityTokenValidator =
                new JwtSecurityTokenHandler
                {
                    // Disable the built-in JWT claims mapping feature.
                    InboundClaimTypeMap = new Dictionary<string, string>()
                },

            TokenValidationParameters =
                new TokenValidationParameters
                {
                    NameClaimType = "name",
                    RoleClaimType = "role"
                },

            Notifications =
                new OpenIdConnectAuthenticationNotifications
                {
                    // Note: by default, the OIDC client throws an OpenIdConnectProtocolException
                    // when an error occurred during the authentication/authorization process.
                    // To prevent a YSOD from being displayed, the response is declared as handled.
                    AuthenticationFailed =
                        notification =>
                        {
                            if (string.Equals(notification.ProtocolMessage.Error, "access_denied", StringComparison.Ordinal))
                            {
                                notification.HandleResponse();

                                notification.Response.Redirect("/");
                            }

                            return Task.CompletedTask;
                        },
                    AuthorizationCodeReceived = AuthorizationCodeReceived,
                    MessageReceived = OnMessageReceived,
                    RedirectToIdentityProvider = OnRedirectToIdentityProvider,
                    SecurityTokenReceived = OnSecurityTokenReceived,
                    SecurityTokenValidated = OnSecurityTokenValidated,
                    TokenResponseReceived = OnTokenResponseReceived
                }
        });
}

The signin link is the same as in the sample app (a sign in view that challenges owin access)

Here is the server configuration:

public void Configuration(IAppBuilder app)
{
    // SignalR
    app.MapSignalR();

    ConfigureAuth(app);

    ConfigureOpenIddict(app);
}

private void ConfigureOpenIddict(IAppBuilder app)
{
    var container = CreateContainer();

    // Register the Autofac scope injector middleware.
    app.UseAutofacLifetimeScopeInjector(container);

    // Register the two OpenIddict server/validation middleware.
    app.UseMiddlewareFromContainer<OpenIddictServerOwinMiddleware>();
    app.UseMiddlewareFromContainer<OpenIddictValidationOwinMiddleware>();

    // Configure ASP.NET MVC 5.2 to use Autofac when activating controller instances.
    DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

    // Seed the database with the sample client using the OpenIddict application manager.
    // Note: in a real world application, this step should be part of a setup script.
    Task.Run(() => this.FillClients(container));
}
private static IContainer CreateContainer()
{
    var services = new ServiceCollection();
    services.AddOpenIddict()

        // Register the OpenIddict core components.
        .AddCore(
            options =>
            {
                // Configure OpenIddict to use the Entity Framework 6.x stores and models.
                // Note: call ReplaceDefaultEntities() to replace the default OpenIddict entities.
                options
                    .UseEntityFramework()
                    .UseDbContext<AppDbContext>();
            })

        // Register the OpenIddict server components.
        .AddServer(
            options =>
            {
                // Enable the authorization, logout and token endpoints.
                options
                    .SetAuthorizationEndpointUris("/connect/authorize")
                    .SetLogoutEndpointUris("/connect/logout")
                    .SetTokenEndpointUris("/connect/token");

                // Mark the "email", "profile" and "roles" scopes as supported scopes.
                options.RegisterScopes(Scopes.Email, Scopes.Profile, Scopes.Roles);

                // Note: this sample only uses the authorization code flow but you can enable
                // the other flows if you need to support implicit, password or client credentials.
                options.AllowAuthorizationCodeFlow();

                // Register the signing and encryption credentials.
                options.AddDevelopmentEncryptionCertificate()
                       .AddDevelopmentSigningCertificate();

                // Register the OWIN host and configure the OWIN-specific options.
                options.UseOwin()
                       .EnableAuthorizationEndpointPassthrough()
                       .EnableLogoutEndpointPassthrough()
                       .EnableTokenEndpointPassthrough();
            })

        // Register the OpenIddict validation components.
        .AddValidation(
            options =>
            {
                // Import the configuration from the local OpenIddict server instance.
                options.UseLocalServer();

                // Register the OWIN host.
                options.UseOwin();
            });

    // Create a new Autofac container and import the OpenIddict services.
    var builder = new ContainerBuilder();
    builder.Populate(services);

    // Register the MVC controllers.
    builder.RegisterControllers(typeof(Startup).Assembly);

    return builder.Build();
}

public void ConfigureAuth(IAppBuilder app)
{
    // Configure the db context, user manager and signin manager to use a single instance per request
    app.CreatePerOwinContext<AppDbContext>((options, context) => AppDbContext.Create());
    app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
    app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
    app.CreatePerOwinContext<ApplicationRoleManager>(Application‌​RoleManager.Create);

    // Enable the application to use a cookie to store information for the signed in user
    // and to use a cookie to temporarily store information about a user logging in with a third party login provider
    // Configure the sign in cookie
    app.UseCookieAuthentication(
        new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),

            CookieName = "CookieNameBla_SessionId",
            SlidingExpiration = true,

            AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
            CookieHttpOnly = true,
            CookiePath = "/",
            CookieSecure = this.ServiceEnvironment == ServiceEnvironment.Development ? CookieSecureOption.SameAsRequest : CookieSecureOption.Always,

            ExpireTimeSpan = TimeSpan.FromDays(14),

            Provider = new CookieAuthenticationProvider
            {
                // Enables the application to validate the security stamp when the user logs in.
                // This is a security feature which is used when you change a password or add an external login to your account.
                OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                validateInterval: TimeSpan.FromMinutes(30),
                regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)),
            }
        });

    // Use a cookie to temporarily store information about a user logging in with a third party login provider
    app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

    // Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.
    app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));

    // Enables the application to remember the second login verification factor such as phone or email.
    // Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from.
    // This is similar to the RememberMe option when you log in.
    app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source