DEV Community

nikosst
nikosst

Posted on Edited on

Πώς λειτουργεί το Authentication με Microsoft Entra ID στο ASP.NET Core

Στις σύγχρονες εφαρμογές δεν είναι απαραίτητο η ίδια η εφαρμογή να αποθηκεύει και να διαχειρίζεται τους κωδικούς πρόσβασης των χρηστών. Αντίθετα, μπορούμε να χρησιμοποιήσουμε έναν 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
Enter fullscreen mode Exit fullscreen mode

Το Client ID αναγνωρίζει την εφαρμογή. Δεν είναι password ούτε secret.

Μια ASP.NET Core εφαρμογή μπορεί, για παράδειγμα, να έχει configuration όπως:

{
  "AzureAd": {
    "TenantId": "...",
    "ClientId": "..."
  }
}
Enter fullscreen mode Exit fullscreen mode

Με αυτόν τον τρόπο η εφαρμογή γνωρίζει σε ποιο Entra tenant ανήκει και ποια εφαρμογή εκπροσωπεί.


Τι γίνεται όταν ο χρήστης κάνει Login;

Ας υποθέσουμε ότι έχουμε:

[Authorize]
public IActionResult Dashboard()
{
    return View();
}
Enter fullscreen mode Exit fullscreen mode

Ο χρήστης επισκέπτεται το /Dashboard, αλλά δεν έχει κάνει login.

Το ASP.NET Core αντιλαμβάνεται ότι απαιτείται authentication και οδηγεί τον χρήστη στο Microsoft Entra ID.

Η απλοποιημένη ροή είναι:

Browser
   ↓
ASP.NET Core
   ↓
Microsoft Entra ID
   ↓
User Login
   ↓
ASP.NET Core
Enter fullscreen mode Exit fullscreen mode

Ο χρήστης κάνει 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"
}
Enter fullscreen mode Exit fullscreen mode

Η ASP.NET Core εφαρμογή χρησιμοποιεί αυτές τις πληροφορίες για να δημιουργήσει το authenticated user.


Πού βρίσκεται το OpenID Connect;

Για να καταλάβουμε πώς λειτουργεί το authentication με το Microsoft Entra ID, πρέπει πρώτα να γνωρίζουμε ότι το Entra ID δεν χρησιμοποιεί έναν δικό του, απομονωμένο μηχανισμό επικοινωνίας με κάθε εφαρμογή. Βασίζεται σε διεθνή πρωτόκολλα, κυρίως το OAuth 2.0 και το OpenID Connect (OIDC).

Το OAuth 2.0 αφορά κυρίως το authorization, δηλαδή την πρόσβαση μιας εφαρμογής σε έναν προστατευμένο πόρο. Το OpenID Connect επεκτείνει το OAuth 2.0 και προσθέτει τη δυνατότητα του authentication, δηλαδή την επιβεβαίωση της ταυτότητας του χρήστη.

Μπορούμε επομένως να το δούμε απλά ως εξής:

             Microsoft Entra ID
                    │
                    │ χρησιμοποιεί
                    ▼
           ┌───────────────────┐
           │    OAuth 2.0      │
           │  Authorization    │
           └─────────┬─────────┘
                     │
                     │ επεκτείνεται από
                     ▼
           ┌───────────────────┐
           │ OpenID Connect    │
           │  Authentication   │
           └───────────────────┘
Enter fullscreen mode Exit fullscreen mode

Άρα, όταν ένας χρήστης κάνει login σε μια ASP.NET Core εφαρμογή μέσω Entra ID, το OpenID Connect είναι το πρωτόκολλο που χρησιμοποιείται για να μεταφερθεί στην εφαρμογή η πληροφορία ότι ο χρήστης ταυτοποιήθηκε επιτυχώς.


Τι συμβαίνει στην πράξη;

Η εφαρμογή μας ζητά από το Entra ID να κάνει authentication για τον χρήστη.

Η ροή είναι περίπου:

Browser
│
│ Login
▼
ASP.NET Core Application
│
│ Authentication request
▼
Microsoft Entra ID
│
│ OpenID Connect
│
│ User authenticates
▼
Microsoft Entra ID
│
│ Authentication result
▼
ASP.NET Core Application

Το Entra ID, αφού ολοκληρώσει την ταυτοποίηση, επιστρέφει τα απαραίτητα tokens. Στο OpenID Connect το σημαντικό token για την ταυτότητα του χρήστη είναι το ID Token.

Το ID Token περιέχει claims, δηλαδή πληροφορίες που περιγράφουν την ταυτότητα του χρήστη, όπως το όνομα ή το username.

Επομένως η σχέση είναι:

OpenID Connect
│
▼
Authentication
│
▼
ID Token
│
▼
ASP.NET Core
│
▼
ClaimsPrincipal
│
▼
HttpContext.User

Από την άλλη πλευρά, όταν η εφαρμογή χρειάζεται να αποκτήσει πρόσβαση σε ένα προστατευμένο API, τότε μπαίνει στο παιχνίδι το OAuth 2.0 authorization και χρησιμοποιείται ένα Access Token.

OAuth 2.0
│
▼
Authorization
│
▼
Access Token
│
▼
Protected API

Άρα δεν πρέπει να βλέπουμε το OpenID Connect ως ένα ακόμη framework που προσθέτουμε στην εφαρμογή. Είναι το πρωτόκολλο authentication που χρησιμοποιείται από το Microsoft identity platform για να επιβεβαιωθεί η ταυτότητα του χρήστη.

