diff --git a/src/Api/Api.csproj b/src/Api/Api.csproj index 2721a5c8e..bcc54244b 100644 --- a/src/Api/Api.csproj +++ b/src/Api/Api.csproj @@ -13,13 +13,13 @@ - - - - - - - + + + + + + + diff --git a/src/Api/Startup.cs b/src/Api/Startup.cs index a1edbaa46..daed2a889 100644 --- a/src/Api/Startup.cs +++ b/src/Api/Startup.cs @@ -19,6 +19,7 @@ using Serilog.Events; using Stripe; using Bit.Core.Utilities; using IdentityModel; +using IdentityServer4.AccessTokenValidation; namespace Bit.Api { @@ -75,18 +76,27 @@ namespace Bit.Api // Identity services.AddCustomIdentityServices(globalSettings); + services + .AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme) + .AddIdentityServerAuthentication(options => + { + options.Authority = globalSettings.BaseServiceUri.InternalIdentity; + options.RequireHttpsMetadata = !Environment.IsDevelopment() && + globalSettings.BaseServiceUri.InternalIdentity.StartsWith("https"); + options.NameClaimType = ClaimTypes.Email; + options.TokenRetriever = TokenRetrieval.FromAuthorizationHeaderOrQueryString("Bearer", "access_token"); + }); + services.AddAuthorization(config => { config.AddPolicy("Application", policy => { - policy.AddAuthenticationSchemes("Bearer", "Bearer3"); policy.RequireAuthenticatedUser(); policy.RequireClaim(JwtClaimTypes.AuthenticationMethod, "Application"); policy.RequireClaim(JwtClaimTypes.Scope, "api"); }); config.AddPolicy("Web", policy => { - policy.AddAuthenticationSchemes("Bearer", "Bearer3"); policy.RequireAuthenticatedUser(); policy.RequireClaim(JwtClaimTypes.AuthenticationMethod, "Application"); policy.RequireClaim(JwtClaimTypes.Scope, "api"); @@ -178,32 +188,11 @@ namespace Bit.Api // Add Cors app.UseCors("All"); - // Add IdentityServer to the request pipeline. - app.UseIdentityServerAuthentication(GetIdentityOptions(env, globalSettings, string.Empty)); - app.UseIdentityServerAuthentication(GetIdentityOptions(env, globalSettings, "3")); - // Add current context app.UseMiddleware(); // Add MVC to the request pipeline. app.UseMvc(); } - - private IdentityServerAuthenticationOptions GetIdentityOptions(IHostingEnvironment env, - GlobalSettings globalSettings, string suffix) - { - var options = new IdentityServerAuthenticationOptions - { - Authority = globalSettings.BaseServiceUri.InternalIdentity, - AllowedScopes = new string[] { "api", "api.push", "api.licensing" }, - RequireHttpsMetadata = !env.IsDevelopment() && globalSettings.BaseServiceUri.InternalIdentity.StartsWith("https"), - NameClaimType = ClaimTypes.Email, - // Suffix until we retire the old jwt schemes. - AuthenticationScheme = $"Bearer{suffix}", - TokenRetriever = TokenRetrieval.FromAuthorizationHeaderOrQueryString($"Bearer{suffix}", $"access_token{suffix}") - }; - - return options; - } } } diff --git a/src/Api/Utilities/MultipartFormDataHelper.cs b/src/Api/Utilities/MultipartFormDataHelper.cs index 9ed277b4c..69941b70d 100644 --- a/src/Api/Utilities/MultipartFormDataHelper.cs +++ b/src/Api/Utilities/MultipartFormDataHelper.cs @@ -5,6 +5,7 @@ using Microsoft.Net.Http.Headers; using System; using System.IO; using System.Threading.Tasks; +using Microsoft.Extensions.Primitives; namespace Bit.Api.Utilities { @@ -30,7 +31,7 @@ namespace Bit.Api.Utilities if(ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var content) && HasFileContentDisposition(content)) { - var fileName = HeaderUtilities.RemoveQuotes(content.FileName) ?? string.Empty; + var fileName = HeaderUtilities.RemoveQuotes(content.FileName).ToString(); using(section.Body) { await callback(section.Body, fileName); @@ -52,7 +53,7 @@ namespace Bit.Api.Utilities private static string GetBoundary(MediaTypeHeaderValue contentType, int lengthLimit) { var boundary = HeaderUtilities.RemoveQuotes(contentType.Boundary); - if(string.IsNullOrWhiteSpace(boundary)) + if(StringSegment.IsNullOrEmpty(boundary)) { throw new InvalidDataException("Missing content-type boundary."); } @@ -62,14 +63,14 @@ namespace Bit.Api.Utilities throw new InvalidDataException($"Multipart boundary length limit {lengthLimit} exceeded."); } - return boundary; + return boundary.ToString(); } private static bool HasFileContentDisposition(ContentDispositionHeaderValue content) { // Content-Disposition: form-data; name="myfile1"; filename="Misc 002.jpg" return content != null && content.DispositionType.Equals("form-data") && - (!string.IsNullOrEmpty(content.FileName) || !string.IsNullOrEmpty(content.FileNameStar)); + (!StringSegment.IsNullOrEmpty(content.FileName) || !StringSegment.IsNullOrEmpty(content.FileNameStar)); } } } diff --git a/src/Billing/Billing.csproj b/src/Billing/Billing.csproj index 8e19452b0..80681a71a 100644 --- a/src/Billing/Billing.csproj +++ b/src/Billing/Billing.csproj @@ -13,11 +13,11 @@ - - - - - + + + + + diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 4c7db6b0a..82afb5eca 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -49,31 +49,31 @@ - - + + + + + + + + - - - - - - - - - - + + + + - + - - + + - + - - + + @@ -82,7 +82,7 @@ - + diff --git a/src/Core/IdentityServer/ProfileService.cs b/src/Core/IdentityServer/ProfileService.cs index 08c3381f6..bf47e42d2 100644 --- a/src/Core/IdentityServer/ProfileService.cs +++ b/src/Core/IdentityServer/ProfileService.cs @@ -5,9 +5,7 @@ using Bit.Core.Repositories; using Bit.Core.Services; using System.Security.Claims; using System.Collections.Generic; -using Microsoft.AspNetCore.Builder; using System.Linq; -using Microsoft.Extensions.Options; using System; using IdentityModel; @@ -19,20 +17,17 @@ namespace Bit.Core.IdentityServer private readonly IUserRepository _userRepository; private readonly IOrganizationUserRepository _organizationUserRepository; private readonly ILicensingService _licensingService; - private IdentityOptions _identityOptions; public ProfileService( IUserRepository userRepository, IUserService userService, IOrganizationUserRepository organizationUserRepository, - ILicensingService licensingService, - IOptions identityOptionsAccessor) + ILicensingService licensingService) { _userRepository = userRepository; _userService = userService; _organizationUserRepository = organizationUserRepository; _licensingService = licensingService; - _identityOptions = identityOptionsAccessor?.Value ?? new IdentityOptions(); } public async Task GetProfileDataAsync(ProfileDataRequestContext context) @@ -49,7 +44,7 @@ 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(_identityOptions.ClaimsIdentity.SecurityStampClaimType, user.SecurityStamp) + new Claim("sstamp", user.SecurityStamp) }); if(!string.IsNullOrWhiteSpace(user.Name)) @@ -101,14 +96,13 @@ namespace Bit.Core.IdentityServer newClaims.AddRange(existingClaimsToKeep); if(newClaims.Any()) { - context.AddFilteredClaims(newClaims); + context.AddRequestedClaims(newClaims); } } public async Task IsActiveAsync(IsActiveContext context) { - var securityTokenClaim = context.Subject?.Claims.FirstOrDefault(c => - c.Type == _identityOptions.ClaimsIdentity.SecurityStampClaimType); + var securityTokenClaim = context.Subject?.Claims.FirstOrDefault(c => c.Type == "sstamp"); var user = await _userService.GetUserByPrincipalAsync(context.Subject); if(user != null && securityTokenClaim != null) diff --git a/src/Core/Utilities/ServiceCollectionExtensions.cs b/src/Core/Utilities/ServiceCollectionExtensions.cs index bcb34f567..efd044e1a 100644 --- a/src/Core/Utilities/ServiceCollectionExtensions.cs +++ b/src/Core/Utilities/ServiceCollectionExtensions.cs @@ -204,7 +204,7 @@ namespace Bit.Core.Utilities if(env.IsDevelopment()) { - identityServerBuilder.AddTemporarySigningCredential(); + identityServerBuilder.AddDeveloperSigningCredential(false); } else if(!string.IsNullOrWhiteSpace(globalSettings.IdentityServer.CertificatePassword) && File.Exists("identity.pfx")) diff --git a/src/Identity/Identity.csproj b/src/Identity/Identity.csproj index a4aabf6ab..97916272f 100644 --- a/src/Identity/Identity.csproj +++ b/src/Identity/Identity.csproj @@ -13,9 +13,9 @@ - - - + + + diff --git a/src/Jobs/Jobs.csproj b/src/Jobs/Jobs.csproj index e9be561fa..28c74d9a2 100644 --- a/src/Jobs/Jobs.csproj +++ b/src/Jobs/Jobs.csproj @@ -15,8 +15,8 @@ - - + + diff --git a/src/Jobs/NoopServer.cs b/src/Jobs/NoopServer.cs index 2ec7214bb..39dcc6c39 100644 --- a/src/Jobs/NoopServer.cs +++ b/src/Jobs/NoopServer.cs @@ -1,4 +1,6 @@ -using Microsoft.AspNetCore.Hosting.Server; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Http.Features; namespace Bit.Jobs @@ -10,7 +12,14 @@ namespace Bit.Jobs public void Dispose() { } - public void Start(IHttpApplication application) - { } + public Task StartAsync(IHttpApplication application, CancellationToken cancellationToken) + { + return Task.FromResult(0); + } + + public Task StopAsync(CancellationToken cancellationToken) + { + return Task.FromResult(0); + } } } diff --git a/util/Function/Function.csproj b/util/Function/Function.csproj index 9e1658460..f1ab30b66 100644 --- a/util/Function/Function.csproj +++ b/util/Function/Function.csproj @@ -4,7 +4,7 @@ Bit.Function - + diff --git a/util/Mail/Mail.csproj b/util/Mail/Mail.csproj index 561573df1..b92e74d41 100644 --- a/util/Mail/Mail.csproj +++ b/util/Mail/Mail.csproj @@ -13,9 +13,7 @@ - - - +