using System.Linq; using CryptoHelper; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Mvc.Server.Models; using Mvc.Server.Services; using NWebsec.AspNetCore.Middleware; using OpenIddict; namespace Mvc.Server { public class Startup { public void ConfigureServices(IServiceCollection services) { var configuration = new ConfigurationBuilder() .AddJsonFile("config.json") .AddEnvironmentVariables() .Build(); services.AddMvc(); services.AddDbContext(options => options.UseSqlServer(configuration["Data:DefaultConnection:ConnectionString"])); // Register the Identity services. services.AddIdentity() .AddEntityFrameworkStores() .AddDefaultTokenProviders(); // Register the OpenIddict services, including the default Entity Framework stores. services.AddOpenIddict() // Register the ASP.NET Core MVC binder used by OpenIddict. // Note: if you don't call this method, you won't be able to // bind OpenIdConnectRequest or OpenIdConnectResponse parameters. .AddMvcBinders() // Enable the authorization, logout, token and userinfo endpoints. .EnableAuthorizationEndpoint("/connect/authorize") .EnableLogoutEndpoint("/connect/logout") .EnableTokenEndpoint("/connect/token") .EnableUserinfoEndpoint("/Account/Userinfo") // Note: the Mvc.Client sample only uses the code flow and the password flow, but you // can enable the other flows if you need to support implicit or client credentials. .AllowAuthorizationCodeFlow() .AllowPasswordFlow() .AllowRefreshTokenFlow() // Make the "client_id" parameter mandatory when sending a token request. .RequireClientIdentification() // During development, you can disable the HTTPS requirement. .DisableHttpsRequirement() // When request caching is enabled, authorization and logout requests // are stored in the distributed cache by OpenIddict and the user agent // is redirected to the same page with a single parameter (request_id). // This allows flowing large OpenID Connect requests even when using // an external authentication provider like Google, Facebook or Twitter. .EnableRequestCaching() // Register a new ephemeral key, that is discarded when the application // shuts down. Tokens signed using this key are automatically invalidated. // This method should only be used during development. .AddEphemeralSigningKey(); // On production, using a X.509 certificate stored in the machine store is recommended. // You can generate a self-signed certificate using Pluralsight's self-cert utility: // https://s3.amazonaws.com/pluralsight-free/keith-brown/samples/SelfCert.zip // // services.AddOpenIddict() // .AddSigningCertificate("7D2A741FE34CC2C7369237A5F2078988E17A6A75"); // // Alternatively, you can also store the certificate as an embedded .pfx resource // directly in this assembly or in a file published alongside this project: // // services.AddOpenIddict() // .AddSigningCertificate( // assembly: typeof(Startup).GetTypeInfo().Assembly, // resource: "Mvc.Server.Certificate.pfx", // password: "OpenIddict"); services.AddTransient(); services.AddTransient(); } public void Configure(IApplicationBuilder app) { app.UseDeveloperExceptionPage(); app.UseStaticFiles(); // Add a middleware used to validate access // tokens and protect the API endpoints. app.UseOAuthValidation(); // Alternatively, you can also use the introspection middleware. // Using it is recommended if your resource server is in a // different application/separated from the authorization server. // // app.UseOAuthIntrospection(options => { // options.AutomaticAuthenticate = true; // options.AutomaticChallenge = true; // options.Authority = "http://localhost:54540/"; // options.Audience = "resource_server"; // options.ClientId = "resource_server"; // options.ClientSecret = "875sqd4s5d748z78z7ds1ff8zz8814ff88ed8ea4z4zzd"; // }); app.UseCsp(options => options.DefaultSources(directive => directive.Self()) .ImageSources(directive => directive.Self() .CustomSources("*")) .ScriptSources(directive => directive.Self() .UnsafeInline()) .StyleSources(directive => directive.Self() .UnsafeInline())); app.UseXContentTypeOptions(); app.UseXfo(options => options.Deny()); app.UseXXssProtection(options => options.EnabledWithBlockMode()); app.UseIdentity(); app.UseGoogleAuthentication(new GoogleOptions { ClientId = "560027070069-37ldt4kfuohhu3m495hk2j4pjp92d382.apps.googleusercontent.com", ClientSecret = "n2Q-GEw9RQjzcRbU3qhfTj8f" }); app.UseTwitterAuthentication(new TwitterOptions { ConsumerKey = "6XaCTaLbMqfj6ww3zvZ5g", ConsumerSecret = "Il2eFzGIrYhz6BWjYhVXBPQSfZuS4xoHpSSyD9PI" }); app.UseStatusCodePagesWithReExecute("/error"); app.UseOpenIddict(); app.UseMvcWithDefaultRoute(); using (var context = new ApplicationDbContext( app.ApplicationServices.GetRequiredService>())) { context.Database.EnsureCreated(); // Add Mvc.Client to the known applications. if (!context.Applications.Any()) { // Note: when using the introspection middleware, your resource server // MUST be registered as an OAuth2 client and have valid credentials. // // context.Applications.Add(new OpenIddictApplication { // Id = "resource_server", // DisplayName = "Main resource server", // Secret = Crypto.HashPassword("secret_secret_secret"), // Type = OpenIddictConstants.ClientTypes.Confidential // }); context.Applications.Add(new OpenIddictApplication { ClientId = "myClient", ClientSecret = Crypto.HashPassword("secret_secret_secret"), DisplayName = "My client application", LogoutRedirectUri = "http://localhost:53507/", RedirectUri = "http://localhost:53507/signin-oidc", Type = OpenIddictConstants.ClientTypes.Confidential }); // To test this sample with Postman, use the following settings: // // * Authorization URL: http://localhost:54540/connect/authorize // * Access token URL: http://localhost:54540/connect/token // * Client ID: postman // * Client secret: [blank] (not used with public clients) // * Scope: openid email profile roles // * Grant type: authorization code // * Request access token locally: yes context.Applications.Add(new OpenIddictApplication { ClientId = "postman", DisplayName = "Postman", RedirectUri = "https://www.getpostman.com/oauth2/callback", Type = OpenIddictConstants.ClientTypes.Public }); context.SaveChanges(); } } } } }