Στο ASP.NET Core, ο developer συνήθως δεν υλοποιεί χειροκίνητα το OpenID Connect. Η σύνδεση με το Entra ID γίνεται μέσω των authentication libraries και, για εφαρμογές ASP.NET Core, μπορεί να χρησιμοποιηθεί το Microsoft.Identity.Web, το οποίο αναλαμβάνει μεγάλο μέρος της απαιτούμενης integration.


Τι γίνεται μέσα στο ASP.NET Core;

Εδώ βρίσκεται το σημαντικό σημείο για έναν .NET developer.

Το authentication middleware επεξεργάζεται το αποτέλεσμα του authentication και δημιουργεί ένα:

ClaimsPrincipal
Enter fullscreen mode Exit fullscreen mode

Αυτό είναι που τελικά βλέπει η εφαρμογή μέσω:

HttpContext.User
Enter fullscreen mode Exit fullscreen mode

Για παράδειγμα:

User.Identity?.IsAuthenticated
Enter fullscreen mode Exit fullscreen mode

μπορεί να επιστρέψει:

true
Enter fullscreen mode Exit fullscreen mode

και μπορούμε να διαβάσουμε τα claims:

User.Claims
Enter fullscreen mode Exit fullscreen mode

Άρα η διαδικασία είναι:

Microsoft Entra ID
        ↓
      Token
        ↓
ASP.NET Core Authentication
        ↓
   ClaimsPrincipal
        ↓
   HttpContext.User
Enter fullscreen mode Exit fullscreen mode

Και τι κάνει το [Authorize];

Το [Authorize] δεν κάνει authentication από μόνο του. Λέει στο ASP.NET Core ότι το συγκεκριμένο endpoint απαιτεί authenticated user.

Για παράδειγμα:

[Authorize]
public IActionResult Dashboard()
{
    return View();
}
Enter fullscreen mode Exit fullscreen mode

Αν ο χρήστης είναι authenticated, μπορεί να συνεχίσει.

Αν δεν είναι authenticated, ενεργοποιείται η διαδικασία login.

Μπορούμε επίσης να έχουμε authorization με roles ή policies:

[Authorize(Roles = "Admin")]
public IActionResult DeleteUser()
{
    ...
}
Enter fullscreen mode Exit fullscreen mode

Εδώ πλέον δεν μας ενδιαφέρει μόνο αν ο χρήστης είναι authenticated. Θέλουμε να έχει και τον κατάλληλο ρόλο.


ID Token και Access Token

Εδώ υπάρχει μια πολύ σημαντική διάκριση.

Το ID Token χρησιμοποιείται κυρίως για να πληροφορήσει την εφαρμογή σχετικά με την ταυτότητα του χρήστη.

Το Access Token χρησιμοποιείται όταν μια εφαρμογή θέλει να καλέσει ένα προστατευμένο API.

Για παράδειγμα:

User
 ↓
Web Application
 ↓
Orders API
Enter fullscreen mode Exit fullscreen mode

Η Web Application μπορεί να χρειαστεί ένα Access Token για να καλέσει το Orders API.

Το API ελέγχει το token και αποφασίζει αν ο caller έχει την απαιτούμενη πρόσβαση.

Επομένως:

ID Token    → Ποιος είναι ο χρήστης;
Access Token → Τι επιτρέπεται να χρησιμοποιήσει;
Enter fullscreen mode Exit fullscreen mode

Πού βρίσκεται το Microsoft.Identity.Web;

Στο ASP.NET Core δεν χρειάζεται να υλοποιήσουμε μόνοι μας όλη αυτή τη διαδικασία.

Η Microsoft παρέχει το Microsoft.Identity.Web, το οποίο διευκολύνει την ενσωμάτωση του Microsoft Entra ID σε ASP.NET Core εφαρμογές.

Ενδεικτικά:

builder.Services
    .AddAuthentication()
    .AddMicrosoftIdentityWebApp(
        builder.Configuration.GetSection("AzureAd"));
Enter fullscreen mode Exit fullscreen mode

Η βιβλιοθήκη αναλαμβάνει μεγάλο μέρος της integration διαδικασίας με το Microsoft identity platform.

Σε ένα Web API χρησιμοποιούμε αντίστοιχα το κατάλληλο Microsoft Identity Web API integration.


Η συνολική εικόνα

Τελικά, η διαδικασία μπορεί να αποτυπωθεί πολύ απλά:

              Microsoft Entra ID
                     │
                     │ Login
                     ▼
                  User
                     │
                     │ Token
                     ▼
              ASP.NET Core
                     │
                     ▼
              Authentication
                     │
                     ▼
             ClaimsPrincipal
                     │
                     ▼
              Authorization
                     │
                     ▼
                Controller
Enter fullscreen mode Exit fullscreen mode

Το βασικό που πρέπει να καταλάβουμε είναι ότι το Entra ID αναλαμβάνει την ταυτοποίηση, ενώ η εφαρμογή μας χρησιμοποιεί την ταυτότητα που προκύπτει για να εφαρμόσει τους δικούς της κανόνες πρόσβασης.

Αυτός ο διαχωρισμός είναι ιδιαίτερα σημαντικός στις enterprise εφαρμογές. Η εφαρμογή δεν χρειάζεται να διαχειρίζεται passwords και authentication μηχανισμούς από την αρχή. Αντίθετα, βασίζεται σε έναν κεντρικό Identity Provider και επικεντρώνεται στο authorization και στους business κανόνες της.

Με αυτόν τον τρόπο το authentication γίνεται ένα ξεχωριστό κομμάτι της αρχιτεκτονικής και μπορεί να χρησιμοποιηθεί με συνέπεια σε πολλές εφαρμογές και APIs.

Top comments (0)