|
|
using System;using System.Collections.Generic;using System.Linq;using System.Runtime.Intrinsics.Arm;using System.Security.Cryptography;using System.Text;using System.Text.Json;using System.Threading.Tasks;using JetBrains.Annotations;using Microsoft.Extensions.Configuration;using Microsoft.Extensions.Localization;using OpenIddict.Abstractions;using Shentun.WebPeis.Enums;using Volo.Abp;using Volo.Abp.Authorization.Permissions;using Volo.Abp.Data;using Volo.Abp.DependencyInjection;using Volo.Abp.OpenIddict.Applications;using Volo.Abp.OpenIddict.Scopes;using Volo.Abp.PermissionManagement;using Volo.Abp.Uow;
namespace Shentun.WebPeis.OpenIddict;
/* Creates initial data that is needed to property run the application * and make client-to-server communication possible. */public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDependency{ private readonly IConfiguration _configuration; private readonly IOpenIddictApplicationRepository _openIddictApplicationRepository; private readonly IAbpApplicationManager _applicationManager; private readonly IOpenIddictScopeRepository _openIddictScopeRepository; private readonly IOpenIddictScopeManager _scopeManager; private readonly IPermissionDataSeeder _permissionDataSeeder; private readonly IStringLocalizer<OpenIddictResponse> L;
public OpenIddictDataSeedContributor( IConfiguration configuration, IOpenIddictApplicationRepository openIddictApplicationRepository, IAbpApplicationManager applicationManager, IOpenIddictScopeRepository openIddictScopeRepository, IOpenIddictScopeManager scopeManager, IPermissionDataSeeder permissionDataSeeder, IStringLocalizer<OpenIddictResponse> l) { _configuration = configuration; _openIddictApplicationRepository = openIddictApplicationRepository; _applicationManager = applicationManager; _openIddictScopeRepository = openIddictScopeRepository; _scopeManager = scopeManager; _permissionDataSeeder = permissionDataSeeder; L = l; }
[UnitOfWork] public virtual async Task SeedAsync(DataSeedContext context) { await CreateScopesAsync(); await CreateApplicationsAsync(); }
private async Task CreateScopesAsync() { if (await _openIddictScopeRepository.FindByNameAsync("WebPeis") == null) { await _scopeManager.CreateAsync(new OpenIddictScopeDescriptor { Name = "WebPeis", DisplayName = "WebPeis API", Resources = { "WebPeis" } }); } }
private async Task CreateApplicationsAsync() { var commonScopes = new List<string> { OpenIddictConstants.Permissions.Scopes.Address, OpenIddictConstants.Permissions.Scopes.Email, OpenIddictConstants.Permissions.Scopes.Phone, OpenIddictConstants.Permissions.Scopes.Profile, OpenIddictConstants.Permissions.Scopes.Roles, "WebPeis" };
var configurationSection = _configuration.GetSection("OpenIddict:Applications");
// Swagger Client
var swaggerClientId = configurationSection["WebPeis_Swagger:ClientId"]; if (!swaggerClientId.IsNullOrWhiteSpace()) { var swaggerRootUrl = configurationSection["WebPeis_Swagger:RootUrl"]?.TrimEnd('/');
await CreateApplicationAsync( name: swaggerClientId!, type: OpenIddictConstants.ClientTypes.Public, consentType: OpenIddictConstants.ConsentTypes.Implicit, displayName: "Swagger Application", secret: null, grantTypes: new List<string> { OpenIddictConstants.GrantTypes.AuthorizationCode, }, scopes: commonScopes, redirectUri: $"{swaggerRootUrl}/swagger/oauth2-redirect.html", clientUri: swaggerRootUrl ); } var weChatClientId = configurationSection.GetSection("WeChatApp").GetSection("ClientId").Value; var secret = configurationSection.GetSection("WeChatApp").GetSection("ClientSecret").Value; if(string.IsNullOrWhiteSpace(secret)) { throw new Exception("secret不能为空"); } //secret = GetSha256Hash(secret);
secret = null; if (!string.IsNullOrWhiteSpace(weChatClientId)) { var swaggerRootUrl = configurationSection["WebPeis_Swagger:RootUrl"]?.TrimEnd('/'); await CreateApplicationAsync( name: weChatClientId!, type: OpenIddictConstants.ClientTypes.Public, consentType: OpenIddictConstants.ConsentTypes.Implicit, displayName: "WeChat Application", secret: secret, grantTypes: new List<string> { OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.Password, OpenIddictConstants.GrantTypes.ClientCredentials, OpenIddictConstants.GrantTypes.RefreshToken, WeChatGrant.GrantType }, scopes: commonScopes, redirectUri: $"{swaggerRootUrl}/swagger/oauth2-redirect.html", clientUri: swaggerRootUrl ); } }
private async Task CreateApplicationAsync( [NotNull] string name, [NotNull] string type, [NotNull] string consentType, string displayName, string? secret, List<string> grantTypes, List<string> scopes, string? clientUri = null, string? redirectUri = null, string? postLogoutRedirectUri = null, List<string>? permissions = null) { if (!string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) { throw new BusinessException(L["NoClientSecretCanBeSetForPublicApplications"]); }
if (string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Confidential, StringComparison.OrdinalIgnoreCase)) { throw new BusinessException(L["TheClientSecretIsRequiredForConfidentialApplications"]); }
var client = await _openIddictApplicationRepository.FindByClientIdAsync(name);
var application = new AbpApplicationDescriptor { ClientId = name, ClientType = type, ClientSecret = secret, ConsentType = consentType, DisplayName = displayName, ClientUri = clientUri, };
Check.NotNullOrEmpty(grantTypes, nameof(grantTypes)); Check.NotNullOrEmpty(scopes, nameof(scopes));
if (new[] { OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.Implicit }.All( grantTypes.Contains)) { application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken);
if (string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) { application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken); application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeToken); } }
if (!redirectUri.IsNullOrWhiteSpace() || !postLogoutRedirectUri.IsNullOrWhiteSpace()) { application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Logout); }
var buildInGrantTypes = new[] { OpenIddictConstants.GrantTypes.Implicit, OpenIddictConstants.GrantTypes.Password, OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.ClientCredentials, OpenIddictConstants.GrantTypes.DeviceCode, OpenIddictConstants.GrantTypes.RefreshToken };
foreach (var grantType in grantTypes) { if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode) { application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode); application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Code); }
if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode || grantType == OpenIddictConstants.GrantTypes.Implicit) { application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Authorization); }
if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode || grantType == OpenIddictConstants.GrantTypes.ClientCredentials || grantType == OpenIddictConstants.GrantTypes.Password || grantType == OpenIddictConstants.GrantTypes.RefreshToken || grantType == OpenIddictConstants.GrantTypes.DeviceCode) { application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Token); application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Revocation); application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Introspection); }
if (grantType == OpenIddictConstants.GrantTypes.ClientCredentials) { application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.ClientCredentials); }
if (grantType == OpenIddictConstants.GrantTypes.Implicit) { application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Implicit); }
if (grantType == OpenIddictConstants.GrantTypes.Password) { application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Password); }
if (grantType == OpenIddictConstants.GrantTypes.RefreshToken) { application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.RefreshToken); }
if (grantType == OpenIddictConstants.GrantTypes.DeviceCode) { application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.DeviceCode); application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Device); }
if (grantType == OpenIddictConstants.GrantTypes.Implicit) { application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdToken); if (string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) { application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken); application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Token); } }
if (!buildInGrantTypes.Contains(grantType)) { application.Permissions.Add(OpenIddictConstants.Permissions.Prefixes.GrantType + grantType); } }
var buildInScopes = new[] { OpenIddictConstants.Permissions.Scopes.Address, OpenIddictConstants.Permissions.Scopes.Email, OpenIddictConstants.Permissions.Scopes.Phone, OpenIddictConstants.Permissions.Scopes.Profile, OpenIddictConstants.Permissions.Scopes.Roles };
foreach (var scope in scopes) { if (buildInScopes.Contains(scope)) { application.Permissions.Add(scope); } else { application.Permissions.Add(OpenIddictConstants.Permissions.Prefixes.Scope + scope); } }
if (redirectUri != null) { if (!redirectUri.IsNullOrEmpty()) { if (!Uri.TryCreate(redirectUri, UriKind.Absolute, out var uri) || !uri.IsWellFormedOriginalString()) { throw new BusinessException(L["InvalidRedirectUri", redirectUri]); }
if (application.RedirectUris.All(x => x != uri)) { application.RedirectUris.Add(uri); } } }
if (postLogoutRedirectUri != null) { if (!postLogoutRedirectUri.IsNullOrEmpty()) { if (!Uri.TryCreate(postLogoutRedirectUri, UriKind.Absolute, out var uri) || !uri.IsWellFormedOriginalString()) { throw new BusinessException(L["InvalidPostLogoutRedirectUri", postLogoutRedirectUri]); }
if (application.PostLogoutRedirectUris.All(x => x != uri)) { application.PostLogoutRedirectUris.Add(uri); } } }
if (permissions != null) { await _permissionDataSeeder.SeedAsync( ClientPermissionValueProvider.ProviderName, name, permissions, null ); }
if (client == null) { await _applicationManager.CreateAsync(application); return; }
if (!HasSameRedirectUris(client, application)) { client.RedirectUris = JsonSerializer.Serialize(application.RedirectUris.Select(q => q.ToString().TrimEnd('/'))); client.PostLogoutRedirectUris = JsonSerializer.Serialize(application.PostLogoutRedirectUris.Select(q => q.ToString().TrimEnd('/')));
await _applicationManager.UpdateAsync(client.ToModel()); }
if (!HasSameScopes(client, application)) { client.Permissions = JsonSerializer.Serialize(application.Permissions.Select(q => q.ToString())); await _applicationManager.UpdateAsync(client.ToModel()); } }
private bool HasSameRedirectUris(OpenIddictApplication existingClient, AbpApplicationDescriptor application) { return existingClient.RedirectUris == JsonSerializer.Serialize(application.RedirectUris.Select(q => q.ToString().TrimEnd('/'))); }
private bool HasSameScopes(OpenIddictApplication existingClient, AbpApplicationDescriptor application) { return existingClient.Permissions == JsonSerializer.Serialize(application.Permissions.Select(q => q.ToString().TrimEnd('/'))); }
private static string GetSha256Hash(string input) { using (SHA256 sha256Hash = SHA256.Create()) { byte[] bytes = Encoding.UTF8.GetBytes(input); return Convert.ToBase64String(((HashAlgorithm)sha256Hash).ComputeHash(bytes));
} }}
|