Skip to content

Commit 423f7b1

Browse files
Ticket #851 : Create a library to import data from the openiddict storage
1 parent b2cff10 commit 423f7b1

24 files changed

Lines changed: 605 additions & 167 deletions

SimpleIdServer.IdServer.Host.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleIdServer.IdServer.Mig
173173
EndProject
174174
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleIdServer.IdServer.Migrations", "src\IdServer\SimpleIdServer.IdServer.Migrations\SimpleIdServer.IdServer.Migrations.csproj", "{1C89FFB2-6054-73EC-8DFE-B97CC1C7B55B}"
175175
EndProject
176+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleIdServer.IdServer.Migrations.Openiddict", "src\IdServer\SimpleIdServer.IdServer.Migrations.Openiddict\SimpleIdServer.IdServer.Migrations.Openiddict.csproj", "{7BABE6E4-5F4B-7A0D-9FF2-FA97AA9BE01D}"
177+
EndProject
176178
Global
177179
GlobalSection(SolutionConfigurationPlatforms) = preSolution
178180
Debug|Any CPU = Debug|Any CPU
@@ -447,6 +449,10 @@ Global
447449
{1C89FFB2-6054-73EC-8DFE-B97CC1C7B55B}.Debug|Any CPU.Build.0 = Debug|Any CPU
448450
{1C89FFB2-6054-73EC-8DFE-B97CC1C7B55B}.Release|Any CPU.ActiveCfg = Release|Any CPU
449451
{1C89FFB2-6054-73EC-8DFE-B97CC1C7B55B}.Release|Any CPU.Build.0 = Release|Any CPU
452+
{7BABE6E4-5F4B-7A0D-9FF2-FA97AA9BE01D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
453+
{7BABE6E4-5F4B-7A0D-9FF2-FA97AA9BE01D}.Debug|Any CPU.Build.0 = Debug|Any CPU
454+
{7BABE6E4-5F4B-7A0D-9FF2-FA97AA9BE01D}.Release|Any CPU.ActiveCfg = Release|Any CPU
455+
{7BABE6E4-5F4B-7A0D-9FF2-FA97AA9BE01D}.Release|Any CPU.Build.0 = Release|Any CPU
450456
EndGlobalSection
451457
GlobalSection(SolutionProperties) = preSolution
452458
HideSolutionNode = FALSE
@@ -533,6 +539,7 @@ Global
533539
{E3ED0DEE-B9BE-4A44-918E-78AF07F8CC13} = {4796A22B-91A9-42AF-87CA-F69392696B0A}
534540
{A6C36FE3-F338-477B-E160-360D44D30D43} = {E3ED0DEE-B9BE-4A44-918E-78AF07F8CC13}
535541
{1C89FFB2-6054-73EC-8DFE-B97CC1C7B55B} = {E3ED0DEE-B9BE-4A44-918E-78AF07F8CC13}
542+
{7BABE6E4-5F4B-7A0D-9FF2-FA97AA9BE01D} = {E3ED0DEE-B9BE-4A44-918E-78AF07F8CC13}
536543
EndGlobalSection
537544
GlobalSection(ExtensibilityGlobals) = postSolution
538545
SolutionGuid = {1FE1E2C8-475E-4592-8609-D331B1D01730}

default.ps1

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,9 @@ task pack -depends release, compile, buildTemplate {
245245
exec { dotnet pack $source_dir\IdServer\SimpleIdServer.IdServer.IntegrationEvents\SimpleIdServer.IdServer.IntegrationEvents.csproj -c $config --output $result_dir }
246246
exec { dotnet pack $source_dir\IdServer\SimpleIdServer.IdServer.OpenTelemetry\SimpleIdServer.IdServer.OpenTelemetry.csproj -c $config --output $result_dir }
247247
exec { dotnet pack $source_dir\IdServer\SimpleIdServer.IdServer.Website.OpenTelemetry\SimpleIdServer.IdServer.Website.OpenTelemetry.csproj -c $config --output $result_dir }
248+
exec { dotnet pack $source_dir\IdServer\SimpleIdServer.IdServer.Migrations\SimpleIdServer.IdServer.Migrations.csproj -c $config --output $result_dir }
249+
exec { dotnet pack $source_dir\IdServer\SimpleIdServer.IdServer.Migrations.Duende\SimpleIdServer.IdServer.Migrations.Duende.csproj -c $config --output $result_dir }
250+
exec { dotnet pack $source_dir\IdServer\SimpleIdServer.IdServer.Migrations.Openiddict\SimpleIdServer.IdServer.Migrations.Openiddict.csproj -c $config --output $result_dir }
248251

249252
exec { dotnet pack $source_dir\Scim\SimpleIdServer.Scim\SimpleIdServer.Scim.csproj -c $config --output $result_dir }
250253
exec { dotnet pack $source_dir\Scim\SimpleIdServer.Scim.Domains\SimpleIdServer.Scim.Domains.csproj -c $config --output $result_dir }

src/IdServer/SimpleIdServer.IdServer.Domains/ClientSecret.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,13 @@ public static ClientSecret Resolve(string str)
105105
{
106106
alg = _mappingAlgToSize.Single(kvp => kvp.Value == size).Key;
107107
}
108-
108+
else
109+
{
110+
if (payload[0] == 0x01)
111+
{
112+
alg = HashAlgs.PBKDF2;
113+
}
114+
}
109115
}
110116

111117
return new ClientSecret
@@ -146,5 +152,6 @@ public enum HashAlgs
146152
SHA1 = 2,
147153
SHA256 = 3,
148154
SHA384 = 4,
149-
SHA512 = 5
155+
SHA512 = 5,
156+
PBKDF2 = 6
150157
}

