I put IdentityServer4 on azure and it worked correctly, but when I log in to IdentityServer4, it only stays logged in for about 20 minutes and then asks for the login again (redirects to the login screen).
Does anyone know how to log in only once?
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(op => op.Filters.Add(new AuthorizeAttributeFilter()));
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
services.AddIdentity<ApplicationUser, IdentityRole>(option =>
{
option.Password.RequireDigit = false;
option.Password.RequiredLength = 3;
option.Password.RequiredUniqueChars = 0;
option.Password.RequireLowercase = false;
option.Password.RequireNonAlphanumeric = false;
option.Password.RequireUppercase = false;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseSuccessEvents = true;
options.Authentication.CookieLifetime = TimeSpan.FromHours(24);
options.Authentication.CookieSlidingExpiration = true;
})
.AddDeveloperSigningCredential()
.AddAspNetIdentity<ApplicationUser>()
.AddClientStore<ClientStore>()
.AddProfileService<ProfileService>()
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
db => db.MigrationsAssembly(migrationsAssembly));
})
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
db => db.MigrationsAssembly(migrationsAssembly));
});
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddAuthentication("MyCookie")
.AddCookie("MyCookie", options =>
{
options.ExpireTimeSpan = TimeSpan.FromHours(24);
});
}
It's not magic and it's just using a cookie. The most likely thing is the lifetime of your authentication cookie. I wouldn't be surprised if it defaulted to 20 minutes.
Related
Hi i use identity on my project. When customer logins it is success but on 1st try its stuck in loading if i redirect manually from url it goes on page normally but on its own its just stuck. If i will sign out after and sign in again it works perfectly. it happens only on 1st time of loading project. my codei s
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(model.Username, model.Password, true, lockoutOnFailure: false);
if (result.Succeeded)
{
return RedirectToAction("Index", "Product");
}
else
{
ModelState.AddModelError("Login", "Invalid login attempt.");
return View(model);
}
}
and in start up code is like
/services.Configure<CookiePolicyOptions>(options =>
//{
// options.ConsentCookie.IsEssential = true;//<--NOTE THIS
// options.CheckConsentNeeded = context => false;
// options.MinimumSameSitePolicy = SameSiteMode.None;
//});
//services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
// .AddEntityFrameworkStores<ApplicationDbContext>();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>
{
//options.Cookie.IsEssential = true;//<--NOTE THIS
//options.Cookie.HttpOnly = true;
//options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
//options.Cookie.SameSite = SameSiteMode.None;
options.LoginPath = "/Account/Login";
options.LogoutPath = "/Account/Logout";
options.AccessDeniedPath = "/Account/AccessDenied"; // If the AccessDeniedPath is not set here, ASP.NET Core will default to /Account/AccessDenied
options.ExpireTimeSpan = TimeSpan.FromMinutes(720);
//options.SlidingExpiration = true;
});
i have tried many other options and things but none worked
this are options i tried.
services.Configure<CookiePolicyOptions>(options =>
{
options.ConsentCookie.IsEssential = true;//<--NOTE THIS
options.CheckConsentNeeded = context => false;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>
{
options.Cookie.IsEssential = true;//<--NOTE THIS
options.Cookie.HttpOnly = true;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.SameSite = SameSiteMode.None;
options.LoginPath = "/Account/Login";
options.LogoutPath = "/Account/Logout";
options.AccessDeniedPath = "/Account/AccessDenied"; // If the AccessDeniedPath is not set here, ASP.NET Core will default to /Account/AccessDenied
options.ExpireTimeSpan = TimeSpan.FromMinutes(720);
options.SlidingExpiration = true;
});
//services.ConfigureApplicationCookie(options =>
//{
// // Cookie settings
// options.Cookie.HttpOnly = true;
// options.ExpireTimeSpan = TimeSpan.FromMinutes(720);
// options.LoginPath = "/Account/Login"; // If the LoginPath is not set here, ASP.NET Core will default to /Account/Login
// options.LogoutPath = "/Account/Logout"; // If the LogoutPath is not set here, ASP.NET Core will default to /Account/Logout
// options.AccessDeniedPath = "/Account/AccessDenied"; // If the AccessDeniedPath is not set here, ASP.NET Core will default to /Account/AccessDenied
// options.SlidingExpiration = true;
//});
I code “MVC Client” just as in “Creating an MVC client” https://identityserver4.readthedocs.io/en/latest/quickstarts/2_interactive_aspnetcore.html#creating-an-mvc-client
My main goal is when access_token is expired to get new one with refresh_token.
I need it not for API access but for “MVC Client” authentication/authorization.
So, I thought before “MVC Client” issues redirect to IdentityServer to its login page (http://localhost:5000/connect/authorize?client_id=mvc&redirect_uri=bla, bla, bla) just intercept it and send instead of it just get new access_token (with refresh_token) w/o user need to enter his credentials.
So, I just need to get any event before “MVC Client” decides that access_token no longer valid and tries to redirect to IdentityServer login.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies", options => {
options.Cookie.Name = "MyCookie";
options.Cookie.MaxAge = new TimeSpan(0, 0, 60);
options.ExpireTimeSpan = new TimeSpan(0, 0, 60);
options.SlidingExpiration = false;
//options.Cookie.s ExpireTimeSpan = new TimeSpan(0, 0, 1);
options.Events = new Func<CookieAuthenticationEvents>(() =>
{
var cookieAuthenticationEvents = new CookieAuthenticationEvents( );
var f = cookieAuthenticationEvents.OnRedirectToLogin;
var f1 = cookieAuthenticationEvents.OnValidatePrincipal;
var f2 = cookieAuthenticationEvents.OnSignedIn;
cookieAuthenticationEvents.OnRedirectToLogin = ( context ) =>
{
return f(context);
};
cookieAuthenticationEvents.OnValidatePrincipal = ( context ) =>
{
return f1(context);
};
cookieAuthenticationEvents.OnSignedIn = ( context ) =>
{
return f2(context);
};
return cookieAuthenticationEvents;
}
)( );
})
.AddOpenIdConnect("oidc", options =>
{
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ClientId = "mvc";
options.ClientSecret = "secret";
options.ResponseType = "code";
options.SaveTokens = true;
options.Scope.Add("email");
options.Scope.Add("api1");
options.Scope.Add("offline_access");
// options.Events = new Func<>
options.Events = new Func<OpenIdConnectEvents>(() =>
{
var openIdConnectEvents = new OpenIdConnectEvents( );
var f = openIdConnectEvents.OnAuthenticationFailed;
var f1 = openIdConnectEvents.OnAccessDenied;
var f2 = openIdConnectEvents.OnTokenValidated;
var f3 = openIdConnectEvents.OnAccessDenied;
openIdConnectEvents.OnAuthenticationFailed = ( context ) =>
{
return f(context);
};
openIdConnectEvents.OnAccessDenied = ( context ) =>
{
return f1(context);
};
openIdConnectEvents.OnTokenValidated = ( context ) =>
{
return f2(context);
};
openIdConnectEvents.OnAccessDenied = ( context ) =>
{
return f3(context);
};
return openIdConnectEvents;
}
)( );
});
}
On every line with "return f3(context);" I put break point with anticipation to hit it before getting to Login page of IdentityServer – no luck .
This is client config.
new Client
{
ClientId = "mvc",
ClientSecrets = { new Secret("secret".Sha256()) },
AllowedGrantTypes = GrantTypes.Code,
RequireConsent = false,
RequirePkce = true,
// where to redirect to after login
RedirectUris = { "http://localhost:5002/signin-oidc" },
// where to redirect to after logout
PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
"api1"
},
AlwaysIncludeUserClaimsInIdToken = true,
AllowOfflineAccess = true,
AccessTokenLifetime = 150,
AuthorizationCodeLifetime = 150,
UserSsoLifetime = 150
}
How to do it - refresh token automatically w/o user interaction for MVC Client authentication (not for API access)
I've found a solution. Here it is:
https://github.com/leastprivilege/AspNetCoreSecuritySamples/tree/aspnetcore21/AutomaticTokenManagement
The key point here is to override this method
public override async Task ValidatePrincipal ( CookieValidatePrincipalContext context )
from class
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationEvents
I'm trying to get an access token from Identity Provider using Resource Owner Password Credentials grant type. The same configuration worked for .NET Core 2.2, but it doesn't work anymore for .NET Core 3.1. Here is the configuration of Identity Provider:
public class Startup
{
public IConfiguration Configuration { get; }
private readonly string _MyAllowSpecificOrigins = "fooorigin";
private readonly IWebHostEnvironment _env;
public Startup(IConfiguration configuration, IWebHostEnvironment env)
{
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
IdentityModelEventSource.ShowPII = true;
_env = env;
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddPersistence(Configuration); //Custom extension
services.AddAutoMapper(Assembly.GetAssembly(typeof(BaseMappingProfile)));
#region Options
services.Configure<IdentityServerOptions>(Configuration.GetSection("IdentityServerOptions"));
services.Configure<Settings>(Configuration.GetSection("Settings"));
#endregion
#region Configurations
services.AddTransient<IdentityServerOptions>();
#endregion
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped<ITokenManagerHelper, TokenManagerHelper>();
services.AddScoped<IUserService, UserService>();
services.AddCors(options =>
{
options.AddPolicy(_MyAllowSpecificOrigins,
builder =>
{
builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddMvc().AddFluentValidation(fv =>
{
fv.RegisterValidatorsFromAssemblyContaining<CommonValidator>();
fv.ImplicitlyValidateChildProperties = true;
})
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
var identityServerDataDBConnectionString = Configuration.GetConnectionString("IdentityServerConfigDatabase");
var migrationsAssembly = typeof(UsersDbContext).GetTypeInfo().Assembly.GetName().Name;
var identityAuthority = Configuration.GetValue<string>("IdentityServerOptions:Authority");
// Add Authentication
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = "oidc";
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.Authority = Configuration.GetValue<string>("IdentityServerOptions:Authority");
options.ClientId = Configuration.GetValue<string>("IdentityServerOptions:ClientName");
options.ClientSecret = Configuration.GetValue<string>("IdentityServerOptions:ClientSecret");
options.ResponseType = Configuration.GetValue<string>("IdentityServerOptions:ResponseType");
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("roles");
options.Scope.Add("fooapi");
options.Scope.Add("fooidentityapi");
options.Scope.Add("offline_access");
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.ClaimActions.Remove("amr");
options.ClaimActions.DeleteClaim("sid");
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = JwtClaimTypes.GivenName,
RoleClaimType = JwtClaimTypes.Role,
};
});
services.AddTransient<IPersistedGrantStore, PersistedGrantStore>();
services.AddTransient<IResourceOwnerPasswordValidator, ResourceOwnerPasswordValidator>();
// Add Identity Server
// Add Signing Certificate
// Add Users Store
// Add Configurations Store
// Add Operational Stores
if (_env.IsDevelopment() || _env.IsStaging())
{
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddUserStore()
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = builder =>
{
builder.UseSqlServer(identityServerDataDBConnectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
};
})
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder =>
{
builder.UseSqlServer(identityServerDataDBConnectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
};
})
.AddResourceOwnerValidator<ResourceOwnerPasswordValidator>();
}
else
{
//Todo: add certificate
}
}
public void Configure(
IApplicationBuilder app,
IWebHostEnvironment env,
IOptions<Settings> settingOptions)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseCors(_MyAllowSpecificOrigins);
app.UseCookiePolicy();
var forwardOptions = new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
RequireHeaderSymmetry = false
};
forwardOptions.KnownNetworks.Clear();
forwardOptions.KnownProxies.Clear();
app.UseForwardedHeaders(forwardOptions);
app.UseAuthentication();
app.UseRouting();
app.UseIdentityServer();
}
}
And here's the configuration of API:
public class Startup
{
#region Private Fields
private readonly string _allowedOrigins = "fooorigin";
#endregion
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddAuthorization();
services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
options.Authority = Configuration.GetValue<string>("IdentityServerOptions:Authority");
options.RequireHttpsMetadata = false;
options.ApiName = Configuration.GetValue<string>("IdentityServerOptions:ApiName");
options.SupportedTokens = IdentityServer4.AccessTokenValidation.SupportedTokens.Jwt;
});
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
#region Options
services.AddOptions();
#endregion
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddCors(options =>
{
options.AddPolicy(_allowedOrigins, builder =>
{
builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddAntiforgery(options =>
{
options.HeaderName = "X-XSRF-TOKEN";
});
services.AddMvc(o =>
{
o.EnableEndpointRouting = false;
o.Conventions.Add(new ApiExplorerGroupPerVersionConvention());
o.Filters.Add(new ModelStateFilter());
}).AddFluentValidation(fv =>
{
fv.RegisterValidatorsFromAssemblyContaining<CommonValidator>();
fv.ImplicitlyValidateChildProperties = true;
})
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
#region Customise default API behavour
services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressModelStateInvalidFilter = true;
});
#endregion
#region Versioning
services.AddApiVersioning(o =>
{
o.ApiVersionReader = new HeaderApiVersionReader("api-version");
o.DefaultApiVersion = new ApiVersion(1, 0);
o.AssumeDefaultVersionWhenUnspecified = true;
o.ReportApiVersions = true;
});
#endregion
#region Register the Swagger generator, defining 1 or more Swagger documents
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1.0", new OpenApiInfo
{
Title = Configuration.GetValue<string>("SwaggerDocOptions:Title"),
Version = Configuration.GetValue<string>("SwaggerDocOptions:Version"),
Description = Configuration.GetValue<string>("SwaggerDocOptions:Description")
});
c.OperationFilter<RemoveApiVersionFromParamsOperationFilter>();
var basePath = PlatformServices.Default.Application.ApplicationBasePath;
var xmlPath = Path.Combine(basePath, "foo.xml");
c.IncludeXmlComments(xmlPath);
var scopes = Configuration.GetValue<string>("IdentityServerOptions:RequiredScopes").Split(',').ToList();
var scopesDictionary = new Dictionary<string, string>();
foreach (var scope in scopes)
{
scopesDictionary.Add(scope, scope);
}
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Name = "Authorization",
Type = SecuritySchemeType.OAuth2,
Scheme = "Bearer",
Flows = new OpenApiOAuthFlows
{
Password = new OpenApiOAuthFlow
{
TokenUrl = new Uri(Configuration.GetValue<string>("IdentityServerOptions:TokenEndpoint")),
Scopes = scopesDictionary
}
},
In = ParameterLocation.Header
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
},
Type = SecuritySchemeType.Http,
Scheme = "Bearer",
Name = "Bearer",
In = ParameterLocation.Header
},
new List<string>()
}
});
});
#endregion
}
/// <summary>
/// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
/// </summary>
/// <param name="app">Application builder</param>
/// <param name="env">Web host environment</param>
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseCors(_allowedOrigins);
app.UseAuthentication();
app.UseSerilogRequestLogging();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
app.UseSwagger(
o =>
{
o.PreSerializeFilters.Add((swaggerDoc, httpReq) =>
{
var paths = new OpenApiPaths();
foreach (var x in swaggerDoc.Paths)
{
var key = x.Key.Contains("{version}") ? x.Key.Replace("{version}", swaggerDoc.Info.Version) : x.Key;
paths.Add(key, x.Value);
}
swaggerDoc.Paths = paths;
swaggerDoc.Extensions.Add(
new KeyValuePair<string,
IOpenApiExtension>("x-identity-authority",
new OpenApiString(Configuration.GetValue<string>("IdentityServerOptions:Authority"))));
});
o.RouteTemplate = "docs/{documentName}/swagger.json";
});
app.UseSwaggerUI(
c =>
{
c.SwaggerEndpoint("/docs/v1.0/swagger.json", "Foo API");
c.OAuthClientId(Configuration.GetValue<string>("IdentityServerOptions:ClientName"));
c.OAuthClientSecret(Configuration.GetValue<string>("IdentityServerOptions:ClientSecret"));
}
);
}
}
Now let's look at the process of getting an access token:
When I press "Authorize", it's validating and gets a token:
but when I try to access API resource which requires an authorization, it returns 401 error:
I tried to check the same in the Postman and when I try to access token endpoint it returns the access token like that:
I've been working for hours, tried many things but nothing worked. I tried to provide everything that can be cause of this problem, any help will be appreciated, thanks in advance.
After researching I found out that the ApiName must be the same as the name of the audience, also we should configure clients for JWT tokens, not the reference tokens.
Project details:
ASP.NET Core 2.2 MVC
Identity
I created an own login view. Actually if I call a view, for which I have to be authorized (by authorize attribute), it will automatically redirected to the login view. But at the moment it's "/Identity/Account/Login". But I want, that my own login view is shown. How can I do that?
I already tried this within startup.cs:
services.AddDefaultIdentity<ApplicationUser>(config => { config.SignIn.RequireConfirmedEmail = true; })
.AddDefaultUI(UIFramework.Bootstrap4).AddEntityFrameworkStores<ApplicationDbContext>();
services.Configure<IdentityOptions>(options => { options.User.RequireUniqueEmail = true; });
services.ConfigureApplicationCookie(options =>
{
options.Cookie.Name = "auth_cookie";
options.AccessDeniedPath = "/Account/Login";
options.LoginPath = "/Account/Login";
options.LogoutPath = "/Account/LogOff";
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(60);
options.ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter;
options.SlidingExpiration = true;
});
You could try to configure CookieAuthenticationOptions to achieve your requirement.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>()
.AddDefaultUI(UIFramework.Bootstrap4)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.PostConfigure<CookieAuthenticationOptions>(IdentityConstants.ApplicationScheme,
opt =>
{
//configure your other properties
opt.LoginPath = "/Login";
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
I have a restful api developed with .net core 2.2. I use OpenIddict password flow for my authentication and it is working properly. But after generating access_token i think it also generates a cookie.
My default scheme has configured with token and i don't need any cookies. How can i disable it?
This is my configure services methods for adding authentication.
public void ConfigureServices(IServiceCollection services)
{
services.AddSignalR();
services.AddMvc(options =>
{
options.SslPort = int.Parse(Configuration.GetValue<string>("https_port"));
options.Filters.Add(typeof(RequireHttpsAttribute));
options.Filters.Add(typeof(JsonExceptionFilter));
})
.AddJsonOptions(p => p.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore);
services
.AddDbContextPool<ShopDb>(opt =>
{
var cs = Configuration.GetValue<string>("connectionstrings:HomeAppliancesStore");
opt.UseSqlServer(cs, p => p.MaxBatchSize(2));
opt.ConfigureWarnings(p => p.Throw(RelationalEventId.QueryClientEvaluationWarning));
opt.UseOpenIddict<Guid>();
});
services.AddIdentity<AppUser, AppRole>(opt =>
{
opt.Password.RequireUppercase = false;
opt.Password.RequiredUniqueChars = 0;
opt.Password.RequiredLength = 6;
opt.Password.RequireNonAlphanumeric = false;
opt.ClaimsIdentity.UserIdClaimType = OpenIdConnectConstants.Claims.Subject;
opt.ClaimsIdentity.UserNameClaimType = OpenIdConnectConstants.Claims.Name;
opt.ClaimsIdentity.RoleClaimType = OpenIdConnectConstants.Claims.Role;
})
.AddEntityFrameworkStores<ShopDb>()
.AddDefaultTokenProviders();
services.AddOpenIddict()
.AddCore(p =>
{
p.UseEntityFrameworkCore()
.UseDbContext<ShopDb>()
.ReplaceDefaultEntities<Guid>();
})
.AddServer(opt =>
{
opt.UseMvc();
opt.EnableTokenEndpoint("/token");
opt.EnableLogoutEndpoint("/logout");
opt.AllowPasswordFlow();
opt.AllowRefreshTokenFlow();
opt.AcceptAnonymousClients();
opt.DisableHttpsRequirement(); // just for development
opt.SetAccessTokenLifetime(TimeSpan.FromDays(1));
opt.SetIdentityTokenLifetime(TimeSpan.FromDays(1));
})
.AddValidation();
services.AddAuthentication(opt =>
{
opt.DefaultAuthenticateScheme = OpenIddictValidationDefaults.AuthenticationScheme;
opt.DefaultScheme = OpenIddictValidationDefaults.AuthenticationScheme;
opt.DefaultChallengeScheme = OpenIddictValidationDefaults.AuthenticationScheme;
});
services.AddAuthorization(opt =>
{
opt.AddPolicy(Constants.BossPolicy,
p => p.RequireClaim(Constants.RoleClaimName, new List<string> { Constants.ManagerClaimValue }));
});
// Removed for brevity
}