Αυτό το άρθρο δείχνει πώς θα μπορούσε να εφαρμοστεί ο βασικός έλεγχος ταυτότητας σε μια εφαρμογή ASP.NET Core. Αυτός δεν είναι ο συνιστώμενος τρόπος εφαρμογής ασφάλειας για τις ροές χρηστών, καθώς ο κωδικός πρόσβασης αποστέλλεται πάντα με κάθε αίτημα, αλλά η ροή μερικές φορές απαιτείται για την εφαρμογή ενός προτύπου ή μερικές φορές χρειάζεται να υποστηρίξετε τη μία πλευρά μιας ροής ελέγχου ταυτότητας που το απαιτεί.
Κώδικας: https://github.com/damienbod/OAuthGrantExchangeOidcDownstreamApi
Υλοποίηση πελάτη
Μια υλοποίηση προγράμματος-πελάτη πρέπει να στείλει μια κεφαλίδα εξουσιοδότησης με ένα clientId και ένα clientSecret που διαχωρίζονται χρησιμοποιώντας τον χαρακτήρα «:» και κωδικοποιούνται χρησιμοποιώντας το base64. Το μυστικό κατακερματίζεται χρησιμοποιώντας το SHA256, ώστε να μην σταλεί το αρχικό μυστικό στο αίτημα, αλλά αυτό δεν βελτιώνει πολύ την ασφάλεια, απλώς αποτρέπει την κοινή χρήση του αρχικού μυστικού της εφαρμογής. Το αίτημα αποστέλλεται χρησιμοποιώντας HTTPS και έτσι οι κεφαλίδες κρυπτογραφούνται.
private static string CreateBasicAuthenticationHeader(
GetDelegatedApiTokenOAuthTokenExchangeModel reqData)
{
var builder = new StringBuilder()
.Append(reqData.ClientId)
.Append(':')
.Append(OauthTokenExchangeExtentions
.ToSha256(reqData.ClientSecret));
var credentials = Convert.ToBase64String(
Encoding.ASCII.GetBytes(builder.ToString()));
return credentials;
}
Ο κατακερματισμός ShA256 υλοποιείται χρησιμοποιώντας μια απλή μέθοδο που επιστρέφει μια συμβολοσειρά base64 από αυτήν.
public static string ToSha256(string text)
{
using var sha256 = SHA256.Create();
var bytes = Encoding.UTF8.GetBytes(text);
var hash = sha256.ComputeHash(bytes);
return Convert.ToBase64String(hash);
}
Τα διαπιστευτήρια αποστέλλονται χρησιμοποιώντας την κεφαλίδα Έλεγχος ταυτότητας.
string credentials = CreateBasicAuthenticationHeader(reqData);
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Basic", credentials);
Υλοποίηση διακομιστή
Το τμήμα διακομιστή της ροής υλοποιείται χρησιμοποιώντας το idunno.Authentication.Basic Πακέτο Nuget. Τα διαπιστευτήρια επικυρώνονται χρησιμοποιώντας τον ίδιο κατακερματισμό και ελέγχονται με τις αναμενόμενες τιμές από τη διαμόρφωση.
services.AddAuthentication(BasicAuthenticationDefaults.AuthenticationScheme)
.AddBasic(options =>
{
options.Realm = "oauthtokenexchange";
options.Events = new BasicAuthenticationEvents
{
OnValidateCredentials = context =>
{
var config = context.HttpContext.RequestServices
.GetService<IOptions<OauthTokenExchangeConfiguration>>();
if(ValidateBasicAuthentication.IsValid(context.Username,
context.Password, config.Value))
{
var claims = new[]
{
new Claim( ClaimTypes.NameIdentifier,
context.Username,
ClaimValueTypes.String,
context.Options.ClaimsIssuer),
new Claim( ClaimTypes.Name,
context.Username,
ClaimValueTypes.String,
context.Options.ClaimsIssuer)
};
context.Principal = new ClaimsPrincipal(
new ClaimsIdentity(claims, context.Scheme.Name));
context.Success();
}
return Task.CompletedTask;
}
};
});
ο ValidateBasicAuthentication η τάξη ελέγχει τα χρησιμοποιημένα διαπιστευτήρια.
public static class ValidateBasicAuthentication
{
public static bool IsValid(
string clientId,
string clientSecret,
OauthTokenExchangeConfiguration oauthTokenExchangeConfiguration)
{
if(!clientId.Equals(oauthTokenExchangeConfiguration.ClientId))
{
return false;
};
if (!clientSecret.Equals(
OauthTokenExchangeExtentions.ToSha256(
oauthTokenExchangeConfiguration.ClientSecret)))
{
return false;
};
return true;
}
}
Ο βασικός έλεγχος ταυτότητας μπορεί να επικυρωθεί στο χαρακτηριστικό εξουσιοδότησης χρησιμοποιώντας το σωστό σχήμα.
[Authorize(AuthenticationSchemes = BasicAuthenticationDefaults.AuthenticationScheme)]
[HttpPost("~/connect/oauthTokenExchangetoken"), Produces("application/json")]
public async Task<IActionResult> Exchange([FromForm] OauthTokenExchangePayload oauthTokenExchangePayload)
{
// business
}
Αυτό λειτουργεί καλά, αλλά η αποστολή του κωδικού πρόσβασης και του ονόματος κατόπιν αιτήματος δεν είναι πάντα ο καλύτερος τρόπος εφαρμογής ελέγχου ταυτότητας. Αυτό θα πρέπει να χρησιμοποιείται μόνο εάν απαιτείται κατά την εφαρμογή ενός προτύπου. Υπάρχουν καλύτεροι τρόποι και πιο ασφαλείς τρόποι για την ασφάλεια των API.
Συνδέσεις
https://github.com/blowdart/idunno.Authentication/tree/dev/src/idunno.Authentication.Basic