src/IdServer/SimpleIdServer.IdServer.Domains/SimpleIdServer.IdServer.Domains.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
<Description>Domains of the Identity Server project.</Description>
77
</PropertyGroup>
88
<ItemGroup>
9-
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.1.2" />
10-
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.1.2" />
9+
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.10.0" />
10+
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.10.0" />
1111
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
1212
</ItemGroup>
1313
<ItemGroup>

src/IdServer/SimpleIdServer.IdServer.Migrations.Duende/ApplicationDbContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
namespace SimpleIdServer.IdServer.Migrations.Duende;
77

8-
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
8+
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IApplicationDbContext
99
{
1010
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
1111
: base(options)

src/IdServer/SimpleIdServer.IdServer.Migrations.Duende/DuendeMigrationService.cs

Lines changed: 15 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// Copyright (c) SimpleIdServer. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
33
using Duende.IdentityServer.EntityFramework.DbContexts;
4-
using Microsoft.AspNetCore.Identity;
54
using Microsoft.EntityFrameworkCore;
65
using Microsoft.IdentityModel.Tokens;
76
using SimpleIdServer.IdServer.Api.Authorization.ResponseTypes;
@@ -10,7 +9,6 @@
109
using SimpleIdServer.IdServer.Config;
1110
using SimpleIdServer.IdServer.Domains;
1211
using SimpleIdServer.IdServer.Stores;
13-
using System.IdentityModel.Tokens.Jwt;
1412
using DPoPTokenExpirationValidationMode = Duende.IdentityServer.Models.DPoPTokenExpirationValidationMode;
1513
using DuendeAccessTokenType = Duende.IdentityServer.Models.AccessTokenType;
1614
using DuendeApiResource = Duende.IdentityServer.EntityFramework.Entities.ApiResource;
@@ -19,29 +17,28 @@
1917
using DuendeIdentityResource = Duende.IdentityServer.EntityFramework.Entities.IdentityResource;
2018
namespace SimpleIdServer.IdServer.Migrations.Duende;
2119

22-
public class DuendeMigrationService : IMigrationService
20+
public class DuendeMigrationService : BaseMicrosoftIdentityMigrationService
2321
{
24-
public string Name => Constants.Name;
2522
private readonly ConfigurationDbContext _configurationDbcontext;
26-
private readonly ApplicationDbContext _applicationDbcontext;
2723
private readonly IScopeRepository _scopeRepository;
2824

2925
public DuendeMigrationService(
3026
ConfigurationDbContext configurationDbcontext,
3127
ApplicationDbContext applicationDbcontext,
32-
IScopeRepository scopeRepository)
28+
IScopeRepository scopeRepository) : base(applicationDbcontext)
3329
{
3430
_configurationDbcontext = configurationDbcontext;
35-
_applicationDbcontext = applicationDbcontext;
3631
_scopeRepository = scopeRepository;
3732
}
3833

39-
public Task<int> NbApiScopes(CancellationToken cancellationToken)
34+
public override string Name => Constants.Name;
35+
36+
public override Task<int> NbApiScopes(CancellationToken cancellationToken)
4037
{
4138
return _configurationDbcontext.ApiScopes.CountAsync(cancellationToken);
4239
}
4340

44-
public async Task<List<Scope>> ExtractApiScopes(ExtractParameter parameter, CancellationToken cancellationToken)
41+
public override async Task<List<Scope>> ExtractApiScopes(ExtractParameter parameter, CancellationToken cancellationToken)
4542
{
4643
var scopes = await _configurationDbcontext.ApiScopes
4744
.Include(c => c.UserClaims)
@@ -51,12 +48,12 @@ public async Task<List<Scope>> ExtractApiScopes(ExtractParameter parameter, Canc
5148
return scopes.Select(Map).ToList();
5249
}
5350

54-
public Task<int> NbIdentityScopes(CancellationToken cancellationToken)
51+
public override Task<int> NbIdentityScopes(CancellationToken cancellationToken)
5552
{
5653
return _configurationDbcontext.IdentityResources.CountAsync(cancellationToken);
5754
}
5855

59-
public async Task<List<Scope>> ExtractIdentityScopes(ExtractParameter parameter, CancellationToken cancellationToken)
56+
public override async Task<List<Scope>> ExtractIdentityScopes(ExtractParameter parameter, CancellationToken cancellationToken)
6057
{
6158
var scopes = await _configurationDbcontext.IdentityResources
6259
.Include(c => c.UserClaims)
@@ -66,12 +63,12 @@ public async Task<List<Scope>> ExtractIdentityScopes(ExtractParameter parameter,
6663
return scopes.Select(Map).ToList();
6764
}
6865

69-
public Task<int> NbApiResources(CancellationToken cancellationToken)
66+
public override Task<int> NbApiResources(CancellationToken cancellationToken)
7067
{
7168
return _configurationDbcontext.ApiResources.CountAsync(cancellationToken);
7269
}
7370

74-
public async Task<List<ApiResource>> ExtractApiResources(ExtractParameter parameter, CancellationToken cancellationToken)
71+
public override async Task<List<ApiResource>> ExtractApiResources(ExtractParameter parameter, CancellationToken cancellationToken)
7572
{
7673
var apiResources = await _configurationDbcontext.ApiResources
7774
.Include(c => c.UserClaims)
@@ -88,12 +85,12 @@ public async Task<List<ApiResource>> ExtractApiResources(ExtractParameter parame
8885
}).ToList();
8986
}
9087

91-
public Task<int> NbClients(CancellationToken cancellationToken)
88+
public override Task<int> NbClients(CancellationToken cancellationToken)
9289
{
9390
return _configurationDbcontext.Clients.CountAsync(cancellationToken);
9491
}
9592

96-
public async Task<List<Client>> ExtractClients(ExtractParameter parameter, CancellationToken cancellationToken)
93+
public override async Task<List<Client>> ExtractClients(ExtractParameter parameter, CancellationToken cancellationToken)
9794
{
9895
var clients = await _configurationDbcontext.Clients
9996
.Include(c => c.RedirectUris)
@@ -105,49 +102,16 @@ public async Task<List<Client>> ExtractClients(ExtractParameter parameter, Cance
105102
.AsNoTracking()
106103
.ToListAsync();
107104
var allScopeNames = clients.SelectMany(c => c.AllowedScopes.Select(s => s.Scope)).Distinct().ToList();
105+
allScopeNames.Add(DefaultScopes.OpenIdScope.Name);
108106
var allScopes = await _scopeRepository.GetByNames(allScopeNames, cancellationToken);
109107
return clients.Select(c =>
110108
{
111-
var filteredScopes = allScopes.Where(s => c.AllowedScopes.All(cs => cs.Scope == s.Name)).ToList();
109+
var clientType = ResolveClientType(c);
110+
var filteredScopes = allScopes.Where(s => c.AllowedScopes.All(cs => cs.Scope == s.Name) || (s.Name == DefaultScopes.OpenIdScope.Name && clientType != ClientTypes.MACHINE)).ToList();
112111
return Map(c, filteredScopes);
113112
}).ToList();
114113
}
115114

116-
public Task<int> NbGroups(CancellationToken cancellationToken)
117-
{
118-
return _applicationDbcontext.Roles.CountAsync(cancellationToken);
119-
}
120-
121-
public async Task<List<Group>> ExtractGroups(ExtractParameter parameter, CancellationToken cancellationToken)
122-
{
123-
var allGroups = await _applicationDbcontext.Roles.Skip(parameter.StartIndex).Take(parameter.Count).ToListAsync(cancellationToken);
124-
return allGroups.Select(Map).ToList();
125-
}
126-
127-
public Task<int> NbUsers(CancellationToken cancellationToken)
128-
{
129-
return _applicationDbcontext.Users.CountAsync(cancellationToken);
130-
}
131-
132-
public async Task<List<User>> ExtractUsers(ExtractParameter parameter, CancellationToken cancellationToken)
133-
{
134-
var users = await _applicationDbcontext.Users.Skip(parameter.StartIndex).Take(parameter.Count).ToListAsync(cancellationToken);
135-
var allUserIds = users.Select(u => u.Id).ToList();
136-
var allUserClaims = await _applicationDbcontext.UserClaims.Where(c => allUserIds.Contains(c.UserId)).ToListAsync(cancellationToken);
137-
var allUserRoles = await _applicationDbcontext.UserRoles.Where(c => allUserIds.Contains(c.UserId)).ToListAsync(cancellationToken);
138-
var allUserRoleIds = allUserRoles.Select(ur => ur.RoleId).Distinct().ToList();
139-
var extractedUsers = new List<User>();
140-
foreach (var user in users)
141-
{
142-
var userClaims = allUserClaims.Where(c => c.UserId == user.Id).Select(Map).ToList();
143-
var userRoles = allUserRoles.Where(ur => ur.UserId == user.Id).Select(ur => ur.RoleId).ToList();
144-
var extractedUser = Map(user, userClaims, userRoles);
145-
extractedUsers.Add(extractedUser);
146-
}
147-
148-
return extractedUsers;
149-
}
150-
151115
private static Scope Map(DuendeApiScope scope)
152116
{
153117
var lst = DefaultClaimMappers.All;
@@ -274,29 +238,6 @@ private static Client Map(DuendeClient client, List<Scope> scopes)
274238
result.UpdateClientName(client.ClientName, IdServer.Constants.DefaultLanguage);
275239
result.UpdateClientUri(client.ClientUri, IdServer.Constants.DefaultLanguage);
276240
result.UpdateLogoUri(client.LogoUri, IdServer.Constants.DefaultLanguage);
277-
/*
278-
AllowPlainTextPkce
279-
EnableLocalLogin
280-
RequireRequestObject
281-
AllowedIdentityTokenSigningAlgorithms
282-
AccessTokenLifetime
283-
AllowOfflineAccess
284-
AllowAccessTokensViaBrowser
285-
Enabled
286-
ProtocolType
287-
RequireClientSecret
288-
Description
289-
AllowRememberConsent
290-
AlwaysIncludeUserClaimsInIdToken
291-
IdentityProviderRestrictions
292-
IncludeJwtId
293-
Claims
294-
AlwaysSendClientClaims
295-
ClientClaimsPrefix
296-
ClientCorsOrigin
297-
ClientProperty
298-
UserCodeType
299-
*/
300241
return result;
301242
}
302243

@@ -367,88 +308,6 @@ private static List<ClientSecret> ResolveClientSecrets(DuendeClient client)
367308
}).ToList();
368309
}
369310

