You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
216 lines
9.8 KiB
216 lines
9.8 KiB
using System;
|
|
using System.Threading.Tasks;
|
|
using AspNet.Security.OpenIdConnect.Primitives;
|
|
using Microsoft.AspNetCore.Builder;
|
|
using Microsoft.AspNetCore.Identity;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Mvc.Server.Models;
|
|
using Mvc.Server.Services;
|
|
using OpenIddict.Abstractions;
|
|
using OpenIddict.Core;
|
|
using OpenIddict.EntityFrameworkCore.Models;
|
|
|
|
namespace Mvc.Server
|
|
{
|
|
public class Startup
|
|
{
|
|
public Startup(IConfiguration configuration)
|
|
{
|
|
Configuration = configuration;
|
|
}
|
|
|
|
public IConfiguration Configuration { get; }
|
|
|
|
public void ConfigureServices(IServiceCollection services)
|
|
{
|
|
services.AddMvc();
|
|
|
|
services.AddDbContext<ApplicationDbContext>(options =>
|
|
{
|
|
// Configure the context to use Microsoft SQL Server.
|
|
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
|
|
|
|
// Register the entity sets needed by OpenIddict.
|
|
// Note: use the generic overload if you need
|
|
// to replace the default OpenIddict entities.
|
|
options.UseOpenIddict();
|
|
});
|
|
|
|
// Register the Identity services.
|
|
services.AddIdentity<ApplicationUser, IdentityRole>()
|
|
.AddEntityFrameworkStores<ApplicationDbContext>()
|
|
.AddDefaultTokenProviders();
|
|
|
|
// Configure Identity to use the same JWT claims as OpenIddict instead
|
|
// of the legacy WS-Federation claims it uses by default (ClaimTypes),
|
|
// which saves you from doing the mapping in your authorization controller.
|
|
services.Configure<IdentityOptions>(options =>
|
|
{
|
|
options.ClaimsIdentity.UserNameClaimType = OpenIdConnectConstants.Claims.Name;
|
|
options.ClaimsIdentity.UserIdClaimType = OpenIdConnectConstants.Claims.Subject;
|
|
options.ClaimsIdentity.RoleClaimType = OpenIdConnectConstants.Claims.Role;
|
|
});
|
|
|
|
services.AddAuthentication()
|
|
.AddGoogle(options =>
|
|
{
|
|
options.ClientId = "560027070069-37ldt4kfuohhu3m495hk2j4pjp92d382.apps.googleusercontent.com";
|
|
options.ClientSecret = "n2Q-GEw9RQjzcRbU3qhfTj8f";
|
|
})
|
|
|
|
.AddTwitter(options =>
|
|
{
|
|
options.ConsumerKey = "6XaCTaLbMqfj6ww3zvZ5g";
|
|
options.ConsumerSecret = "Il2eFzGIrYhz6BWjYhVXBPQSfZuS4xoHpSSyD9PI";
|
|
});
|
|
|
|
services.AddOpenIddict()
|
|
|
|
// Register the OpenIddict core services.
|
|
.AddCore(options =>
|
|
{
|
|
// Configure OpenIddict to use the Entity Framework Core stores and models.
|
|
options.UseEntityFrameworkCore()
|
|
.UseDbContext<ApplicationDbContext>();
|
|
})
|
|
|
|
// Register the OpenIddict server handler.
|
|
.AddServer(options =>
|
|
{
|
|
// 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.
|
|
options.AddMvcBinders();
|
|
|
|
// Enable the authorization, logout, token and userinfo endpoints.
|
|
options.EnableAuthorizationEndpoint("/connect/authorize")
|
|
.EnableLogoutEndpoint("/connect/logout")
|
|
.EnableTokenEndpoint("/connect/token")
|
|
.EnableUserinfoEndpoint("/api/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.
|
|
options.AllowAuthorizationCodeFlow()
|
|
.AllowPasswordFlow()
|
|
.AllowRefreshTokenFlow();
|
|
|
|
// Mark the "email", "profile" and "roles" scopes as supported scopes.
|
|
options.RegisterScopes(OpenIdConnectConstants.Scopes.Email,
|
|
OpenIdConnectConstants.Scopes.Profile,
|
|
OpenIddictConstants.Scopes.Roles);
|
|
|
|
// Make the "client_id" parameter mandatory when sending a token request.
|
|
options.RequireClientIdentification();
|
|
|
|
// 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.
|
|
options.EnableRequestCaching();
|
|
|
|
// Enable scope validation, so that authorization and token requests
|
|
// that specify unregistered scopes are automatically rejected.
|
|
options.EnableScopeValidation();
|
|
|
|
// During development, you can disable the HTTPS requirement.
|
|
options.DisableHttpsRequirement();
|
|
|
|
// Note: to use JWT access tokens instead of the default
|
|
// encrypted format, the following lines are required:
|
|
//
|
|
// options.UseJsonWebTokens();
|
|
// options.AddEphemeralSigningKey();
|
|
})
|
|
|
|
// Register the OpenIddict validation handler.
|
|
// Note: the OpenIddict validation handler is only compatible with the
|
|
// default token format or with reference tokens and cannot be used with
|
|
// JWT tokens. For JWT tokens, use the Microsoft JWT bearer handler.
|
|
.AddValidation();
|
|
|
|
services.AddTransient<IEmailSender, AuthMessageSender>();
|
|
services.AddTransient<ISmsSender, AuthMessageSender>();
|
|
}
|
|
|
|
public void Configure(IApplicationBuilder app)
|
|
{
|
|
app.UseDeveloperExceptionPage();
|
|
|
|
app.UseStaticFiles();
|
|
|
|
app.UseStatusCodePagesWithReExecute("/error");
|
|
|
|
app.UseAuthentication();
|
|
|
|
app.UseMvcWithDefaultRoute();
|
|
|
|
// Seed the database with the sample applications.
|
|
// Note: in a real world application, this step should be part of a setup script.
|
|
InitializeAsync(app.ApplicationServices).GetAwaiter().GetResult();
|
|
}
|
|
|
|
private async Task InitializeAsync(IServiceProvider services)
|
|
{
|
|
// Create a new service scope to ensure the database context is correctly disposed when this methods returns.
|
|
using (var scope = services.GetRequiredService<IServiceScopeFactory>().CreateScope())
|
|
{
|
|
var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
|
|
await context.Database.EnsureCreatedAsync();
|
|
|
|
var manager = scope.ServiceProvider.GetRequiredService<OpenIddictApplicationManager<OpenIddictApplication>>();
|
|
|
|
if (await manager.FindByClientIdAsync("mvc") == null)
|
|
{
|
|
var descriptor = new OpenIddictApplicationDescriptor
|
|
{
|
|
ClientId = "mvc",
|
|
ClientSecret = "901564A5-E7FE-42CB-B10D-61EF6A8F3654",
|
|
DisplayName = "MVC client application",
|
|
PostLogoutRedirectUris = { new Uri("http://localhost:53507/signout-callback-oidc") },
|
|
RedirectUris = { new Uri("http://localhost:53507/signin-oidc") },
|
|
Permissions =
|
|
{
|
|
OpenIddictConstants.Permissions.Endpoints.Authorization,
|
|
OpenIddictConstants.Permissions.Endpoints.Logout,
|
|
OpenIddictConstants.Permissions.Endpoints.Token,
|
|
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode,
|
|
OpenIddictConstants.Permissions.GrantTypes.RefreshToken
|
|
}
|
|
};
|
|
|
|
await manager.CreateAsync(descriptor);
|
|
}
|
|
|
|
// 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
|
|
if (await manager.FindByClientIdAsync("postman") == null)
|
|
{
|
|
var descriptor = new OpenIddictApplicationDescriptor
|
|
{
|
|
ClientId = "postman",
|
|
DisplayName = "Postman",
|
|
RedirectUris = { new Uri("https://www.getpostman.com/oauth2/callback") },
|
|
Permissions =
|
|
{
|
|
OpenIddictConstants.Permissions.Endpoints.Authorization,
|
|
OpenIddictConstants.Permissions.Endpoints.Token,
|
|
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode
|
|
}
|
|
};
|
|
|
|
await manager.CreateAsync(descriptor);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|