Управляющим пользователям разрешено входить в клиенты с помощью единого входа. - PullRequest
0 голосов
/ 08 мая 2018

IdentityServer4 обеспечивает работу единого входа вместе с функциями STS. SSO работает, как только клиенты проверены согласно OAuth OpenId Connect. Таким образом, пользователи, если личность основана на cookie.

Мне было интересно, если бы кто-нибудь реализовал это для многопользовательской моды, чтобы запретить пользователям разрешать только набор клиентов (значит, SSO все еще работает среди них - давайте назовем группу арендатором). Когда речь идет о недопустимых пользователях и клиентах, сервер идентификации должен перевести их на экран входа в систему.

Конфигурация при запуске - хранилище AspNetIdentity для пользователей

     services.AddIdentity<ApplicationUser, IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddUserManager<CustomUserManager>()
                .AddSignInManager<CustomSignInManager>()
                .AddDefaultTokenProviders();
            //TODO Tenant based cookie SaasKit/Finbuckle
            services.ConfigureApplicationCookie(cookieOptions =>
            {
                cookieOptions.Cookie = new Microsoft.AspNetCore.Http.CookieBuilder
                {
                    Name="Tenant_Cookie"
                };
            });   

 var builder = services.AddIdentityServer(options =>
                {
                    options.Events.RaiseErrorEvents = true;
                    options.Events.RaiseInformationEvents = true;
                    options.Events.RaiseFailureEvents = true;
                    options.Events.RaiseSuccessEvents = true;
                }).AddSigningCredential(GetSigningCertificate("my", "a7 e2 f5 f7 9a b8 8c 86 2c 37 f5 22 1b ea 8c 19 b1 58 99 3c", true))                  
                .AddResponseGenerators()
                .AddCustomAuthorizeRequestValidator<TenantAuthorizeRequestValidator>()
                .AddCustomTokenRequestValidator<TenantTokenRequestValidator>()
                .AddInMemoryIdentityResources(Config.GetIdentityResources())
                .AddInMemoryApiResources(Config.GetApiResources())
                .AddInMemoryClients(Config.GetClients())
                .AddProfileService<CustomProfileService>()
                .AddAspNetIdentity<ApplicationUser>();

Валидатор запроса Tenant Token - проверка пользователя и клиента

 public class TenantTokenRequestValidator : ICustomTokenRequestValidator
{
    HttpContext _context;
    IClientService _clientService;
    public TenantTokenRequestValidator(IHttpContextAccessor contextAccessor, IClientService clientService)
    {
        _context = contextAccessor.HttpContext;
        _clientService = clientService;
    }

    public Task ValidateAsync(CustomTokenRequestValidationContext context)
    {
        if (!context.Result.IsError)
        {
            //AuthorizationCode authorization_code
            if (context.Result.ValidatedRequest.UserName!=null && 
                !_clientService.IsValidUser(context.Result.ValidatedRequest.Client.ClientId,context.Result.ValidatedRequest.UserName))
            {
                context.Result.IsError = true;
                context.Result.Error = "UnauthorizedUser";
            }
        }

        return Task.CompletedTask;
    }
}

Валидатор запроса авторизации арендатора - Валидат клиента и арендатора

 public class TenantAuthorizeRequestValidator : ICustomAuthorizeRequestValidator
{
    HttpContext _context;
    ITenantService _tenantService;
    public TenantAuthorizeRequestValidator(IHttpContextAccessor contextAccessor,ITenantService tenantService)
    {
        _context = contextAccessor.HttpContext;
        _tenantService = tenantService;
    }
    public Task ValidateAsync(CustomAuthorizeRequestValidationContext context)
    {
        if (!context.Result.IsError)
        {
            var tenant = context.Result.ValidatedRequest.GetTenant();
            if (!string.IsNullOrEmpty(tenant))
            {                  
                if (!_tenantService.IsValidClient(tenant,context.Result.ValidatedRequest.ClientId))
                {
                    context.Result.IsError = true;
                    context.Result.Error = OidcConstants.AuthorizeErrors.UnauthorizedClient;
                }
                context.Result.ValidatedRequest.ClientClaims.Add(new Claim(
                TenantConstants.TokenKey,
                tenant,
                IdentityServerConstants.ClaimValueTypes.Json));
            }             


            //Find a way to respond the error message
        }

        return Task.CompletedTask;
    }
}

База данных похожа на

public static Dictionary<string, string[]> TenantClients()
    {
        return new Dictionary<string, string[]>()
        {
            { "tenant1",new string[]{ "tenant1.mvc","tenant1.mvc2" } },
            { "tenant2",new string[]{ "tenant2.mvc" } }
        };
    }
public static Dictionary<string, string[]> ClientUsers()
    {
        return new Dictionary<string, string[]>()
        {
            { "tenant1.mvc", new string[]{"alice","bob"} },
            { "tenant1.mvc2", new string[]{"alice","bob"} },
            { "tenant2.mvc", new string[]{"alice"}}
        };
    }

Я проверяю клиента и арендатора, а также клиента и пользователя с помощью вышеуказанного. Однако не удалось получить cookie-файлы, основанные на клиенте, поэтому разные логины будут работать в одном сеансе браузера с разными cookie-файлами. Saaskit, похоже, не очень хорошо работает с ядром aspnet 2.0, не найдя выхода с помощью finbuckle.

вопрос - Как установить имя куки с арендатором? разрешение из запроса на основе значений acr контекста. этот подход работает?

1 Ответ

0 голосов
/ 09 июля 2018

Мы закончили тем, что добавили дополнительный пакет специфичных для клиента утверждений в учетные записи пользователей и установили политику авторизации на основе входящих утверждений.

Например-

Ресурс Api хочет ограничить доступ на основе области действия в токене, что хорошо для проверки клиента, а также для проверки пользователя ищет определенную заявку в токене и предоставляет доступ.

При вышеупомянутом подходе мы должны были поддерживать заявки для пользователей, поступающих через пользовательский интерфейс, для других клиентов, обращающихся к серверу без сервера, в претензии клиентов.

Хотя это не лучший подход, это решило наше текущее требование.

...