// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { // *** CHANGE THIS FOR PRODUCTION USE *** // Here, we're generating a random key to sign tokens - obviously this means // that each time the app is started the key will change, and multiple servers // all have different keys. This should be changed to load a key from a file // securely delivered to your application, controlled by configuration. // // See the RSAKeyUtils.GetKeyParameters method for an examle of loading from // a JSON file. RSAParameters keyParams = RsaKeyService.GetRandomKey(); // Create the key, and a set of token options to record signing credentials // using that key, along with the other parameters we will need in the // token controlller. key = new Microsoft.IdentityModel.Tokens.RsaSecurityKey(keyParams); tokenOptions = new TokenOptionsModel() { Audience = TokenAudience, Issuer = TokenIssuer, SigningCredentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(key, Microsoft.IdentityModel.Tokens.SecurityAlgorithms.RsaSha256Signature) }; // Save the token options into an instance so they're accessible to the // controller. services.AddSingleton <TokenOptionsModel>(tokenOptions); // Enable the use of an [Authorize("Bearer")] attribute on methods and classes to protect. services.AddAuthorization(auth => { // inline policies //https://leastprivilege.com/2015/10/12/the-state-of-security-in-asp-net-5-and-mvc-6-authorization/ auth.AddPolicy("Admin", new AuthorizationPolicyBuilder() .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme) .RequireAuthenticatedUser().RequireClaim("Admin").Build()); // inline policies //https://leastprivilege.com/2015/10/12/the-state-of-security-in-asp-net-5-and-mvc-6-authorization/ auth.AddPolicy("Manager", new AuthorizationPolicyBuilder() .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme) .RequireAuthenticatedUser().RequireClaim("Manager").Build()); //https://github.com/mrsheepuk/ASPNETSelfCreatedTokenAuthExample auth.DefaultPolicy = new AuthorizationPolicyBuilder() .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme) .RequireAuthenticatedUser().Build(); }); // CORS works but hosting can make things confusing // http://stackoverflow.com/questions/34212765/how-do-i-get-the-kestrel-web-server-to-listen-to-non-localhost-requests services.AddCors(o => o.AddPolicy("AnyOrigin", builder => { builder.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader(); })); // Add framework services. services.AddMvc(); }
public void ConfigureServices(IServiceCollection services) { services.AddDbContext <IdentityDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); services.AddIdentity <IdentityUser, Role>() .AddEntityFrameworkStores <IdentityDbContext>() .AddDefaultTokenProviders(); services.AddMvc().SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_2_1); var builder = services.AddIdentityServer(options => { options.Events.RaiseErrorEvents = true; options.Events.RaiseInformationEvents = true; options.Events.RaiseFailureEvents = true; options.Events.RaiseSuccessEvents = true; }) .AddInMemoryIdentityResources(Configuration.GetSection("IdentityResources").Get <List <IdentityResource> >()) .AddInMemoryApiResources(Configuration.GetSection("ApiResources").Get <List <ApiResource> >()) .AddInMemoryClients(Configuration.GetSection("IdentityServer:Clients")) .AddAspNetIdentity <IdentityUser>() .AddOperationalStore(options => { options.RedisConnectionString = Configuration.GetConnectionString("RedisConnection"); }); var rsa = new RsaKeyService(Configuration["SigningCredentialFilePath"], TimeSpan.FromDays(30)); services.AddTransient(provider => rsa); builder.AddSigningCredential(rsa.GetKey()); services.AddAuthentication() .AddGoogle("Google", options => { var googleAuth = Configuration.GetSection("GoogleAuth"); options.ClientId = googleAuth["Id"]; options.ClientSecret = googleAuth["Secret"]; }); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { _identityConfig = Config.GetIdentityResources(); _apiConfig = Config.GetApiResources(Configuration); _clientConfig = Config.GetClients(Configuration); _publicOrigin = Config.GetPublicOrigin(Configuration); _cookieExpiration = Config.GetCookieExpirationByMinute(Configuration); var encConnStrMySql = Configuration.GetConnectionString("MySqlConnection(Azure)"); var connStrMySql = AesCryptoUtil.Decrypt(encConnStrMySql); Log.Information($"Connection String: {connStrMySql}"); services.AddDbContext <ApplicationDbContext>(option => option.UseMySQL(connStrMySql)); services.AddIdentity <ApplicationUser, IdentityRole>() .AddEntityFrameworkStores <ApplicationDbContext>() .AddDefaultTokenProviders(); services.AddCors(options => { options.AddPolicy(EmpWebOrigins, corsBuilder => { corsBuilder .AllowAnyHeader() // .WithHeaders(HeaderNames.AccessControlAllowHeaders, "Content-Type") // .AllowAnyOrigin() .WithOrigins( _clientConfig.First().AllowedCorsOrigins.ToArray() ) .AllowAnyMethod() // .WithMethods("GET", "PUT", "POST", "DELETE") .AllowCredentials(); }); }); services.AddMvc(); services.AddTransient <IProfileService, CustomProfileService>(); var builder = services.AddIdentityServer(options => { options.Events.RaiseErrorEvents = true; options.Events.RaiseInformationEvents = true; options.Events.RaiseFailureEvents = true; options.Events.RaiseSuccessEvents = true; options.Authentication.CheckSessionCookieName = "IDS4_EMP.Sts"; options.PublicOrigin = _publicOrigin; }) .AddInMemoryIdentityResources(_identityConfig) .AddInMemoryApiResources(_apiConfig) .AddInMemoryClients(_clientConfig) .AddAspNetIdentity <ApplicationUser>() .AddProfileService <CustomProfileService>(); services.ConfigureApplicationCookie(options => { // To prevent Refresh Access Token overriding cookie refreshe, subtract 1 minute options.ExpireTimeSpan = TimeSpan.FromMinutes(_cookieExpiration - 1); options.SlidingExpiration = true; options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest; }); if (_env.IsDevelopment()) { // builder.AddDeveloperSigningCredential(); var rsa = new RsaKeyService(_env, TimeSpan.FromDays(30), Configuration); services.AddSingleton <RsaKeyService>(provider => rsa); builder.AddSigningCredential(rsa.GetKey()); } else { var rsa = new RsaKeyService(_env, TimeSpan.FromDays(30), Configuration); services.AddSingleton <RsaKeyService>(provider => rsa); builder.AddSigningCredential(rsa.GetKey()); // services.AddIdentityServer(...).AddSigningCredential(new X509Certificate2(bytes, "password") // builder.AddSigningCredential(new X509Certificate2(bytes, "password"); } }
/// <summary> /// This optional method gets called by the runtime. Use this method to add services to the container. /// </summary> /// <param name="services">IServiceCollection</param> /// <method>ConfigureServices(IServiceCollection services)</method> public void ConfigureServices(IServiceCollection services) { // Register appsettings.json AppSettings appSettings = new AppSettings(); _configuration.Bind("AppSettings", appSettings); _appSettings = appSettings; services.AddSingleton(_appSettings); services.AddMvc(); services.AddControllersWithViews(); // Register IHttpContextAccessor services.TryAddSingleton <IHttpContextAccessor, HttpContextAccessor>(); // Register controller fillters services.AddScoped <SecurityHeadersAttribute>(); services.AddScoped <ControllerActionLogFilter>(); services.AddScoped <ControllerActionUserFilter>(); services.AddScoped <ControllerActionPageFilter>(); // Register RsaKeyService var rsa = new RsaKeyService(_webHostEnvironment, TimeSpan.FromDays(30)); services.AddSingleton <RsaKeyService>(provider => rsa); services.AddCustomUserStore(options => { options.ISDBaseUrl = appSettings.Application.ISDUrlTrim; options.ApiBaseUrl = appSettings.Application.ApiUrlTrim; options.ApiAccessToken = Config.ApiAccessToken; }); services.AddCustomRoleStore(options => { options.ISDBaseUrl = appSettings.Application.ISDUrlTrim; options.ApiBaseUrl = appSettings.Application.ApiUrlTrim; options.ApiAccessToken = Config.ApiAccessToken; }); services.AddEmailService(options => { options.Host = _appSettings.EmailService.Host; options.Port = _appSettings.EmailService.Port; options.EnableSsl = _appSettings.EmailService.EnableSsl; options.Credentials = new NetworkCredential( _appSettings.EmailService.UserId, _appSettings.EmailService.Password); }); services.AddIdentity <ApplicationUser, ApplicationRole>() .AddUserStore <CustomUserStore>() .AddRoleStore <CustomRoleStore>() .AddUserManager <CustomUserManager>() .AddDefaultTokenProviders(); services.Configure <DataProtectionTokenProviderOptions>( x => x.TokenLifespan = TimeSpan.FromMinutes(15) ); var builder = services.AddIdentityServer(options => { options.Events.RaiseErrorEvents = true; options.Events.RaiseInformationEvents = true; options.Events.RaiseFailureEvents = true; options.Events.RaiseSuccessEvents = true; options.EmitStaticAudienceClaim = true; options.KeyManagement.RotationInterval = TimeSpan.FromDays(15); options.KeyManagement.PropagationTime = TimeSpan.FromDays(2); options.KeyManagement.RetentionDuration = TimeSpan.FromDays(3); }) .AddAspNetIdentity <ApplicationUser>(); // in-memory, code config builder.AddInMemoryIdentityResources(Config.IdentityResources); builder.AddInMemoryApiScopes(Config.ApiScopes); builder.AddInMemoryClients(Config.Clients); // not recommended for production - you need to store your key material somewhere secure // builder.AddDeveloperSigningCredential(); // Duende IdentityServer defaults to automatic key management // see: https://docs.duendesoftware.com/identityserver/v5/fundamentals/keys/ //RsaSecurityKey key = rsa.GetKey(); //builder.AddValidationKey(key); //builder.AddSigningCredential(key, SecurityAlgorithms.RsaSha512); services.AddAuthentication() .AddMicrosoftAccount("Microsoft", microsoftOptions => { microsoftOptions.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; microsoftOptions.ClientId = appSettings.Authentication.Microsoft.ClientId; microsoftOptions.ClientSecret = appSettings.Authentication.Microsoft.ClientSecret; }) .AddGoogle("Google", googleOptions => { googleOptions.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; googleOptions.ClientId = appSettings.Authentication.Google.ClientId; googleOptions.ClientSecret = appSettings.Authentication.Google.ClientSecret; }) .AddGitHub("GitHub", githubOptions => { githubOptions.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; githubOptions.ClientId = appSettings.Authentication.GitHub.ClientId; githubOptions.ClientSecret = appSettings.Authentication.GitHub.ClientSecret; }) .AddTwitter("Twitter", twitterOptions => { twitterOptions.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; twitterOptions.ConsumerKey = appSettings.Authentication.Twitter.ConsumerAPIKey; twitterOptions.ConsumerSecret = appSettings.Authentication.Twitter.ConsumerSecret; twitterOptions.RetrieveUserDetails = true; }) .AddFacebook("Facebook", facebookOptions => { facebookOptions.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; facebookOptions.AppId = appSettings.Authentication.Facebook.AppId; facebookOptions.AppSecret = appSettings.Authentication.Facebook.AppSecret; }); // Override the CookieAuthenticationOptions for DefaultCookieAuthenticationScheme // https://github.com/IdentityServer/IdentityServer4/blob/c30de032ec1dedc3b17dfa342043850638e84b43/src/IdentityServer4/src/Configuration/DependencyInjection/ConfigureInternalCookieOptions.cs#L28 services.Configure <CookieAuthenticationOptions>(IdentityServerConstants.DefaultCookieAuthenticationScheme, options => { options.Cookie.SameSite = SameSiteMode.None; options.Cookie.SecurePolicy = CookieSecurePolicy.Always; options.Cookie.IsEssential = true; }); if (_webHostEnvironment.EnvironmentName.Equals("Production")) { services.AddHsts(options => { options.Preload = true; options.IncludeSubDomains = true; options.MaxAge = TimeSpan.FromDays(730); }); services.AddHttpsRedirection(options => { options.RedirectStatusCode = StatusCodes.Status308PermanentRedirect; options.HttpsPort = 443; }); } }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { var rsa = new RsaKeyService(_env, TimeSpan.FromDays(30)); services.AddSingleton(provider => rsa); services.AddDbContext <ApplicationDbContext>(options => options.UseInMemoryDatabase( Configuration.GetConnectionString("DefaultConnection"))); var connection = Configuration["ConnectionStrings:DefaultConnection"]; services.AddDbContext <ContextDb>(options => options.UseSqlServer(connection)); services.AddDatabaseDeveloperPageExceptionFilter(); services.AddDefaultIdentity <IdentityUser>(options => options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+/ ") .AddEntityFrameworkStores <ApplicationDbContext>(); services.AddControllersWithViews(); services.AddIdentityServer() .AddInMemoryIdentityResources(IdentityServerConfig.IdentityResources) .AddInMemoryApiScopes(IdentityServerConfig.ApiScopes) .AddInMemoryClients(IdentityServerConfig.Clients) .AddSigningCredential(rsa.GetKey(), RsaSigningAlgorithm.RS256); services .AddAuthentication(options => { options.DefaultScheme = IdentityConstants.ApplicationScheme; options.DefaultChallengeScheme = "oidc"; }) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => { options.LoginPath = new PathString("/Identity/Account/ExternalLogin"); }) .AddOpenIdConnect("oidc", options => { options.SignInScheme = IdentityConstants.ExternalScheme; options.SaveTokens = true; options.ClientId = Configuration["OpenIdConfig:ClientId"]; options.Authority = Configuration["OpenIdConfig:Issuer"]; // The Platform MUST send the id_token via the OAuth 2 Form Post // See https://www.imsglobal.org/spec/security/v1p0/#successful-authentication options.ResponseType = OpenIdConnectResponseType.IdToken; // See http://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html options.ResponseMode = OpenIdConnectResponseMode.FormPost; options.Prompt = OpenIdConnectPrompt.None; options.AuthenticationMethod = OpenIdConnectRedirectBehavior.RedirectGet; options.DisableTelemetry = true; options.Configuration = new OpenIdConnectConfiguration { AuthorizationEndpoint = Configuration["OpenIdConfig:AuthorizationEndpoint"], TokenEndpoint = Configuration["OpenIdConfig:TokenEndpoint"], Issuer = Configuration["OpenIdConfig:Issuer"], JwksUri = Configuration["OpenIdConfig:JwksUri"] }; options.CallbackPath = new PathString("/LtiTool"); options.Scope.Clear(); options.Scope.Add(OpenIdConnectScope.OpenId); options.Events = new OpenIdConnectEvents { //OnRemoteFailure = HandleOnRemoteFailure, // Authenticate the request starting at step 5 in the OpenId Implicit Flow // See https://www.imsglobal.org/spec/security/v1p0/#platform-originating-messages // See https://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowSteps OnRedirectToIdentityProvider = context => { if (context.Properties.Items.TryGetValue(nameof(OidcModel.LoginHint), out var login_hint)) { context.ProtocolMessage.LoginHint = login_hint; } if (context.Properties.Items.TryGetValue(nameof(OidcModel.LtiMessageHint), out var lti_message_hint)) { context.ProtocolMessage.SetParameter("lti_message_hint", lti_message_hint); } if (context.Properties.Items.TryGetValue(nameof(OidcModel.ClientId), out var clientId)) { context.ProtocolMessage.ClientId = clientId; } context.ProtocolMessage.Prompt = OpenIdConnectPrompt.None; if (context.Properties.Items.Count < 4) { context.Response.Redirect("Home/Index"); } return(Task.CompletedTask); }, }; // Using the options.TokenValidationParameters, validate four things: // // 1. The Issuer Identifier for the Platform MUST exactly match the value of the iss // (Issuer) Claim (therefore the Tool MUST previously have been made aware of this // identifier. // 2. The Tool MUST Validate the signature of the ID Token according to JSON Web Signature // RFC 7515, Section 5; using the Public Key for the Platform which collected offline. // 3. The Tool MUST validate that the aud (audience) Claim contains its client_id value // registered as an audience with the Issuer identified by the iss (Issuer) Claim. The // aud (audience) Claim MAY contain an array with more than one element. The Tool MUST // reject the ID Token if it does not list the client_id as a valid audience, or if it // contains additional audiences not trusted by the Tool. // 4. The current time MUST be before the time represented by the exp Claim; options.TokenValidationParameters = new TokenValidationParameters { ValidateTokenReplay = true, ValidateAudience = true, ValidateIssuer = true, RequireSignedTokens = true, ValidateIssuerSigningKey = true, ValidAudience = Configuration["OpenIdConfig:ClientId"], ValidIssuer = Configuration["OpenIdConfig:Issuer"], ValidateLifetime = true, IssuerSigningKeyResolver = (token, securityToken, kid, validationParameters) => { var keySetJson = new WebClient().DownloadString(Configuration["OpenIdConfig:JwksUri"]); var keySet = JsonConvert.DeserializeObject <JsonWebKeySet>(keySetJson); var key = keySet.Keys.SingleOrDefault(k => k.Kid == kid); return(new List <JsonWebKey> { key }); }, ClockSkew = TimeSpan.FromMinutes(5.0) }; }); services.AddSingleton(Configuration.GetSection("OpenIdConfig").Get <OidcModel>()); // Make AccessTokenService available for dependency injection. services.AddTransient <AccessTokenService>(); }
public void ConfigureServices(IServiceCollection services) { //IdentityModelEventSource.ShowPII = true; // Better Identity stacktraces and messages. (Insecure) services.AddDatabaseDeveloperPageExceptionFilter(); services.AddControllersWithViews(); services.AddDbContext <ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); services.AddIdentity <ApplicationUser, IdentityRole>() .AddEntityFrameworkStores <ApplicationDbContext>() .AddDefaultTokenProviders(); var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name; var builder = services.AddIdentityServer(options => { options.Events.RaiseErrorEvents = true; options.Events.RaiseInformationEvents = true; options.Events.RaiseFailureEvents = true; options.Events.RaiseSuccessEvents = true; // see https://identityserver4.readthedocs.io/en/latest/topics/resources.html options.EmitStaticAudienceClaim = true; options.IssuerUri = Configuration["Identity:IssuerUri"]; }) .AddConfigurationStore(options => // this adds the config data from DB (clients, resources) { options.ConfigureDbContext = builder => builder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), sql => sql.MigrationsAssembly(migrationsAssembly)); }) // this adds the operational data from DB (codes, tokens, consents) .AddOperationalStore(options => { options.ConfigureDbContext = builder => builder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), sql => sql.MigrationsAssembly(migrationsAssembly)); options.EnableTokenCleanup = true; // this enables automatic token cleanup. this is optional. options.TokenCleanupInterval = 30; }) .AddAspNetIdentity <ApplicationUser>() .AddProfileService <ProfileService>(); if (Environment.IsDevelopment()) { builder.AddDeveloperSigningCredential(); } else { var rsa = new RsaKeyService(Environment, TimeSpan.FromDays(30)); services.AddTransient <RsaKeyService>(provider => rsa); builder.AddSigningCredential(rsa.GetKey(), IdentityServerConstants.RsaSigningAlgorithm.RS512); } services.AddAuthentication() .AddGoogle(options => { options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; // register your IdentityServer with Google at https://console.developers.google.com // enable the Google+ API // set the redirect URI to http://identity:5000/signin-google options.ClientId = Configuration["Identity:Google:ClientId"]; options.ClientSecret = Configuration["Identity:Google:ClientSecret"]; }); services.AddSendGrid(options => // Use whatever email provider you want to. I use SendGrid, because it has a basic free plan to get started with. { options.ApiKey = Configuration["SendGridApiKey"]; }); services.AddTransient <IEmailService, EmailService>(); }
/// <summary> /// Create an instance of the AccessTokenService. /// </summary> /// <param name="context">The application database context to look up the issuer's token endpoint.</param> /// <param name="httpClientFactory">The HttpClient factory.</param> /// <param name-"rsaKeyService">RSA Key service</param> public AccessTokenService(IHttpClientFactory httpClientFactory, OidcModel oidcModel, RsaKeyService rsaKeyService) { _httpClientFactory = httpClientFactory; _oidcModel = oidcModel; _rsaKeyService = rsaKeyService; }