diff --git a/Squidex.sln b/Squidex.sln
index bd07f14e5..1c40c8524 100644
--- a/Squidex.sln
+++ b/Squidex.sln
@@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
-VisualStudioVersion = 15.0.26730.12
+VisualStudioVersion = 15.0.27004.2002
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex", "src\Squidex\Squidex.csproj", "{61F6BBCE-A080-4400-B194-70E2F5D2096E}"
EndProject
diff --git a/src/Squidex.Domain.Apps.Core/Squidex.Domain.Apps.Core.csproj b/src/Squidex.Domain.Apps.Core/Squidex.Domain.Apps.Core.csproj
index 73c1db950..721bd7392 100644
--- a/src/Squidex.Domain.Apps.Core/Squidex.Domain.Apps.Core.csproj
+++ b/src/Squidex.Domain.Apps.Core/Squidex.Domain.Apps.Core.csproj
@@ -13,8 +13,8 @@
-
-
+
+
diff --git a/src/Squidex.Domain.Apps.Events/Squidex.Domain.Apps.Events.csproj b/src/Squidex.Domain.Apps.Events/Squidex.Domain.Apps.Events.csproj
index 2b809030a..af764763d 100644
--- a/src/Squidex.Domain.Apps.Events/Squidex.Domain.Apps.Events.csproj
+++ b/src/Squidex.Domain.Apps.Events/Squidex.Domain.Apps.Events.csproj
@@ -11,7 +11,7 @@
-
+
diff --git a/src/Squidex.Domain.Apps.Read/Squidex.Domain.Apps.Read.csproj b/src/Squidex.Domain.Apps.Read/Squidex.Domain.Apps.Read.csproj
index 951f9fcbe..ca4434061 100644
--- a/src/Squidex.Domain.Apps.Read/Squidex.Domain.Apps.Read.csproj
+++ b/src/Squidex.Domain.Apps.Read/Squidex.Domain.Apps.Read.csproj
@@ -13,8 +13,8 @@
-
-
+
+
diff --git a/src/Squidex.Domain.Apps.Write/Squidex.Domain.Apps.Write.csproj b/src/Squidex.Domain.Apps.Write/Squidex.Domain.Apps.Write.csproj
index 79f4eaf26..95685bf46 100644
--- a/src/Squidex.Domain.Apps.Write/Squidex.Domain.Apps.Write.csproj
+++ b/src/Squidex.Domain.Apps.Write/Squidex.Domain.Apps.Write.csproj
@@ -14,7 +14,7 @@
-
+
diff --git a/src/Squidex.Domain.Users.MongoDb/Squidex.Domain.Users.MongoDb.csproj b/src/Squidex.Domain.Users.MongoDb/Squidex.Domain.Users.MongoDb.csproj
index 7f9ebe67f..3e95a2ab6 100644
--- a/src/Squidex.Domain.Users.MongoDb/Squidex.Domain.Users.MongoDb.csproj
+++ b/src/Squidex.Domain.Users.MongoDb/Squidex.Domain.Users.MongoDb.csproj
@@ -13,8 +13,8 @@
-
-
+
+
diff --git a/src/Squidex.Domain.Users/Squidex.Domain.Users.csproj b/src/Squidex.Domain.Users/Squidex.Domain.Users.csproj
index e0d2ec803..11b5070ec 100644
--- a/src/Squidex.Domain.Users/Squidex.Domain.Users.csproj
+++ b/src/Squidex.Domain.Users/Squidex.Domain.Users.csproj
@@ -11,7 +11,7 @@
-
+
diff --git a/src/Squidex.Infrastructure.GetEventStore/Squidex.Infrastructure.GetEventStore.csproj b/src/Squidex.Infrastructure.GetEventStore/Squidex.Infrastructure.GetEventStore.csproj
index a3687426d..c06c834c2 100644
--- a/src/Squidex.Infrastructure.GetEventStore/Squidex.Infrastructure.GetEventStore.csproj
+++ b/src/Squidex.Infrastructure.GetEventStore/Squidex.Infrastructure.GetEventStore.csproj
@@ -8,7 +8,7 @@
True
-
+
diff --git a/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj b/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj
index 0bdb3b4d4..c338c9865 100644
--- a/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj
+++ b/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj
@@ -8,10 +8,10 @@
True
-
-
+
+
-
+
diff --git a/src/Squidex/Config/Identity/AuthenticationServices.cs b/src/Squidex/Config/Identity/AuthenticationServices.cs
new file mode 100644
index 000000000..aeb2743b9
--- /dev/null
+++ b/src/Squidex/Config/Identity/AuthenticationServices.cs
@@ -0,0 +1,62 @@
+// ==========================================================================
+// AuthenticationServices.cs
+// Squidex Headless CMS
+// ==========================================================================
+// Copyright (c) Squidex Group
+// All rights reserved.
+// ==========================================================================
+
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Squidex.Infrastructure;
+
+namespace Squidex.Config.Identity
+{
+ public static class AuthenticationServices
+ {
+ public static IServiceCollection AddMyAuthentication(this IServiceCollection services, IConfiguration configuration)
+ {
+ var identityOptions = configuration.GetSection("identity").Get();
+
+ services.AddAuthentication()
+ .AddMyGoogleAuthentication(identityOptions)
+ .AddMyMicrosoftAuthentication(identityOptions)
+ .AddMyApiProtection(identityOptions, configuration);
+
+ return services;
+ }
+
+ public static AuthenticationBuilder AddMyApiProtection(this AuthenticationBuilder authBuilder, MyIdentityOptions identityOptions, IConfiguration configuration)
+ {
+ var apiScope = Constants.ApiScope;
+
+ var urlsOptions = configuration.GetSection("urls").Get();
+
+ if (!string.IsNullOrWhiteSpace(urlsOptions.BaseUrl))
+ {
+ string apiAuthorityUrl;
+
+ if (!string.IsNullOrWhiteSpace(identityOptions.AuthorityUrl))
+ {
+ apiAuthorityUrl = identityOptions.AuthorityUrl.BuildFullUrl(Constants.IdentityPrefix);
+ }
+ else
+ {
+ apiAuthorityUrl = urlsOptions.BuildUrl(Constants.IdentityPrefix);
+ }
+
+ authBuilder.AddIdentityServerAuthentication(options =>
+ {
+ options.Authority = apiAuthorityUrl;
+ options.ApiName = apiScope;
+ options.ApiSecret = null;
+ options.RequireHttpsMetadata = identityOptions.RequiresHttps;
+ });
+ }
+
+ return authBuilder;
+ }
+ }
+}
diff --git a/src/Squidex/Config/Identity/AuthenticationUsage.cs b/src/Squidex/Config/Identity/AuthenticationUsage.cs
new file mode 100644
index 000000000..b9dd4ad8f
--- /dev/null
+++ b/src/Squidex/Config/Identity/AuthenticationUsage.cs
@@ -0,0 +1,22 @@
+// ==========================================================================
+// AuthenticationUsage.cs
+// Squidex Headless CMS
+// ==========================================================================
+// Copyright (c) Squidex Group
+// All rights reserved.
+// ==========================================================================
+
+using Microsoft.AspNetCore.Builder;
+
+namespace Squidex.Config.Identity
+{
+ public static class AuthenticationUsage
+ {
+ public static IApplicationBuilder UseMyAuthentication(this IApplicationBuilder app)
+ {
+ app.UseAuthentication();
+
+ return app;
+ }
+ }
+}
diff --git a/src/Squidex/Config/Identity/GithubHandler.cs b/src/Squidex/Config/Identity/GithubHandler.cs
deleted file mode 100644
index a1e1cb433..000000000
--- a/src/Squidex/Config/Identity/GithubHandler.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-// ==========================================================================
-// GithubHandler.cs
-// Squidex Headless CMS
-// ==========================================================================
-// Copyright (c) Squidex Group
-// All rights reserved.
-// ==========================================================================
-
-using System.Security.Claims;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Authentication.OAuth;
-using Squidex.Shared.Identity;
-
-namespace Squidex.Config.Identity
-{
- public sealed class GitHubHandler : OAuthEvents
- {
- public override Task CreatingTicket(OAuthCreatingTicketContext context)
- {
- var userLogin = context.User.Value("login");
- var userName = context.User.Value("name");
-
- if (!string.IsNullOrEmpty(userName))
- {
- context.Identity.AddClaim(new Claim(SquidexClaimTypes.SquidexDisplayName, userName));
- }
- else if (!string.IsNullOrWhiteSpace(userLogin))
- {
- context.Identity.AddClaim(new Claim(SquidexClaimTypes.SquidexDisplayName, userName));
- }
-
- var pictureUrl = context.User.Value("avatar_url");
-
- if (!string.IsNullOrEmpty(pictureUrl))
- {
- context.Identity.AddClaim(new Claim(SquidexClaimTypes.SquidexPictureUrl, pictureUrl));
- }
-
- return base.CreatingTicket(context);
- }
- }
-}
diff --git a/src/Squidex/Config/Identity/GithubIdentityUsage.cs b/src/Squidex/Config/Identity/GithubIdentityUsage.cs
deleted file mode 100644
index 022a2a4b7..000000000
--- a/src/Squidex/Config/Identity/GithubIdentityUsage.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-// ==========================================================================
-// GithubIdentityUsage.cs
-// Squidex Headless CMS
-// ==========================================================================
-// Copyright (c) Squidex Group
-// All rights reserved.
-// ==========================================================================
-
-using AspNet.Security.OAuth.GitHub;
-using Microsoft.AspNetCore.Builder;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Options;
-
-namespace Squidex.Config.Identity
-{
- public static class GitHubIdentityUsage
- {
- public static IApplicationBuilder UseMyGithubAuthentication(this IApplicationBuilder app)
- {
- var options = app.ApplicationServices.GetService>().Value;
-
- if (options.IsGithubAuthConfigured())
- {
- var githubOptions =
- new GitHubAuthenticationOptions
- {
- ClientId = options.GithubClient,
- ClientSecret = options.GithubSecret
- };
-
- app.UseGitHubAuthentication(githubOptions);
- }
-
- return app;
- }
- }
-}
diff --git a/src/Squidex/Config/Identity/GoogleAuthenticationServices.cs b/src/Squidex/Config/Identity/GoogleAuthenticationServices.cs
new file mode 100644
index 000000000..43dd42477
--- /dev/null
+++ b/src/Squidex/Config/Identity/GoogleAuthenticationServices.cs
@@ -0,0 +1,31 @@
+// ==========================================================================
+// GoogleAuthenticationServices.cs
+// Squidex Headless CMS
+// ==========================================================================
+// Copyright (c) Squidex Group
+// All rights reserved.
+// ==========================================================================
+
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Squidex.Config.Identity
+{
+ public static class GoogleAuthenticationServices
+ {
+ public static AuthenticationBuilder AddMyGoogleAuthentication(this AuthenticationBuilder authBuilder, MyIdentityOptions identityOptions)
+ {
+ if (identityOptions.IsGoogleAuthConfigured())
+ {
+ authBuilder.AddGoogle(options =>
+ {
+ options.ClientId = identityOptions.GoogleClient;
+ options.ClientSecret = identityOptions.GoogleSecret;
+ options.Events = new GoogleHandler();
+ });
+ }
+
+ return authBuilder;
+ }
+ }
+}
diff --git a/src/Squidex/Config/Identity/GoogleHandler.cs b/src/Squidex/Config/Identity/GoogleHandler.cs
index 6c311dc34..df6f8c0f7 100644
--- a/src/Squidex/Config/Identity/GoogleHandler.cs
+++ b/src/Squidex/Config/Identity/GoogleHandler.cs
@@ -9,6 +9,7 @@
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OAuth;
using Squidex.Infrastructure.Tasks;
using Squidex.Shared.Identity;
@@ -17,7 +18,7 @@ namespace Squidex.Config.Identity
{
public sealed class GoogleHandler : OAuthEvents
{
- public override Task RedirectToAuthorizationEndpoint(OAuthRedirectToAuthorizationContext context)
+ public override Task RedirectToAuthorizationEndpoint(RedirectContext context)
{
context.Response.Redirect(context.RedirectUri + "&prompt=select_account");
diff --git a/src/Squidex/Config/Identity/GoogleIdentityUsage.cs b/src/Squidex/Config/Identity/GoogleIdentityUsage.cs
deleted file mode 100644
index 78e68baa4..000000000
--- a/src/Squidex/Config/Identity/GoogleIdentityUsage.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-// ==========================================================================
-// GoogleIdentityUsage.cs
-// Squidex Headless CMS
-// ==========================================================================
-// Copyright (c) Squidex Group
-// All rights reserved.
-// ==========================================================================
-
-using Microsoft.AspNetCore.Builder;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Options;
-
-namespace Squidex.Config.Identity
-{
- public static class GoogleIdentityUsage
- {
- public static IApplicationBuilder UseMyGoogleAuthentication(this IApplicationBuilder app)
- {
- var options = app.ApplicationServices.GetService>().Value;
-
- if (options.IsGoogleAuthConfigured())
- {
- var googleOptions =
- new GoogleOptions
- {
- ClientId = options.GoogleClient,
- ClientSecret = options.GoogleSecret,
- Events = new GoogleHandler()
- };
-
- app.UseGoogleAuthentication(googleOptions);
- }
-
- return app;
- }
- }
-}
diff --git a/src/Squidex/Config/Identity/IdentityServices.cs b/src/Squidex/Config/Identity/IdentityServices.cs
index 5437166e8..cdd8421a2 100644
--- a/src/Squidex/Config/Identity/IdentityServices.cs
+++ b/src/Squidex/Config/Identity/IdentityServices.cs
@@ -113,7 +113,8 @@ namespace Squidex.Config.Identity
public static IServiceCollection AddMyIdentity(this IServiceCollection services)
{
- services.AddIdentity().AddDefaultTokenProviders();
+ services.AddIdentity()
+ .AddDefaultTokenProviders();
return services;
}
diff --git a/src/Squidex/Config/Identity/IdentityUsage.cs b/src/Squidex/Config/Identity/IdentityUsage.cs
index 960eafd27..22db07e35 100644
--- a/src/Squidex/Config/Identity/IdentityUsage.cs
+++ b/src/Squidex/Config/Identity/IdentityUsage.cs
@@ -14,7 +14,6 @@ using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Squidex.Domain.Users;
-using Squidex.Infrastructure;
using Squidex.Infrastructure.Log;
using Squidex.Shared.Identity;
using Squidex.Shared.Users;
@@ -23,13 +22,6 @@ namespace Squidex.Config.Identity
{
public static class IdentityUsage
{
- public static IApplicationBuilder UseMyIdentity(this IApplicationBuilder app)
- {
- app.UseIdentity();
-
- return app;
- }
-
public static IApplicationBuilder UseMyIdentityServer(this IApplicationBuilder app)
{
app.UseIdentityServer();
@@ -83,38 +75,5 @@ namespace Squidex.Config.Identity
return app;
}
-
- public static IApplicationBuilder UseMyApiProtection(this IApplicationBuilder app)
- {
- var apiScope = Constants.ApiScope;
-
- var urlsOptions = app.ApplicationServices.GetService>().Value;
-
- if (!string.IsNullOrWhiteSpace(urlsOptions.BaseUrl))
- {
- var identityOptions = app.ApplicationServices.GetService>().Value;
-
- string apiAuthorityUrl;
-
- if (!string.IsNullOrWhiteSpace(identityOptions.AuthorityUrl))
- {
- apiAuthorityUrl = identityOptions.AuthorityUrl.BuildFullUrl(Constants.IdentityPrefix);
- }
- else
- {
- apiAuthorityUrl = urlsOptions.BuildUrl(Constants.IdentityPrefix);
- }
-
- app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
- {
- Authority = apiAuthorityUrl,
- ApiName = apiScope,
- ApiSecret = null,
- RequireHttpsMetadata = identityOptions.RequiresHttps
- });
- }
-
- return app;
- }
}
}
diff --git a/src/Squidex/Config/Identity/MicrosoftAuthenticationServices.cs b/src/Squidex/Config/Identity/MicrosoftAuthenticationServices.cs
new file mode 100644
index 000000000..b2ceeeaaf
--- /dev/null
+++ b/src/Squidex/Config/Identity/MicrosoftAuthenticationServices.cs
@@ -0,0 +1,31 @@
+// ==========================================================================
+// MicrosoftAuthenticationServices.cs
+// Squidex Headless CMS
+// ==========================================================================
+// Copyright (c) Squidex Group
+// All rights reserved.
+// ==========================================================================
+
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Squidex.Config.Identity
+{
+ public static class MicrosoftAuthenticationServices
+ {
+ public static AuthenticationBuilder AddMyMicrosoftAuthentication(this AuthenticationBuilder authBuilder, MyIdentityOptions identityOptions)
+ {
+ if (identityOptions.IsMicrosoftAuthConfigured())
+ {
+ authBuilder.AddMicrosoftAccount(options =>
+ {
+ options.ClientId = identityOptions.MicrosoftClient;
+ options.ClientSecret = identityOptions.MicrosoftSecret;
+ options.Events = new MicrosoftHandler();
+ });
+ }
+
+ return authBuilder;
+ }
+ }
+}
diff --git a/src/Squidex/Config/Identity/MicrosoftIdentityUsage.cs b/src/Squidex/Config/Identity/MicrosoftIdentityUsage.cs
deleted file mode 100644
index ab9c68358..000000000
--- a/src/Squidex/Config/Identity/MicrosoftIdentityUsage.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-// ==========================================================================
-// MicrosoftIdentityUsage.cs
-// Squidex Headless CMS
-// ==========================================================================
-// Copyright (c) Squidex Group
-// All rights reserved.
-// ==========================================================================
-
-using Microsoft.AspNetCore.Builder;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Options;
-
-namespace Squidex.Config.Identity
-{
- public static class MicrosoftIdentityUsage
- {
- public static IApplicationBuilder UseMyMicrosoftAuthentication(this IApplicationBuilder app)
- {
- var options = app.ApplicationServices.GetService>().Value;
-
- if (options.IsMicrosoftAuthConfigured())
- {
- var googleOptions =
- new MicrosoftAccountOptions
- {
- ClientId = options.MicrosoftClient,
- ClientSecret = options.MicrosoftSecret,
- Events = new MicrosoftHandler()
- };
-
- app.UseMicrosoftAccountAuthentication(googleOptions);
- }
-
- return app;
- }
- }
-}
diff --git a/src/Squidex/Config/Identity/MyIdentityOptions.cs b/src/Squidex/Config/Identity/MyIdentityOptions.cs
index ae8383df3..f38566b94 100644
--- a/src/Squidex/Config/Identity/MyIdentityOptions.cs
+++ b/src/Squidex/Config/Identity/MyIdentityOptions.cs
@@ -18,10 +18,6 @@ namespace Squidex.Config.Identity
public string GoogleSecret { get; set; }
- public string GithubClient { get; set; }
-
- public string GithubSecret { get; set; }
-
public string MicrosoftClient { get; set; }
public string MicrosoftSecret { get; set; }
@@ -39,11 +35,6 @@ namespace Squidex.Config.Identity
return !string.IsNullOrWhiteSpace(AdminEmail) && !string.IsNullOrWhiteSpace(AdminPassword);
}
- public bool IsGithubAuthConfigured()
- {
- return !string.IsNullOrWhiteSpace(GithubClient) && !string.IsNullOrWhiteSpace(GithubSecret);
- }
-
public bool IsGoogleAuthConfigured()
{
return !string.IsNullOrWhiteSpace(GoogleClient) && !string.IsNullOrWhiteSpace(GoogleSecret);
diff --git a/src/Squidex/Controllers/Api/Apps/AppsController.cs b/src/Squidex/Controllers/Api/Apps/AppsController.cs
index 447e31768..e1a39b542 100644
--- a/src/Squidex/Controllers/Api/Apps/AppsController.cs
+++ b/src/Squidex/Controllers/Api/Apps/AppsController.cs
@@ -9,7 +9,6 @@
using System;
using System.Linq;
using System.Threading.Tasks;
-using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using NSwag.Annotations;
using Squidex.Controllers.Api.Apps.Models;
@@ -25,7 +24,7 @@ namespace Squidex.Controllers.Api.Apps
///
/// Manages and configures apps.
///
- [Authorize]
+ [ApiAuthorize]
[ApiExceptionFilter]
[SwaggerTag(nameof(Apps))]
public sealed class AppsController : ControllerBase
diff --git a/src/Squidex/Controllers/Api/Languages/LanguagesController.cs b/src/Squidex/Controllers/Api/Languages/LanguagesController.cs
index aac500468..f87546cb1 100644
--- a/src/Squidex/Controllers/Api/Languages/LanguagesController.cs
+++ b/src/Squidex/Controllers/Api/Languages/LanguagesController.cs
@@ -7,7 +7,6 @@
// ==========================================================================
using System.Linq;
-using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using NSwag.Annotations;
using Squidex.Infrastructure;
@@ -19,7 +18,7 @@ namespace Squidex.Controllers.Api.Languages
///
/// Readonly API to the supported langauges.
///
- [Authorize]
+ [ApiAuthorize]
[ApiExceptionFilter]
[SwaggerTag(nameof(Languages))]
public sealed class LanguagesController : Controller
diff --git a/src/Squidex/Controllers/Api/Users/UsersController.cs b/src/Squidex/Controllers/Api/Users/UsersController.cs
index c517780f9..5ec95aedd 100644
--- a/src/Squidex/Controllers/Api/Users/UsersController.cs
+++ b/src/Squidex/Controllers/Api/Users/UsersController.cs
@@ -11,7 +11,6 @@ using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Threading.Tasks;
-using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using NSwag.Annotations;
@@ -62,7 +61,7 @@ namespace Squidex.Controllers.Api.Users
///
/// 200 => Users returned.
///
- [Authorize]
+ [ApiAuthorize]
[HttpGet]
[Route("users/")]
[ProducesResponseType(typeof(UserDto[]), 200)]
@@ -83,7 +82,7 @@ namespace Squidex.Controllers.Api.Users
/// 200 => User found.
/// 404 => User not found.
///
- [Authorize]
+ [ApiAuthorize]
[HttpGet]
[Route("users/{id}/")]
[ProducesResponseType(typeof(UserDto), 200)]
diff --git a/src/Squidex/Controllers/UI/Account/AccountController.cs b/src/Squidex/Controllers/UI/Account/AccountController.cs
index 2785404b4..952c33452 100644
--- a/src/Squidex/Controllers/UI/Account/AccountController.cs
+++ b/src/Squidex/Controllers/UI/Account/AccountController.cs
@@ -129,16 +129,16 @@ namespace Squidex.Controllers.UI.Account
[HttpGet]
[Route("account/signup/")]
- public IActionResult Signup(string returnUrl = null)
+ public Task Signup(string returnUrl = null)
{
- return LoginView(returnUrl, false, false);
+ return LoginViewAsync(returnUrl, false, false);
}
[HttpGet]
[Route("account/login/")]
- public IActionResult Login(string returnUrl = null)
+ public Task Login(string returnUrl = null)
{
- return LoginView(returnUrl, true, false);
+ return LoginViewAsync(returnUrl, true, false);
}
[HttpPost]
@@ -147,14 +147,14 @@ namespace Squidex.Controllers.UI.Account
{
if (!ModelState.IsValid)
{
- return LoginView(returnUrl, true, true);
+ return await LoginViewAsync(returnUrl, true, true);
}
var result = await signInManager.PasswordSignInAsync(model.Email, model.Password, true, true);
if (!result.Succeeded)
{
- return LoginView(returnUrl, true, true);
+ return await LoginViewAsync(returnUrl, true, true);
}
else if (!string.IsNullOrWhiteSpace(returnUrl))
{
@@ -166,21 +166,20 @@ namespace Squidex.Controllers.UI.Account
}
}
- private IActionResult LoginView(string returnUrl, bool isLogin, bool isFailed)
+ private async Task LoginViewAsync(string returnUrl, bool isLogin, bool isFailed)
{
var allowPasswordAuth = identityOptions.Value.AllowPasswordAuth;
- var providers =
- signInManager.GetExternalAuthenticationSchemes()
- .Select(x => new ExternalProvider(x.AuthenticationScheme, x.DisplayName)).ToList();
+ var externalSchemes = await signInManager.GetExternalAuthenticationSchemesAsync();
+ var externalProviders = externalSchemes.Select(x => new ExternalProvider(x.Name, x.DisplayName)).ToList();
var vm = new LoginVM
{
- ExternalProviders = providers,
+ ExternalProviders = externalProviders,
IsLogin = isLogin,
IsFailed = isFailed,
HasPasswordAuth = allowPasswordAuth,
- HasPasswordAndExternal = allowPasswordAuth && providers.Any(),
+ HasPasswordAndExternal = allowPasswordAuth && externalProviders.Any(),
ReturnUrl = returnUrl
};
diff --git a/src/Squidex/Controllers/UI/Profile/ProfileController.cs b/src/Squidex/Controllers/UI/Profile/ProfileController.cs
index a37f3c9ad..e09e105cd 100644
--- a/src/Squidex/Controllers/UI/Profile/ProfileController.cs
+++ b/src/Squidex/Controllers/UI/Profile/ProfileController.cs
@@ -11,6 +11,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
@@ -34,19 +35,16 @@ namespace Squidex.Controllers.UI.Profile
private readonly IUserPictureStore userPictureStore;
private readonly IAssetThumbnailGenerator assetThumbnailGenerator;
private readonly IOptions identityOptions;
- private readonly IOptions identityCookieOptions;
public ProfileController(
SignInManager signInManager,
UserManager userManager,
IUserPictureStore userPictureStore,
IAssetThumbnailGenerator assetThumbnailGenerator,
- IOptions identityOptions,
- IOptions identityCookieOptions)
+ IOptions identityOptions)
{
this.signInManager = signInManager;
this.identityOptions = identityOptions;
- this.identityCookieOptions = identityCookieOptions;
this.userManager = userManager;
this.userPictureStore = userPictureStore;
this.assetThumbnailGenerator = assetThumbnailGenerator;
@@ -65,7 +63,7 @@ namespace Squidex.Controllers.UI.Profile
[Route("/account/profile/login-add/")]
public async Task AddLogin(string provider)
{
- await HttpContext.Authentication.SignOutAsync(identityCookieOptions.Value.ExternalCookieAuthenticationScheme);
+ await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
var properties =
signInManager.ConfigureExternalAuthenticationProperties(provider,
@@ -182,9 +180,8 @@ namespace Squidex.Controllers.UI.Profile
private async Task GetProfileVM(IUser user, ChangeProfileModel model = null, string errorMessage = null, string successMessage = null)
{
- var providers =
- signInManager.GetExternalAuthenticationSchemes()
- .Select(x => new ExternalProvider(x.AuthenticationScheme, x.DisplayName)).ToList();
+ var externalSchemes = await signInManager.GetExternalAuthenticationSchemesAsync();
+ var externalProviders = externalSchemes.Select(x => new ExternalProvider(x.Name, x.DisplayName)).ToList();
var result = new ProfileVM
{
@@ -192,7 +189,7 @@ namespace Squidex.Controllers.UI.Profile
Email = user.Email,
ErrorMessage = errorMessage,
ExternalLogins = user.Logins,
- ExternalProviders = providers,
+ ExternalProviders = externalProviders,
DisplayName = user.DisplayName(),
HasPassword = await userManager.HasPasswordAsync(user),
HasPasswordAuth = identityOptions.Value.AllowPasswordAuth,
diff --git a/src/Squidex/Pipeline/ApiAuthorizeAttribute.cs b/src/Squidex/Pipeline/ApiAuthorizeAttribute.cs
new file mode 100644
index 000000000..79d8be724
--- /dev/null
+++ b/src/Squidex/Pipeline/ApiAuthorizeAttribute.cs
@@ -0,0 +1,21 @@
+// ==========================================================================
+// ApiAuthorizeAttribute.cs
+// Squidex Headless CMS
+// ==========================================================================
+// Copyright (c) Squidex Group
+// All rights reserved.
+// ==========================================================================
+
+using IdentityServer4.AccessTokenValidation;
+using Microsoft.AspNetCore.Authorization;
+
+namespace Squidex.Pipeline
+{
+ public class ApiAuthorizeAttribute : AuthorizeAttribute
+ {
+ public ApiAuthorizeAttribute()
+ {
+ AuthenticationSchemes = IdentityServerAuthenticationDefaults.AuthenticationScheme;
+ }
+ }
+}
diff --git a/src/Squidex/Pipeline/FileCallbackResultExecutor.cs b/src/Squidex/Pipeline/FileCallbackResultExecutor.cs
index 355d0f48c..d607dbc8c 100644
--- a/src/Squidex/Pipeline/FileCallbackResultExecutor.cs
+++ b/src/Squidex/Pipeline/FileCallbackResultExecutor.cs
@@ -25,7 +25,7 @@ namespace Squidex.Pipeline
{
try
{
- SetHeadersAndLog(context, result);
+ SetHeadersAndLog(context, result, null);
await result.Callback(context.HttpContext.Response.Body);
}
diff --git a/src/Squidex/Pipeline/MustBeAdministratorAttribute.cs b/src/Squidex/Pipeline/MustBeAdministratorAttribute.cs
index fa9a0ba76..ddb71bcc9 100644
--- a/src/Squidex/Pipeline/MustBeAdministratorAttribute.cs
+++ b/src/Squidex/Pipeline/MustBeAdministratorAttribute.cs
@@ -6,12 +6,11 @@
// All rights reserved.
// ==========================================================================
-using Microsoft.AspNetCore.Authorization;
using Squidex.Shared.Identity;
namespace Squidex.Pipeline
{
- public sealed class MustBeAdministratorAttribute : AuthorizeAttribute
+ public sealed class MustBeAdministratorAttribute : ApiAuthorizeAttribute
{
public MustBeAdministratorAttribute()
{
diff --git a/src/Squidex/Pipeline/MustBeAppDeveloperAttribute.cs b/src/Squidex/Pipeline/MustBeAppDeveloperAttribute.cs
index 28ce12b41..5b3dc042a 100644
--- a/src/Squidex/Pipeline/MustBeAppDeveloperAttribute.cs
+++ b/src/Squidex/Pipeline/MustBeAppDeveloperAttribute.cs
@@ -6,12 +6,11 @@
// All rights reserved.
// ==========================================================================
-using Microsoft.AspNetCore.Authorization;
using Squidex.Shared.Identity;
namespace Squidex.Pipeline
{
- public sealed class MustBeAppDeveloperAttribute : AuthorizeAttribute
+ public sealed class MustBeAppDeveloperAttribute : ApiAuthorizeAttribute
{
public MustBeAppDeveloperAttribute()
{
diff --git a/src/Squidex/Pipeline/MustBeAppEditorAttribute.cs b/src/Squidex/Pipeline/MustBeAppEditorAttribute.cs
index 965cf123d..443bf2d12 100644
--- a/src/Squidex/Pipeline/MustBeAppEditorAttribute.cs
+++ b/src/Squidex/Pipeline/MustBeAppEditorAttribute.cs
@@ -6,12 +6,11 @@
// All rights reserved.
// ==========================================================================
-using Microsoft.AspNetCore.Authorization;
using Squidex.Shared.Identity;
namespace Squidex.Pipeline
{
- public sealed class MustBeAppEditorAttribute : AuthorizeAttribute
+ public sealed class MustBeAppEditorAttribute : ApiAuthorizeAttribute
{
public MustBeAppEditorAttribute()
{
diff --git a/src/Squidex/Pipeline/MustBeAppOwnerAttribute.cs b/src/Squidex/Pipeline/MustBeAppOwnerAttribute.cs
index 20ad0e605..b3e069ca4 100644
--- a/src/Squidex/Pipeline/MustBeAppOwnerAttribute.cs
+++ b/src/Squidex/Pipeline/MustBeAppOwnerAttribute.cs
@@ -6,12 +6,11 @@
// All rights reserved.
// ==========================================================================
-using Microsoft.AspNetCore.Authorization;
using Squidex.Shared.Identity;
namespace Squidex.Pipeline
{
- public sealed class MustBeAppOwnerAttribute : AuthorizeAttribute
+ public sealed class MustBeAppOwnerAttribute : ApiAuthorizeAttribute
{
public MustBeAppOwnerAttribute()
{
diff --git a/src/Squidex/Pipeline/MustBeAppReaderAttribute.cs b/src/Squidex/Pipeline/MustBeAppReaderAttribute.cs
index 2ca5282a3..d18c94c56 100644
--- a/src/Squidex/Pipeline/MustBeAppReaderAttribute.cs
+++ b/src/Squidex/Pipeline/MustBeAppReaderAttribute.cs
@@ -6,12 +6,11 @@
// All rights reserved.
// ==========================================================================
-using Microsoft.AspNetCore.Authorization;
using Squidex.Shared.Identity;
namespace Squidex.Pipeline
{
- public sealed class MustBeAppReaderAttribute : AuthorizeAttribute
+ public sealed class MustBeAppReaderAttribute : ApiAuthorizeAttribute
{
public MustBeAppReaderAttribute()
{
diff --git a/src/Squidex/Program.cs b/src/Squidex/Program.cs
index 783accd70..35d74a6e0 100644
--- a/src/Squidex/Program.cs
+++ b/src/Squidex/Program.cs
@@ -8,6 +8,7 @@
using System.IO;
using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
namespace Squidex
{
@@ -20,6 +21,14 @@ namespace Squidex
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup()
+ .ConfigureAppConfiguration((hostContext, options) =>
+ {
+ options.Sources.Clear();
+ options.AddJsonFile("appsettings.json", true, true);
+ options.AddJsonFile($"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json", true);
+ options.AddEnvironmentVariables();
+ options.AddCommandLine(args);
+ })
.Build()
.Run();
}
diff --git a/src/Squidex/Squidex.csproj b/src/Squidex/Squidex.csproj
index 91a6c2bc7..ba48b4a0f 100644
--- a/src/Squidex/Squidex.csproj
+++ b/src/Squidex/Squidex.csproj
@@ -15,9 +15,14 @@
+
+
+
+
+
PreserveNewest
@@ -42,43 +47,33 @@
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
+
-
+
-
+
diff --git a/src/Squidex/Startup.cs b/src/Squidex/Startup.cs
index c2a42f306..deb1601d0 100644
--- a/src/Squidex/Startup.cs
+++ b/src/Squidex/Startup.cs
@@ -25,6 +25,8 @@ using Squidex.Config.Web;
using Squidex.Infrastructure.Log;
using Squidex.Infrastructure.Log.Adapter;
+#pragma warning disable RECS0002 // Convert anonymous method to method group
+
namespace Squidex
{
public class Startup
@@ -37,21 +39,15 @@ namespace Squidex
"/error"
};
- private IConfigurationRoot Configuration { get; }
+ private IConfiguration Configuration { get; }
private IHostingEnvironment Environment { get; }
- public Startup(IHostingEnvironment env)
+ public Startup(IHostingEnvironment env, IConfiguration config)
{
Environment = env;
- var builder = new ConfigurationBuilder()
- .SetBasePath(env.ContentRootPath)
- .AddJsonFile("appsettings.json", true, true)
- .AddJsonFile($"appsettings.{env.EnvironmentName}.json", true)
- .AddEnvironmentVariables();
-
- Configuration = builder.Build();
+ Configuration = config;
}
public IServiceProvider ConfigureServices(IServiceCollection services)
@@ -59,6 +55,7 @@ namespace Squidex
services.AddMySwaggerSettings();
services.AddMyEventFormatter();
services.AddMyDataProtectection(Configuration);
+ services.AddMyAuthentication(Configuration);
services.AddMyIdentity();
services.AddMyIdentityServer();
services.AddMyMvc();
@@ -142,14 +139,10 @@ namespace Squidex
identityApp.UseExceptionHandler("/error");
}
- identityApp.UseMyIdentity();
+ identityApp.UseMyAuthentication();
identityApp.UseMyIdentityServer();
identityApp.UseMyAdminRole();
identityApp.UseMyAdmin();
- identityApp.UseMyApiProtection();
- identityApp.UseMyGoogleAuthentication();
- identityApp.UseMyGithubAuthentication();
- identityApp.UseMyMicrosoftAuthentication();
identityApp.UseStaticFiles();
identityApp.MapWhen(x => IsIdentityRequest(x), mvcApp =>
@@ -169,7 +162,6 @@ namespace Squidex
}
appApi.UseMySwagger();
- appApi.UseMyApiProtection();
appApi.MapWhen(x => !IsIdentityRequest(x), mvcApp =>
{
diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Squidex.Domain.Apps.Core.Tests.csproj b/tests/Squidex.Domain.Apps.Core.Tests/Squidex.Domain.Apps.Core.Tests.csproj
index 7f3e5875b..e2b84e201 100644
--- a/tests/Squidex.Domain.Apps.Core.Tests/Squidex.Domain.Apps.Core.Tests.csproj
+++ b/tests/Squidex.Domain.Apps.Core.Tests/Squidex.Domain.Apps.Core.Tests.csproj
@@ -11,7 +11,6 @@
-
diff --git a/tests/Squidex.Domain.Apps.Read.Tests/Squidex.Domain.Apps.Read.Tests.csproj b/tests/Squidex.Domain.Apps.Read.Tests/Squidex.Domain.Apps.Read.Tests.csproj
index a46de5c85..24478e87f 100644
--- a/tests/Squidex.Domain.Apps.Read.Tests/Squidex.Domain.Apps.Read.Tests.csproj
+++ b/tests/Squidex.Domain.Apps.Read.Tests/Squidex.Domain.Apps.Read.Tests.csproj
@@ -17,7 +17,7 @@
-
+
diff --git a/tests/Squidex.Domain.Apps.Write.Tests/Squidex.Domain.Apps.Write.Tests.csproj b/tests/Squidex.Domain.Apps.Write.Tests/Squidex.Domain.Apps.Write.Tests.csproj
index d891202a4..19ac1d18e 100644
--- a/tests/Squidex.Domain.Apps.Write.Tests/Squidex.Domain.Apps.Write.Tests.csproj
+++ b/tests/Squidex.Domain.Apps.Write.Tests/Squidex.Domain.Apps.Write.Tests.csproj
@@ -10,7 +10,7 @@
-
+
diff --git a/tests/Squidex.Domain.Users.Tests/Squidex.Domain.Users.Tests.csproj b/tests/Squidex.Domain.Users.Tests/Squidex.Domain.Users.Tests.csproj
index 13aa91f47..f54f04636 100644
--- a/tests/Squidex.Domain.Users.Tests/Squidex.Domain.Users.Tests.csproj
+++ b/tests/Squidex.Domain.Users.Tests/Squidex.Domain.Users.Tests.csproj
@@ -11,7 +11,7 @@
-
+
diff --git a/tests/Squidex.Infrastructure.Tests/Squidex.Infrastructure.Tests.csproj b/tests/Squidex.Infrastructure.Tests/Squidex.Infrastructure.Tests.csproj
index 73b94a3c5..feee70e93 100644
--- a/tests/Squidex.Infrastructure.Tests/Squidex.Infrastructure.Tests.csproj
+++ b/tests/Squidex.Infrastructure.Tests/Squidex.Infrastructure.Tests.csproj
@@ -11,11 +11,11 @@
-
+
-
-
+
+
diff --git a/tests/Squidex.Infrastructure.Tests/UsageTracking/BackgroundUsageTrackerTests.cs b/tests/Squidex.Infrastructure.Tests/UsageTracking/BackgroundUsageTrackerTests.cs
index 6259fd841..f91948809 100644
--- a/tests/Squidex.Infrastructure.Tests/UsageTracking/BackgroundUsageTrackerTests.cs
+++ b/tests/Squidex.Infrastructure.Tests/UsageTracking/BackgroundUsageTrackerTests.cs
@@ -114,7 +114,7 @@ namespace Squidex.Infrastructure.UsageTracking
sut.Next();
sut.Dispose();
- A.CallTo(() => usageStore.TrackUsagesAsync(A.Ignored, A.Ignored, A.Ignored, A.Ignored)).MustNotHaveHappened();
+ A.CallTo(() => usageStore.TrackUsagesAsync(A.Ignored, A.Ignored, A.Ignored, A.Ignored)).MustNotHaveHappened();
}
[Fact]