1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-02 00:22:50 -05:00

upgrade identity server 4 to v4 (#842)

* upgrade identity server 4 to v4

* remove script ref
This commit is contained in:
Kyle Spearrin
2020-07-30 17:00:13 -04:00
committed by GitHub
parent 22eb8316f2
commit 623cd36bd4
20 changed files with 432 additions and 107 deletions

View File

@ -46,7 +46,7 @@
<PackageReference Include="Serilog.Extensions.Logging.File" Version="2.0.0" />
<PackageReference Include="Serilog.Sinks.AzureDocumentDB" Version="3.8.0" />
<PackageReference Include="Sentry.Serilog" Version="2.1.5" />
<PackageReference Include="IdentityServer4" Version="3.1.3" />
<PackageReference Include="IdentityServer4" Version="4.0.4" />
<PackageReference Include="Dapper" Version="2.0.35" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Serilog.Sinks.SyslogMessages" Version="1.0.5" />

View File

@ -0,0 +1,20 @@
using IdentityServer4.Models;
using System.Collections.Generic;
namespace Bit.Core.IdentityServer
{
public class ApiScopes
{
public static IEnumerable<ApiScope> GetApiScopes()
{
return new List<ApiScope>
{
new ApiScope("api", "API Access"),
new ApiScope("api.push", "API Push Access"),
new ApiScope("api.licensing", "API Licensing Access"),
new ApiScope("api.organization", "API Organization Access"),
new ApiScope("internal", "Internal Access")
};
}
}
}

View File

@ -23,7 +23,8 @@ namespace Bit.Core.IdentityServer
public Task<string> StoreAuthorizationCodeAsync(AuthorizationCode code)
{
return CreateItemAsync(code, code.ClientId, code.Subject.GetSubjectId(), code.CreationTime, code.Lifetime);
return CreateItemAsync(code, code.ClientId, code.Subject.GetSubjectId(), code.SessionId,
code.Description, code.CreationTime, code.Lifetime);
}
public Task<AuthorizationCode> GetAuthorizationCodeAsync(string code)

View File

@ -47,7 +47,7 @@ namespace Bit.Core.IdentityServer
AllowedGrantTypes = GrantTypes.ClientCredentials,
AccessTokenLifetime = 3600 * 24,
Enabled = installation.Enabled,
Claims = new List<Claim> { new Claim(JwtClaimTypes.Subject, installation.Id.ToString()) }
Claims = new List<ClientClaim> { new ClientClaim(JwtClaimTypes.Subject, installation.Id.ToString()) }
};
}
}
@ -70,7 +70,7 @@ namespace Bit.Core.IdentityServer
AllowedGrantTypes = GrantTypes.ClientCredentials,
AccessTokenLifetime = 3600 * 24,
Enabled = true,
Claims = new List<Claim> { new Claim(JwtClaimTypes.Subject, id) }
Claims = new List<ClientClaim> { new ClientClaim(JwtClaimTypes.Subject, id) }
};
}
}
@ -92,7 +92,7 @@ namespace Bit.Core.IdentityServer
AllowedGrantTypes = GrantTypes.ClientCredentials,
AccessTokenLifetime = 3600 * 1,
Enabled = org.Enabled && org.UseApi,
Claims = new List<Claim> { new Claim(JwtClaimTypes.Subject, org.Id.ToString()) }
Claims = new List<ClientClaim> { new ClientClaim(JwtClaimTypes.Subject, org.Id.ToString()) }
};
}
}

View File

@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Bit.Core.Models.Table;
using Bit.Core.Repositories;
using IdentityServer4.Models;
using IdentityServer4.Stores;
@ -19,13 +17,6 @@ namespace Bit.Core.IdentityServer
_grantRepository = grantRepository;
}
public async Task<IEnumerable<PersistedGrant>> GetAllAsync(string subjectId)
{
var grants = await _grantRepository.GetManyAsync(subjectId);
var pGrants = grants.Select(g => ToPersistedGrant(g));
return pGrants;
}
public async Task<PersistedGrant> GetAsync(string key)
{
var grant = await _grantRepository.GetByKeyAsync(key);
@ -38,19 +29,22 @@ namespace Bit.Core.IdentityServer
return pGrant;
}
public async Task RemoveAllAsync(string subjectId, string clientId)
public async Task<IEnumerable<PersistedGrant>> GetAllAsync(PersistedGrantFilter filter)
{
await _grantRepository.DeleteAsync(subjectId, clientId);
var grants = await _grantRepository.GetManyAsync(filter.SubjectId, filter.SessionId,
filter.ClientId, filter.Type);
var pGrants = grants.Select(g => ToPersistedGrant(g));
return pGrants;
}
public async Task RemoveAllAsync(string subjectId, string clientId, string type)
public async Task RemoveAllAsync(PersistedGrantFilter filter)
{
await _grantRepository.DeleteAsync(subjectId, clientId, type);
await _grantRepository.DeleteManyAsync(filter.SubjectId, filter.SessionId, filter.ClientId, filter.Type);
}
public async Task RemoveAsync(string key)
{
await _grantRepository.DeleteAsync(key);
await _grantRepository.DeleteByKeyAsync(key);
}
public async Task StoreAsync(PersistedGrant pGrant)
@ -59,30 +53,36 @@ namespace Bit.Core.IdentityServer
await _grantRepository.SaveAsync(grant);
}
private Grant ToGrant(PersistedGrant pGrant)
private Models.Table.Grant ToGrant(PersistedGrant pGrant)
{
return new Grant
return new Models.Table.Grant
{
Key = pGrant.Key,
Type = pGrant.Type,
SubjectId = pGrant.SubjectId,
SessionId = pGrant.SessionId,
ClientId = pGrant.ClientId,
Description = pGrant.Description,
CreationDate = pGrant.CreationTime,
ExpirationDate = pGrant.Expiration,
ConsumedDate = pGrant.ConsumedTime,
Data = pGrant.Data
};
}
private PersistedGrant ToPersistedGrant(Grant grant)
private PersistedGrant ToPersistedGrant(Models.Table.Grant grant)
{
return new PersistedGrant
{
Key = grant.Key,
Type = grant.Type,
SubjectId = grant.SubjectId,
SessionId = grant.SessionId,
ClientId = grant.ClientId,
Description = grant.Description,
CreationTime = grant.CreationDate,
Expiration = grant.ExpirationDate,
ConsumedTime = grant.ConsumedDate,
Data = grant.Data
};
}

