Jaki sposób autentykacji najlepszy?

0

Cześć, mam pytanie, czy 'pakiet' Identity nie jest wystarczający do autentykacji i autoryzacji w aplikacji? Ma jakieś wady? Z tego co widzę, to zawiera tak jakby dużo predefiniowanych opcji.
Widzę, że często jest używane także OAuth i JWT Bearer(?),
na jakiej postawie mam wybrać, któryś z wyżej wymienionych?

W autentykacji i autoryzacji jestem świeży, po prostu się pogubiłem a chciałbym to ogarnąć a nie rozumiem, jaki system dla mojej strony byłby najlepszy (najważniejsze bezpieczny), czego się używa najczęściej?

1

Odsyłam do https://knews.vip/pl/q/so4596[...]y-jwt-ktorego-uzyc-i-dlaczego , tam jest wyjaśnienie oraz odniesienie do kolejnych artykułów

6

Trochę mylisz pojęcia- co zrozumiałe, jak sam napisałeś gubisz się w tym, o co nie trudno tak naprawdę jak się pierwszy raz zderza z tym zagadnieniem.

Przede wszystkim to OAuth to standard pozwalający na integrację z różnymi serwisami w celu logowania użytkowników (logowanie za pomocą kont Google, Facebook itp). JWT to również standard, ale z perspektywy programisty to przede wszystkim jedna z metod przesyłania informacji o użytkownikach, i pozwalająca na ich uwierzutelnianie. Alternatywą najczęściej jest zastosowanie informacji o sesji użytkownika przesyłanej w cookies.

Identity to z kolei framework pozwalający na korzystanie z tego wszystkiego. Nie jest alternatywą dla nich. I jak najbardziej warto z tego korzystać, bo jest to sprawdzona, dobrze udokumentowana technologia.

1

Mam mieszane uczucia co do tej libki. Poskładanie jej miliona extension methodów do service collection to walka przez mękę jak się tego nie dotykało przez pół roku albo podnosi wersję .NETa, bo "nagle" zmieniają się metody, buildery - ogólnie API, no i generalnie baaardzo dużo pod spodem robi.

Z jednej strony konceptualnie wszystko wygląda tak, jakby wystarczyło nadpisać auth middleware i można się uwierzytelniać nawet hasłem wyciągniętym z obrazka zuploadowanego przez usera w formularzu, gdzie samo Identity wygląda jak tylko abstrakcja nad obsługą logowania(dość rozbudowany trzeba przyznać), to jednak w praktyce idzie to gorzej.

O ile z Cookie based auth wszystko idzie gładko, to połączenia Identity z JWT nigdy nie widziałem* i nie udało mi się nic znaleźć poza jakimś przykładzie w MS docsach w oparciu o IdentityServer

Nie wiem, jakoś spinanie Identity z innymi rozwiązaniami, providerami itd. wydaje mi się być słabo udokumentowane. Jest niby w docsach sekcja Identity(lib)+SPA, ale wrzucają tam sobie IdentityServer - wtf?

A to tylko appki typu backend+front, a gdzie zabawy w organizacje, sso, federacje, tenants.

Nie wiem, cały czas mam uczucie jakbym jakąś prostą rzecz pomijał przy Identity przez co nie rozumiem jak tego zręcznie używać

* in fact, widziałem, ale to bardziej przypominało hakowanie

3

@WeiXiao: używanie JWT z Identity to tylko kwestia konfiguracji. Po prostu domyślna opcja to cookies, więc trzeba skonfigurować używanie JWT. Będę miał później chwilę to załączę przykład.

2

Tutaj przykładowy kod konfigurujący uwierzytelnianie JWT. Cała reszta działa tak samo, czyli zabezpieczamy endpointy za pomocą atrybutu Authorize lub ustawiamy globalny filtr aby domyślnie nam zabezpieczył całe API.

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(o => ConfigureJwtBearerOptions(o, config));

services.AddAuthorization(ConfigureAuthorizationOptions);

private static void ConfigureJwtBearerOptions(JwtBearerOptions options, AppConfiguration config)
{
    var signingKey = Encoding.UTF8.GetBytes(config.Security.JwtKey);
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = config.Security.JwtIssuer,
        ValidAudience = config.Security.JwtIssuer,
        IssuerSigningKey = new SymmetricSecurityKey(signingKey)
    };
}

private static void ConfigureAuthorizationOptions(AuthorizationOptions options)
{
    var policy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
        .Build();

    options.AddPolicy(Constants.DefaultAuthenticationPolicyName, policy);
}
2

@Aventus: działa jak złoto, dzięki.

Tak właściwie to zwykłe JWT, ale w sumie teraz zrozumiałem ten podział odpowiedzialności.

Wrzucam jakby ktoś się chciał pobawić (zasady użyte tutaj przy walidacji JWT nie nadające się na proda)

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddDbContext<ApplicationDbContext>(options => options.UseSqlite("Filename=db.db"));

    services
        .AddDefaultIdentity<ApplicationUser>()
        .AddUserStore<ApplicationDbContext>();

    services
        .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(o => ConfigureJwtBearerOptions(o));

    services
        .AddAuthorization(ConfigureAuthorizationOptions);

    services
        .AddControllersWithViews();
}

private static void ConfigureJwtBearerOptions(JwtBearerOptions options)
{
    var key = Encoding.ASCII.GetBytes("[email protected]#");
    options.TokenValidationParameters = new TokenValidationParameters
    {
        IssuerSigningKey = new SymmetricSecurityKey(key),
        ValidateIssuer = false,
        ValidateAudience = false,
        ClockSkew = TimeSpan.Zero
    };
}

private static void ConfigureAuthorizationOptions(AuthorizationOptions options)
{
    var policy = new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
                .Build();

    options.AddPolicy("test", policy);
}

[Authorize(Policy = "test")]
public IActionResult Privacy()
{
    return Ok("15");
}

[HttpGet]
public IActionResult Test()
{
    return Ok(GenerateJwtToken());
}

private string GenerateJwtToken()
{
    var tokenHandler = new JwtSecurityTokenHandler();
    var key = Encoding.ASCII.GetBytes("[email protected]#");
    var tokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new ClaimsIdentity(new[] { new Claim("id", "1234567890") }),
        SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
    };
    var token = tokenHandler.CreateToken(tokenDescriptor);
    return tokenHandler.WriteToken(token);
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0