370-
private static UserClaim Map(IdentityUserClaim<string> userClaim)
371-
{
372-
return new UserClaim
373-
{
374-
Id = Guid.NewGuid().ToString(),
375-
Name = userClaim.ClaimType,
376-
Value = userClaim.ClaimValue,
377-
UserId = userClaim.UserId
378-
};
379-
}
380-
381-
private static Group Map(IdentityRole identityRole)
382-
{
383-
return new Group
384-
{
385-
Id = identityRole.Id,
386-
Name = identityRole.Name,
387-
Source = Constants.Name,
388-
FullPath = identityRole.Name,
389-
Description = identityRole.NormalizedName,
390-
CreateDateTime = DateTime.UtcNow,
391-
UpdateDateTime = DateTime.UtcNow
392-
};
393-
}
394-
395-
private static User Map(ApplicationUser applicationUser, List<UserClaim> userClaims, List<string> groupIds)
396-
{
397-
var result = new User
398-
{
399-
Id = applicationUser.Id,
400-
Source = Constants.Name,
401-
Name = applicationUser.UserName,
402-
Email = applicationUser.Email,
403-
UnblockDateTime = applicationUser.LockoutEnd == null ? null : applicationUser.LockoutEnd.Value.UtcDateTime,
404-
NbLoginAttempt = applicationUser.AccessFailedCount,
405-
EmailVerified = applicationUser.EmailConfirmed,
406-
Credentials = new List<UserCredential>
407-
{
408-
new UserCredential
409-
{
410-
Id = Guid.NewGuid().ToString(),
411-
Value = applicationUser.PasswordHash,
412-
CredentialType = UserCredential.PWD,
413-
IsActive = true,
414-
HashAlg = PasswordHashAlgs.Microsoft
415-
}
416-
},
417-
CreateDateTime = DateTime.UtcNow,
418-
UpdateDateTime = DateTime.UtcNow
419-
};
420-
result.Status = result.IsBlocked() ? UserStatus.BLOCKED : UserStatus.ACTIVATED;
421-
var claims = new List<UserClaim>();
422-
var filteredClaims = userClaims.Where(c => c.UserId == applicationUser.Id);
423-
claims.AddRange(filteredClaims);
424-
if (!string.IsNullOrWhiteSpace(applicationUser.PhoneNumber) && !claims.Any(c => c.Type == JwtRegisteredClaimNames.PhoneNumber))
425-
{
426-
claims.Add(new UserClaim
427-
{
428-
Id = Guid.NewGuid().ToString(),
429-
Name = JwtRegisteredClaimNames.PhoneNumber,
430-
Value = applicationUser.PhoneNumber
431-
});
432-
}
433-
434-
if (!claims.Any(c => c.Type == JwtRegisteredClaimNames.PhoneNumberVerified))
435-
{
436-
claims.Add(new UserClaim
437-
{
438-
Id = Guid.NewGuid().ToString(),
439-
Name = JwtRegisteredClaimNames.PhoneNumberVerified,
440-
Value = applicationUser.PhoneNumberConfirmed.ToString().ToLowerInvariant()
441-
});
442-
}
443-
444-
result.OAuthUserClaims = claims;
445-
result.Groups = groupIds.Select(groupId => new GroupUser
446-
{
447-
GroupsId = groupId
448-
}).ToList();
449-
return result;
450-
}
451-
452311
private static ClientTypes ResolveClientType(DuendeClient client)
453312
{
454313
var grantTypes = client.AllowedGrantTypes.Select(g => g.GrantType).ToList();
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright (c) SimpleIdServer. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
3+
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
4+
using Microsoft.EntityFrameworkCore;
5+
6+
namespace SimpleIdServer.IdServer.Migrations.Openiddict;
7+
8+
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IApplicationDbContext
9+
{
10+
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
11+
: base(options)
12+
{
13+
}
14+
15+
protected override void OnModelCreating(ModelBuilder builder)
16+
{
17+
base.OnModelCreating(builder);
18+
}
19+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) SimpleIdServer. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
3+
4+
using Microsoft.EntityFrameworkCore;
5+
using OpenIddict.EntityFrameworkCore.Models;
6+
7+
namespace SimpleIdServer.IdServer.Migrations.Openiddict;
8+
9+
public class ConfigurationDbcontext : DbContext
10+
{
11+
public ConfigurationDbcontext(DbContextOptions<ConfigurationDbcontext> options)
12+
: base(options)
13+
{
14+
}
15+
16+
public DbSet<OpenIddictEntityFrameworkCoreApplication> Applications => Set<OpenIddictEntityFrameworkCoreApplication>();
17+
public DbSet<OpenIddictEntityFrameworkCoreScope> Scopes => Set<OpenIddictEntityFrameworkCoreScope>();
18+
}

0 commit comments

Comments
 (0)