diff --git a/src/OrchardCore.Modules/OrchardCore.Users/GraphQL/CurrentUserQuery.cs b/src/OrchardCore.Modules/OrchardCore.Users/GraphQL/CurrentUserQuery.cs
new file mode 100644
index 00000000000..7acaf54d6e3
--- /dev/null
+++ b/src/OrchardCore.Modules/OrchardCore.Users/GraphQL/CurrentUserQuery.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+using GraphQL.Resolvers;
+using GraphQL.Types;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Localization;
+using Microsoft.Extensions.Options;
+using OrchardCore.Apis.GraphQL;
+using OrchardCore.ContentManagement.GraphQL.Options;
+using OrchardCore.ContentManagement.Metadata;
+using OrchardCore.ContentManagement.Metadata.Models;
+using OrchardCore.Users.Models;
+using OrchardCore.Users.Services;
+
+namespace OrchardCore.Users.GraphQL;
+
+///
+/// Registers the current user including its custom user settings as a query.
+///
+internal class CurrentUserQuery : ISchemaBuilder
+{
+ private readonly IHttpContextAccessor _httpContextAccessor;
+ private readonly IOptions _contentOptionsAccessor;
+ protected readonly IStringLocalizer S;
+
+ public CurrentUserQuery(
+ IHttpContextAccessor httpContextAccessor,
+ IOptions contentOptionsAccessor,
+ IStringLocalizer localizer)
+ {
+ _httpContextAccessor = httpContextAccessor;
+ _contentOptionsAccessor = contentOptionsAccessor;
+ S = localizer;
+ }
+
+ public async Task BuildAsync(ISchema schema)
+ {
+ // Build a user type that includes all custom user settings.
+ var serviceProvider = _httpContextAccessor.HttpContext.RequestServices;
+ var contentDefinitionManager = serviceProvider.GetRequiredService();
+ var contentTypes = await contentDefinitionManager.ListTypeDefinitionsAsync();
+
+ var userType = serviceProvider.GetRequiredService();
+
+ // Note: The content types are already added to GraphQL by the ContentTypeQuery. Just add them to the user type.
+ foreach (var typeDefinition in contentTypes.Where(t => t.StereotypeEquals("CustomUserSettings")))
+ {
+ // Skip hidden types
+ if (_contentOptionsAccessor.Value.ShouldHide(typeDefinition))
+ {
+ continue;
+ }
+
+ userType.AddField(schema, typeDefinition);
+ }
+
+ var currentUserField = new FieldType
+ {
+ Name = "me",
+ Description = S["Gets the currently authenticated user."],
+ ResolvedType = userType,
+ Resolver = new AsyncFieldResolver(async context =>
+ {
+ var userService = context.RequestServices!.GetRequiredService();
+ var user = await userService.GetAuthenticatedUserAsync(((GraphQLUserContext)context.UserContext).User);
+
+ return user as User;
+ }),
+ };
+
+ schema.Query.AddField(currentUserField);
+ }
+
+ public Task GetIdentifierAsync()
+ {
+ var contentDefinitionManager = _httpContextAccessor.HttpContext!.RequestServices.GetRequiredService();
+ return contentDefinitionManager.GetIdentifierAsync();
+ }
+}
diff --git a/src/OrchardCore.Modules/OrchardCore.Users/GraphQL/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Users/GraphQL/Startup.cs
new file mode 100644
index 00000000000..4dba4a80de3
--- /dev/null
+++ b/src/OrchardCore.Modules/OrchardCore.Users/GraphQL/Startup.cs
@@ -0,0 +1,15 @@
+using Microsoft.Extensions.DependencyInjection;
+using OrchardCore.Apis.GraphQL;
+using OrchardCore.Modules;
+
+namespace OrchardCore.Users.GraphQL;
+
+[RequireFeatures("OrchardCore.Apis.GraphQL", "OrchardCore.Contents")]
+public class Startup : StartupBase
+{
+ public override void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSingleton();
+ services.AddTransient();
+ }
+}
diff --git a/src/OrchardCore.Modules/OrchardCore.Users/GraphQL/UserType.cs b/src/OrchardCore.Modules/OrchardCore.Users/GraphQL/UserType.cs
new file mode 100644
index 00000000000..9f43c89cc0f
--- /dev/null
+++ b/src/OrchardCore.Modules/OrchardCore.Users/GraphQL/UserType.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Linq;
+using GraphQL.Types;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Localization;
+using OrchardCore.ContentManagement.Metadata.Models;
+using OrchardCore.Users.Models;
+using OrchardCore.Users.Services;
+
+namespace OrchardCore.Users.GraphQL;
+
+public class UserType : ObjectGraphType
+{
+ protected readonly IStringLocalizer S;
+
+ public UserType(IStringLocalizer localizer)
+ {
+ S = localizer;
+
+ Name = "User";
+ Description = S["Represents the currently authenticated user."];
+
+ Field(u => u.UserId).Description(S["The id of the user."]);
+ Field(u => u.UserName).Description(S["The name of the user."]);
+ Field(u => u.Email, nullable: true).Description(S["The email of the user."]);
+ Field(u => u.PhoneNumber, nullable: true).Description(S["The phone number of the user."]);
+ }
+
+ // Adds a custom user settings field
+ internal void AddField(ISchema schema, ContentTypeDefinition typeDefinition)
+ {
+ var contentItemType = schema.AdditionalTypeInstances.SingleOrDefault(t => t.Name == typeDefinition.Name);
+ if (contentItemType == null)
+ {
+ // This error would indicate that this graph type is build too early.
+ throw new InvalidOperationException("ContentTypeDefinition has not been registered in GraphQL");
+ }
+
+ this.FieldAsync(typeDefinition.Name, contentItemType, S["Custom user settings of {0}.", typeDefinition.DisplayName], resolve: async context =>
+ {
+ // We don't want to create an empty content item if it does not exist.
+ if (context.Source is User user &&
+ user.Properties.ContainsKey(context.FieldDefinition.ResolvedType.Name))
+ {
+ var customUserSettingsService = context.RequestServices!.GetRequiredService();
+ var settingsType = await customUserSettingsService.GetSettingsTypeAsync(context.FieldDefinition.ResolvedType.Name);
+
+ return await customUserSettingsService.GetSettingsAsync(user, settingsType);
+ }
+
+ return null;
+ });
+ }
+}
diff --git a/src/OrchardCore.Modules/OrchardCore.Users/OrchardCore.Users.csproj b/src/OrchardCore.Modules/OrchardCore.Users/OrchardCore.Users.csproj
index c074f55b1b5..eaaf839674a 100644
--- a/src/OrchardCore.Modules/OrchardCore.Users/OrchardCore.Users.csproj
+++ b/src/OrchardCore.Modules/OrchardCore.Users/OrchardCore.Users.csproj
@@ -18,8 +18,10 @@
+
+