131 lines
4.4 KiB
C#
131 lines
4.4 KiB
C#
namespace MyOffice.Web.Auth;
|
|
|
|
using DbContext;
|
|
using Infrastructure;
|
|
using Microsoft.Extensions.Options;
|
|
using OpenIddict.Abstractions;
|
|
using static OpenIddict.Abstractions.OpenIddictConstants;
|
|
|
|
public sealed class OpenIddictSeeder : IHostedService
|
|
{
|
|
private readonly IServiceProvider _serviceProvider;
|
|
private readonly IConfiguration _configuration;
|
|
private readonly ILogger<OpenIddictSeeder> _logger;
|
|
|
|
public OpenIddictSeeder(
|
|
IServiceProvider serviceProvider,
|
|
IConfiguration configuration,
|
|
ILogger<OpenIddictSeeder> logger
|
|
)
|
|
{
|
|
_serviceProvider = serviceProvider;
|
|
_configuration = configuration;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task StartAsync(CancellationToken cancellationToken)
|
|
{
|
|
await using var scope = _serviceProvider.CreateAsyncScope();
|
|
|
|
await RegisterScopesAsync(scope.ServiceProvider, cancellationToken);
|
|
await RegisterClientAsync(scope.ServiceProvider, cancellationToken);
|
|
}
|
|
|
|
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
|
|
|
private async Task RegisterScopesAsync(IServiceProvider provider, CancellationToken cancellationToken)
|
|
{
|
|
var manager = provider.GetRequiredService<IOpenIddictScopeManager>();
|
|
|
|
if (await manager.FindByNameAsync(OpenIddictAuthConstants.ApiScope, cancellationToken) is null)
|
|
{
|
|
await manager.CreateAsync(new OpenIddictScopeDescriptor
|
|
{
|
|
Name = OpenIddictAuthConstants.ApiScope,
|
|
DisplayName = OpenIddictAuthConstants.ApiFriendlyName,
|
|
Resources = { OpenIddictAuthConstants.ApiScope }
|
|
}, cancellationToken);
|
|
|
|
_logger.LogInformation("Created OpenIddict scope {Scope}.", OpenIddictAuthConstants.ApiScope);
|
|
}
|
|
|
|
if (await manager.FindByNameAsync(OpenIddictAuthConstants.RolesScope, cancellationToken) is null)
|
|
{
|
|
await manager.CreateAsync(new OpenIddictScopeDescriptor
|
|
{
|
|
Name = OpenIddictAuthConstants.RolesScope,
|
|
DisplayName = "User roles"
|
|
}, cancellationToken);
|
|
|
|
_logger.LogInformation("Created OpenIddict scope {Scope}.", OpenIddictAuthConstants.RolesScope);
|
|
}
|
|
}
|
|
|
|
private async Task RegisterClientAsync(IServiceProvider provider, CancellationToken cancellationToken)
|
|
{
|
|
var manager = provider.GetRequiredService<IOpenIddictApplicationManager>();
|
|
var globalSettings = provider.GetRequiredService<GlobalSettings>();
|
|
|
|
var redirectUri = BuildRedirectUri(globalSettings.Host);
|
|
var existing = await manager.FindByClientIdAsync(OpenIddictAuthConstants.SpaClientId, cancellationToken);
|
|
var descriptor = CreateSpaClientDescriptor(redirectUri);
|
|
|
|
if (existing is null)
|
|
{
|
|
await manager.CreateAsync(descriptor, cancellationToken);
|
|
_logger.LogInformation("Created OpenIddict client {ClientId}.", OpenIddictAuthConstants.SpaClientId);
|
|
return;
|
|
}
|
|
|
|
var currentRedirectUris = await manager.GetRedirectUrisAsync(existing, cancellationToken);
|
|
foreach (var uri in currentRedirectUris)
|
|
{
|
|
if (!string.Equals(uri, redirectUri.ToString(), StringComparison.Ordinal))
|
|
descriptor.RedirectUris.Add(new Uri(uri, UriKind.Absolute));
|
|
}
|
|
|
|
await manager.UpdateAsync(existing, descriptor, cancellationToken);
|
|
_logger.LogInformation("Updated OpenIddict client {ClientId}.", OpenIddictAuthConstants.SpaClientId);
|
|
}
|
|
|
|
internal static OpenIddictApplicationDescriptor CreateSpaClientDescriptor(Uri redirectUri)
|
|
{
|
|
var descriptor = new OpenIddictApplicationDescriptor
|
|
{
|
|
ClientId = OpenIddictAuthConstants.SpaClientId,
|
|
DisplayName = "MyOffice SPA",
|
|
ClientType = ClientTypes.Public,
|
|
ConsentType = ConsentTypes.Implicit,
|
|
Permissions =
|
|
{
|
|
Permissions.Endpoints.Authorization,
|
|
Permissions.Endpoints.Token,
|
|
Permissions.Endpoints.EndSession,
|
|
Permissions.GrantTypes.AuthorizationCode,
|
|
Permissions.GrantTypes.Password,
|
|
Permissions.GrantTypes.RefreshToken,
|
|
Permissions.Prefixes.GrantType + OpenIddictAuthConstants.ExternalGrantType,
|
|
Permissions.ResponseTypes.Code,
|
|
Permissions.Scopes.Email,
|
|
Permissions.Scopes.Profile,
|
|
Permissions.Scopes.Roles,
|
|
Permissions.Prefixes.Scope + Scopes.OpenId,
|
|
Permissions.Prefixes.Scope + Scopes.OfflineAccess,
|
|
Permissions.Prefixes.Scope + OpenIddictAuthConstants.ApiScope,
|
|
Permissions.Prefixes.Scope + OpenIddictAuthConstants.RolesScope
|
|
}
|
|
};
|
|
|
|
descriptor.RedirectUris.Add(redirectUri);
|
|
return descriptor;
|
|
}
|
|
|
|
internal static Uri BuildRedirectUri(string? host)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(host))
|
|
return new Uri("http://localhost:4300/silent-refresh.html");
|
|
|
|
return new Uri($"{host.TrimEnd('/')}/silent-refresh.html");
|
|
}
|
|
}
|