Στις σύγχρονες εφαρμογές δεν είναι απαραίτητο η ίδια η εφαρμογή να αποθηκεύει και να διαχειρίζεται τους κωδικούς πρόσβασης των χρηστών. Αντίθετα, μπορούμε να χρησιμοποιήσουμε έναν Identity Provider, όπως το Microsoft Entra ID, ο οποίος αναλαμβάνει να επιβεβαιώσει την ταυτότητα του χρήστη.
Με απλά λόγια, η εφαρμογή μας δεν χρειάζεται να γνωρίζει τον κωδικό του χρήστη. Ρωτά το Entra ID: «Έχεις επιβεβαιώσει ότι αυτός ο χρήστης είναι πράγματι αυτός που δηλώνει ότι είναι;». Εφόσον η απάντηση είναι θετική, η εφαρμογή μπορεί να συνεχίσει.
Authentication και Authorization
Πριν δούμε τη διαδικασία, πρέπει να ξεχωρίσουμε δύο έννοιες.
Authentication σημαίνει «ποιος είσαι;».
Authorization σημαίνει «τι επιτρέπεται να κάνεις;».
Για παράδειγμα, το Entra ID μπορεί να επιβεβαιώσει ότι ο χρήστης είναι ο nikos@company.com. Αυτό είναι authentication. Το αν ο συγκεκριμένος χρήστης μπορεί να διαγράψει έναν πελάτη είναι authorization και αποτελεί ευθύνη της εφαρμογής.
Ο ρόλος του Microsoft Entra ID
Το Entra ID λειτουργεί ως Identity Provider. Η εφαρμογή μας είναι καταχωρημένη στο Entra ID μέσω ενός App Registration.
Στο App Registration υπάρχουν βασικές πληροφορίες όπως το:
Client ID
Tenant ID
Redirect URI
Το Client ID αναγνωρίζει την εφαρμογή. Δεν είναι password ούτε secret.
Μια ASP.NET Core εφαρμογή μπορεί, για παράδειγμα, να έχει configuration όπως:
{
"AzureAd": {
"TenantId": "...",
"ClientId": "..."
}
}
Με αυτόν τον τρόπο η εφαρμογή γνωρίζει σε ποιο Entra tenant ανήκει και ποια εφαρμογή εκπροσωπεί.
Τι γίνεται όταν ο χρήστης κάνει Login;
Ας υποθέσουμε ότι έχουμε:
[Authorize]
public IActionResult Dashboard()
{
return View();
}
Ο χρήστης επισκέπτεται το /Dashboard, αλλά δεν έχει κάνει login.
Το ASP.NET Core αντιλαμβάνεται ότι απαιτείται authentication και οδηγεί τον χρήστη στο Microsoft Entra ID.
Η απλοποιημένη ροή είναι:
Browser
↓
ASP.NET Core
↓
Microsoft Entra ID
↓
User Login
↓
ASP.NET Core
Ο χρήστης κάνει login στο Entra ID και, ανάλογα με τις ρυθμίσεις του οργανισμού, μπορεί να χρειαστεί password, MFA ή άλλους ελέγχους ασφαλείας.
Σημαντικό είναι ότι ο κωδικός του χρήστη δεν περνάει από τη δική μας εφαρμογή.
Τι επιστρέφει το Entra ID;
Μετά την επιτυχημένη authentication διαδικασία, το Entra ID επιστρέφει πληροφορίες που επιτρέπουν στην εφαρμογή να γνωρίζει την ταυτότητα του χρήστη.
Στο OpenID Connect χρησιμοποιείται το ID Token.
Το ID Token είναι ένα JWT και περιέχει claims, δηλαδή πληροφορίες σχετικά με τον χρήστη.
Για παράδειγμα:
{
"name": "Nikos Stavropoulos",
"preferred_username": "nikos@company.com"
}
Η ASP.NET Core εφαρμογή χρησιμοποιεί αυτές τις πληροφορίες για να δημιουργήσει το authenticated user.
Τι γίνεται μέσα στο ASP.NET Core;
Εδώ βρίσκεται το σημαντικό σημείο για έναν .NET developer.
Το authentication middleware επεξεργάζεται το αποτέλεσμα του authentication και δημιουργεί ένα:
ClaimsPrincipal
Αυτό είναι που τελικά βλέπει η εφαρμογή μέσω:
HttpContext.User
Για παράδειγμα:
User.Identity?.IsAuthenticated
μπορεί να επιστρέψει:
true
και μπορούμε να διαβάσουμε τα claims:
User.Claims
Άρα η διαδικασία είναι:
Microsoft Entra ID
↓
Token
↓
ASP.NET Core Authentication
↓
ClaimsPrincipal
↓
HttpContext.User
Και τι κάνει το [Authorize];
Το [Authorize] δεν κάνει authentication από μόνο του. Λέει στο ASP.NET Core ότι το συγκεκριμένο endpoint απαιτεί authenticated user.
Για παράδειγμα:
[Authorize]
public IActionResult Dashboard()
{
return View();
}
Αν ο χρήστης είναι authenticated, μπορεί να συνεχίσει.
Αν δεν είναι authenticated, ενεργοποιείται η διαδικασία login.
Μπορούμε επίσης να έχουμε authorization με roles ή policies:
[Authorize(Roles = "Admin")]
public IActionResult DeleteUser()
{
...
}
Εδώ πλέον δεν μας ενδιαφέρει μόνο αν ο χρήστης είναι authenticated. Θέλουμε να έχει και τον κατάλληλο ρόλο.
ID Token και Access Token
Εδώ υπάρχει μια πολύ σημαντική διάκριση.
Το ID Token χρησιμοποιείται κυρίως για να πληροφορήσει την εφαρμογή σχετικά με την ταυτότητα του χρήστη.
Το Access Token χρησιμοποιείται όταν μια εφαρμογή θέλει να καλέσει ένα προστατευμένο API.
Για παράδειγμα:
User
↓
Web Application
↓
Orders API
Η Web Application μπορεί να χρειαστεί ένα Access Token για να καλέσει το Orders API.
Το API ελέγχει το token και αποφασίζει αν ο caller έχει την απαιτούμενη πρόσβαση.
Επομένως:
ID Token → Ποιος είναι ο χρήστης;
Access Token → Τι επιτρέπεται να χρησιμοποιήσει;
Πού βρίσκεται το Microsoft.Identity.Web;
Στο ASP.NET Core δεν χρειάζεται να υλοποιήσουμε μόνοι μας όλη αυτή τη διαδικασία.
Η Microsoft παρέχει το Microsoft.Identity.Web, το οποίο διευκολύνει την ενσωμάτωση του Microsoft Entra ID σε ASP.NET Core εφαρμογές.
Ενδεικτικά:
builder.Services
.AddAuthentication()
.AddMicrosoftIdentityWebApp(
builder.Configuration.GetSection("AzureAd"));
Η βιβλιοθήκη αναλαμβάνει μεγάλο μέρος της integration διαδικασίας με το Microsoft identity platform.
Σε ένα Web API χρησιμοποιούμε αντίστοιχα το κατάλληλο Microsoft Identity Web API integration.
Η συνολική εικόνα
Τελικά, η διαδικασία μπορεί να αποτυπωθεί πολύ απλά:
Microsoft Entra ID
│
│ Login
▼
User
│
│ Token
▼
ASP.NET Core
│
▼
Authentication
│
▼
ClaimsPrincipal
│
▼
Authorization
│
▼
Controller
Το βασικό που πρέπει να καταλάβουμε είναι ότι το Entra ID αναλαμβάνει την ταυτοποίηση, ενώ η εφαρμογή μας χρησιμοποιεί την ταυτότητα που προκύπτει για να εφαρμόσει τους δικούς της κανόνες πρόσβασης.
Αυτός ο διαχωρισμός είναι ιδιαίτερα σημαντικός στις enterprise εφαρμογές. Η εφαρμογή δεν χρειάζεται να διαχειρίζεται passwords και authentication μηχανισμούς από την αρχή. Αντίθετα, βασίζεται σε έναν κεντρικό Identity Provider και επικεντρώνεται στο authorization και στους business κανόνες της.
Με αυτόν τον τρόπο το authentication γίνεται ένα ξεχωριστό κομμάτι της αρχιτεκτονικής και μπορεί να χρησιμοποιηθεί με συνέπεια σε πολλές εφαρμογές και APIs.
Top comments (0)