using System; using System.Linq; using AspNet.Security.OAuth.GitHub; using CryptoHelper; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; 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.AddEntityFramework() .AddEntityFrameworkSqlServer() .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, ApplicationDbContext, Guid>() // Register the HTML/CSS assets and MVC modules to handle the interactive flows. // Note: these modules are not necessary when using your own authorization controller // or when using non-interactive flows-only like the resource owner password credentials grant. .AddAssets() .AddMvc() // Register the NWebsec module. Note: you can replace the default Content Security Policy (CSP) // by calling UseNWebsec with a custom delegate instead of using the parameterless extension. // This can be useful to allow your HTML views to reference remote scripts/images/styles. .AddNWebsec(options => options.DefaultSources(directive => directive.Self()) .ImageSources(directive => directive.Self() .CustomSources("*")) .ScriptSources(directive => directive.Self() .UnsafeInline() .CustomSources("https://my.custom.url/")) .StyleSources(directive => directive.Self() .UnsafeInline())) // During development, you can disable the HTTPS requirement. .DisableHttpsRequirement(); // When using your own authorization controller instead of using the // MVC module, you need to configure the authorization/logout paths: // services.AddOpenIddict() // .SetAuthorizationEndpointPath("/connect/authorize") // .SetLogoutEndpointPath("/connect/logout"); // Note: if you don't explicitly register a signing key, one is automatically generated and // persisted on the disk. If the key cannot be persisted, an in-memory key is used instead: // when the application shuts down, the key is definitely lost and the access/identity tokens // will be considered as invalid by client applications/resource servers when validating them. // // 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.UseIdentity(); app.UseGoogleAuthentication(new GoogleOptions { ClientId = "560027070069-37ldt4kfuohhu3m495hk2j4pjp92d382.apps.googleusercontent.com", ClientSecret = "n2Q-GEw9RQjzcRbU3qhfTj8f" }); app.UseTwitterAuthentication(new TwitterOptions { ConsumerKey = "6XaCTaLbMqfj6ww3zvZ5g", ConsumerSecret = "Il2eFzGIrYhz6BWjYhVXBPQSfZuS4xoHpSSyD9PI" }); app.UseGitHubAuthentication(new GitHubAuthenticationOptions { ClientId = "49e302895d8b09ea5656", ClientSecret = "98f1bf028608901e9df91d64ee61536fe562064b", Scope = { "user:email" } }); 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(); } } } } }