AuthServerDataSeeder.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. using Microsoft.Extensions.Configuration;
  2. using OpenIddict.Abstractions;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Diagnostics.CodeAnalysis;
  6. using System.Linq;
  7. using System.Threading.Tasks;
  8. using Volo.Abp;
  9. using Volo.Abp.Authorization.Permissions;
  10. using Volo.Abp.Data;
  11. using Volo.Abp.DependencyInjection;
  12. using Volo.Abp.Guids;
  13. using Volo.Abp.OpenIddict.Applications;
  14. using Volo.Abp.PermissionManagement;
  15. using Volo.Abp.Uow;
  16. namespace AuthServer
  17. {
  18. public class AuthServerDataSeeder : IDataSeedContributor, ITransientDependency
  19. {
  20. private readonly IConfiguration _configuration;
  21. private readonly IAbpApplicationManager _applicationManager;
  22. private readonly IOpenIddictScopeManager _scopeManager;
  23. private readonly IPermissionDataSeeder _permissionDataSeeder;
  24. public AuthServerDataSeeder(
  25. IConfiguration configuration,
  26. IAbpApplicationManager applicationManager,
  27. IOpenIddictScopeManager scopeManager,
  28. IPermissionDataSeeder permissionDataSeeder)
  29. {
  30. _configuration = configuration;
  31. _applicationManager = applicationManager;
  32. _scopeManager = scopeManager;
  33. _permissionDataSeeder = permissionDataSeeder;
  34. }
  35. [UnitOfWork]
  36. public virtual async Task SeedAsync(DataSeedContext context)
  37. {
  38. await CreateApiScopesAsync();
  39. await CreateApplicationsAsync();
  40. }
  41. private async Task CreateApiScopesAsync()
  42. {
  43. await CreateApiScopeAsync("BaseService");
  44. await CreateApiScopeAsync("InternalGateway");
  45. await CreateApiScopeAsync("WebAppGateway");
  46. await CreateApiScopeAsync("BusinessService");
  47. }
  48. private async Task CreateApiScopeAsync(string name)
  49. {
  50. if (await _scopeManager.FindByNameAsync(name) == null)
  51. {
  52. await _scopeManager.CreateAsync(new OpenIddictScopeDescriptor
  53. {
  54. Name = name,
  55. DisplayName = name + " API",
  56. Resources =
  57. {
  58. name
  59. }
  60. });
  61. }
  62. }
  63. private async Task CreateApplicationsAsync()
  64. {
  65. var commonScopes = new List<string>
  66. {
  67. OpenIddictConstants.Permissions.Scopes.Address,
  68. OpenIddictConstants.Permissions.Scopes.Email,
  69. OpenIddictConstants.Permissions.Scopes.Phone,
  70. OpenIddictConstants.Permissions.Scopes.Profile,
  71. OpenIddictConstants.Permissions.Scopes.Roles
  72. };
  73. var configurationSection = _configuration.GetSection("OpenIddict:Applications");
  74. //Vue Client
  75. var vueClientId = configurationSection["Web_App:ClientId"];
  76. if (!vueClientId.IsNullOrWhiteSpace())
  77. {
  78. var VueClientRootUrl = configurationSection["Web_App:RootUrl"]?.TrimEnd('/');
  79. var WebAppScopes = new List<string>()
  80. {
  81. "BaseService",
  82. "WebAppGateway",
  83. "BusinessService"
  84. };
  85. WebAppScopes.AddRange(commonScopes);
  86. await CreateApplicationAsync(
  87. name: vueClientId,
  88. type: OpenIddictConstants.ClientTypes.Public,
  89. consentType: OpenIddictConstants.ConsentTypes.Implicit,
  90. displayName: "Vue Application",
  91. secret: null,
  92. grantTypes: new List<string>
  93. {
  94. OpenIddictConstants.GrantTypes.AuthorizationCode,
  95. OpenIddictConstants.GrantTypes.Password,
  96. OpenIddictConstants.GrantTypes.ClientCredentials,
  97. OpenIddictConstants.GrantTypes.RefreshToken
  98. },
  99. scopes: WebAppScopes,
  100. redirectUri: VueClientRootUrl,
  101. clientUri: VueClientRootUrl,
  102. postLogoutRedirectUri: VueClientRootUrl
  103. );
  104. }
  105. // Blazor Client
  106. var blazorClientId = configurationSection["Blazor:ClientId"];
  107. if (!blazorClientId.IsNullOrWhiteSpace())
  108. {
  109. var blazorRootUrl = configurationSection["Blazor:RootUrl"].TrimEnd('/');
  110. var BlazorScopes = new List<string>()
  111. {
  112. "BaseService",
  113. "WebAppGateway",
  114. "BusinessService"
  115. };
  116. BlazorScopes.AddRange(commonScopes);
  117. await CreateApplicationAsync(
  118. name: blazorClientId,
  119. type: OpenIddictConstants.ClientTypes.Public,
  120. consentType: OpenIddictConstants.ConsentTypes.Implicit,
  121. displayName: "Blazor Application",
  122. secret: null,
  123. grantTypes: new List<string>
  124. {
  125. OpenIddictConstants.GrantTypes.AuthorizationCode,
  126. },
  127. scopes: BlazorScopes,
  128. redirectUri: $"{blazorRootUrl}/authentication/login-callback",
  129. clientUri: blazorRootUrl,
  130. postLogoutRedirectUri: $"{blazorRootUrl}/authentication/logout-callback"
  131. );
  132. }
  133. // Business Client
  134. var businessClientId = configurationSection["Business:ClientId"];
  135. if (!businessClientId.IsNullOrWhiteSpace())
  136. {
  137. var BusinessScopes = new List<string>()
  138. {
  139. "BaseService",
  140. "InternalGateway"
  141. };
  142. await CreateApplicationAsync(
  143. name: businessClientId,
  144. type: OpenIddictConstants.ClientTypes.Confidential,
  145. consentType: OpenIddictConstants.ConsentTypes.Implicit,
  146. displayName: "Business Application",
  147. secret: "1q2w3e*",
  148. grantTypes: new List<string>
  149. {
  150. OpenIddictConstants.GrantTypes.ClientCredentials,
  151. },
  152. scopes: BusinessScopes
  153. );
  154. }
  155. }
  156. private async Task CreateApplicationAsync(
  157. [NotNull] string name,
  158. [NotNull] string type,
  159. [NotNull] string consentType,
  160. string displayName,
  161. string secret,
  162. List<string> grantTypes,
  163. List<string> scopes,
  164. string clientUri = null,
  165. string redirectUri = null,
  166. string postLogoutRedirectUri = null,
  167. List<string> permissions = null)
  168. {
  169. if (!string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase))
  170. {
  171. throw new BusinessException("NoClientSecretCanBeSetForPublicApplications");
  172. }
  173. if (string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Confidential, StringComparison.OrdinalIgnoreCase))
  174. {
  175. throw new BusinessException("TheClientSecretIsRequiredForConfidentialApplications");
  176. }
  177. var client = await _applicationManager.FindByClientIdAsync(name);
  178. if (!string.IsNullOrEmpty(name) && await _applicationManager.FindByClientIdAsync(name) != null)
  179. {
  180. return;
  181. }
  182. //var client = await _applicationManager.FindByClientIdAsync(name);
  183. if (client == null)
  184. {
  185. var application = new AbpApplicationDescriptor
  186. {
  187. ClientId = name,
  188. Type = type,
  189. ClientSecret = secret,
  190. ConsentType = consentType,
  191. DisplayName = displayName,
  192. ClientUri = clientUri,
  193. };
  194. Check.NotNullOrEmpty(grantTypes, nameof(grantTypes));
  195. Check.NotNullOrEmpty(scopes, nameof(scopes));
  196. if (new[] { OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.Implicit }.All(grantTypes.Contains))
  197. {
  198. application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken);
  199. if (string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase))
  200. {
  201. application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken);
  202. application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeToken);
  203. }
  204. }
  205. if (!redirectUri.IsNullOrWhiteSpace() || !postLogoutRedirectUri.IsNullOrWhiteSpace())
  206. {
  207. application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Logout);
  208. }
  209. foreach (var grantType in grantTypes)
  210. {
  211. if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode)
  212. {
  213. application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode);
  214. application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Code);
  215. }
  216. if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode || grantType == OpenIddictConstants.GrantTypes.Implicit)
  217. {
  218. application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Authorization);
  219. }
  220. if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode ||
  221. grantType == OpenIddictConstants.GrantTypes.ClientCredentials ||
  222. grantType == OpenIddictConstants.GrantTypes.Password ||
  223. grantType == OpenIddictConstants.GrantTypes.RefreshToken ||
  224. grantType == OpenIddictConstants.GrantTypes.DeviceCode)
  225. {
  226. application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Token);
  227. application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Revocation);
  228. application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Introspection);
  229. }
  230. if (grantType == OpenIddictConstants.GrantTypes.ClientCredentials)
  231. {
  232. application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.ClientCredentials);
  233. }
  234. if (grantType == OpenIddictConstants.GrantTypes.Implicit)
  235. {
  236. application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Implicit);
  237. }
  238. if (grantType == OpenIddictConstants.GrantTypes.Password)
  239. {
  240. application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Password);
  241. }
  242. if (grantType == OpenIddictConstants.GrantTypes.RefreshToken)
  243. {
  244. application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.RefreshToken);
  245. }
  246. if (grantType == OpenIddictConstants.GrantTypes.DeviceCode)
  247. {
  248. application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.DeviceCode);
  249. application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Device);
  250. }
  251. if (grantType == OpenIddictConstants.GrantTypes.Implicit)
  252. {
  253. application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdToken);
  254. if (string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase))
  255. {
  256. application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken);
  257. application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Token);
  258. }
  259. }
  260. }
  261. var buildInScopes = new[]
  262. {
  263. OpenIddictConstants.Permissions.Scopes.Address,
  264. OpenIddictConstants.Permissions.Scopes.Email,
  265. OpenIddictConstants.Permissions.Scopes.Phone,
  266. OpenIddictConstants.Permissions.Scopes.Profile,
  267. OpenIddictConstants.Permissions.Scopes.Roles
  268. };
  269. foreach (var scope in scopes)
  270. {
  271. if (buildInScopes.Contains(scope))
  272. {
  273. application.Permissions.Add(scope);
  274. }
  275. else
  276. {
  277. application.Permissions.Add(OpenIddictConstants.Permissions.Prefixes.Scope + scope);
  278. }
  279. }
  280. if (redirectUri != null)
  281. {
  282. if (!redirectUri.IsNullOrEmpty())
  283. {
  284. if (!Uri.TryCreate(redirectUri, UriKind.Absolute, out var uri) || !uri.IsWellFormedOriginalString())
  285. {
  286. throw new BusinessException("InvalidRedirectUri", redirectUri);
  287. }
  288. if (application.RedirectUris.All(x => x != uri))
  289. {
  290. application.RedirectUris.Add(uri);
  291. }
  292. }
  293. }
  294. if (postLogoutRedirectUri != null)
  295. {
  296. if (!postLogoutRedirectUri.IsNullOrEmpty())
  297. {
  298. if (!Uri.TryCreate(postLogoutRedirectUri, UriKind.Absolute, out var uri) || !uri.IsWellFormedOriginalString())
  299. {
  300. throw new BusinessException("InvalidPostLogoutRedirectUri", postLogoutRedirectUri);
  301. }
  302. if (application.PostLogoutRedirectUris.All(x => x != uri))
  303. {
  304. application.PostLogoutRedirectUris.Add(uri);
  305. }
  306. }
  307. }
  308. if (permissions != null)
  309. {
  310. await _permissionDataSeeder.SeedAsync(
  311. ClientPermissionValueProvider.ProviderName,
  312. name,
  313. permissions,
  314. null
  315. );
  316. }
  317. await _applicationManager.CreateAsync(application);
  318. }
  319. }
  320. }
  321. }