View File

@ -14,19 +14,16 @@ namespace Bit.Core.IdentityServer
public class ProfileService : IProfileService
{
private readonly IUserService _userService;
private readonly IUserRepository _userRepository;
private readonly IOrganizationUserRepository _organizationUserRepository;
private readonly ILicensingService _licensingService;
private readonly CurrentContext _currentContext;
public ProfileService(
IUserRepository userRepository,
IUserService userService,
IOrganizationUserRepository organizationUserRepository,
ILicensingService licensingService,
CurrentContext currentContext)
{
_userRepository = userRepository;
_userService = userService;
_organizationUserRepository = organizationUserRepository;
_licensingService = licensingService;
@ -46,7 +43,8 @@ namespace Bit.Core.IdentityServer
{
new Claim("premium", isPremium ? "true" : "false", ClaimValueTypes.Boolean),
new Claim(JwtClaimTypes.Email, user.Email),
new Claim(JwtClaimTypes.EmailVerified, user.EmailVerified ? "true" : "false", ClaimValueTypes.Boolean),
new Claim(JwtClaimTypes.EmailVerified, user.EmailVerified ? "true" : "false",
ClaimValueTypes.Boolean),
new Claim("sstamp", user.SecurityStamp)
});
@ -96,13 +94,14 @@ namespace Bit.Core.IdentityServer
// filter out any of the new claims
var existingClaimsToKeep = existingClaims
.Where(c => !c.Type.StartsWith("org") && (newClaims.Count == 0 || !newClaims.Any(nc => nc.Type == c.Type)))
.Where(c => !c.Type.StartsWith("org") &&
(newClaims.Count == 0 || !newClaims.Any(nc => nc.Type == c.Type)))
.ToList();
newClaims.AddRange(existingClaimsToKeep);
if (newClaims.Any())
{
context.AddRequestedClaims(newClaims);
context.IssuedClaims.AddRange(newClaims);
}
}

View File

@ -7,9 +7,12 @@ namespace Bit.Core.Models.Table
public string Key { get; set; }
public string Type { get; set; }
public string SubjectId { get; set; }
public string SessionId { get; set; }
public string ClientId { get; set; }
public string Description { get; set; }
public DateTime CreationDate { get; set; }
public DateTime? ExpirationDate { get; set; }
public DateTime? ConsumedDate { get; set; }
public string Data { get; set; }
}
}

View File

@ -8,10 +8,9 @@ namespace Bit.Core.Repositories
public interface IGrantRepository
{
Task<Grant> GetByKeyAsync(string key);
Task<ICollection<Grant>> GetManyAsync(string subjectId);
Task<ICollection<Grant>> GetManyAsync(string subjectId, string sessionId, string clientId, string type);
Task SaveAsync(Grant obj);
Task DeleteAsync(string key);
Task DeleteAsync(string subjectId, string clientId);
Task DeleteAsync(string subjectId, string clientId, string type);
Task DeleteByKeyAsync(string key);
Task DeleteManyAsync(string subjectId, string sessionId, string clientId, string type);
}
}

View File

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
@ -32,13 +31,14 @@ namespace Bit.Core.Repositories.SqlServer
}
}
public async Task<ICollection<Grant>> GetManyAsync(string subjectId)
public async Task<ICollection<Grant>> GetManyAsync(string subjectId, string sessionId,
string clientId, string type)
{
using (var connection = new SqlConnection(ConnectionString))
{
var results = await connection.QueryAsync<Grant>(
"[dbo].[Grant_ReadBySubjectId]",
new { SubjectId = subjectId },
"[dbo].[Grant_Read]",
new { SubjectId = subjectId, SessionId = sessionId, ClientId = clientId, Type = type },
commandType: CommandType.StoredProcedure);
return results.ToList();
@ -56,7 +56,7 @@ namespace Bit.Core.Repositories.SqlServer
}
}
public async Task DeleteAsync(string key)
public async Task DeleteByKeyAsync(string key)
{
using (var connection = new SqlConnection(ConnectionString))
{
@ -67,24 +67,13 @@ namespace Bit.Core.Repositories.SqlServer
}
}
public async Task DeleteAsync(string subjectId, string clientId)
public async Task DeleteManyAsync(string subjectId, string sessionId, string clientId, string type)
{
using (var connection = new SqlConnection(ConnectionString))
{
await connection.ExecuteAsync(
"[dbo].[Grant_DeleteBySubjectIdClientId]",
new { SubjectId = subjectId, ClientId = clientId },
commandType: CommandType.StoredProcedure);
}
}
public async Task DeleteAsync(string subjectId, string clientId, string type)
{
using (var connection = new SqlConnection(ConnectionString))
{
await connection.ExecuteAsync(
"[dbo].[Grant_DeleteBySubjectIdClientIdType]",
new { SubjectId = subjectId, ClientId = clientId, Type = type },
"[dbo].[Grant_Delete]",
new { SubjectId = subjectId, SessionId = sessionId, ClientId = clientId, Type = type },
commandType: CommandType.StoredProcedure);
}
}