OpenID Connect: εξουσιοδότηση εσωτερικών εφαρμογών από προσαρμοσμένη σε τυπική

Πριν από λίγους μήνες, εφάρμοζα έναν διακομιστή OpenID Connect για τη διαχείριση της πρόσβασης για εκατοντάδες εσωτερικές εφαρμογές μας. Από τις δικές μας εξελίξεις, βολικές σε μικρότερη κλίμακα, περάσαμε σε ένα γενικά αποδεκτό πρότυπο. Η πρόσβαση μέσω της κεντρικής υπηρεσίας απλοποιεί σε μεγάλο βαθμό τις μονότονες λειτουργίες, μειώνει το κόστος εφαρμογής των εξουσιοδοτήσεων, σας επιτρέπει να βρείτε πολλές έτοιμες λύσεις και να μην ταράζετε το μυαλό σας όταν αναπτύσσετε νέες. Σε αυτό το άρθρο, θα μιλήσω για αυτή τη μετάβαση και τα χτυπήματα που καταφέραμε να καλύψουμε.

OpenID Connect: εξουσιοδότηση εσωτερικών εφαρμογών από προσαρμοσμένη σε τυπική

Πριν από πολύ καιρό... Πώς ξεκίνησαν όλα

Πριν από μερικά χρόνια, όταν υπήρχαν πάρα πολλές εσωτερικές εφαρμογές για χειροκίνητο έλεγχο, γράψαμε μια εφαρμογή για τον έλεγχο της πρόσβασης εντός της εταιρείας. Ήταν μια απλή εφαρμογή Rails που συνδέθηκε με μια βάση δεδομένων με πληροφορίες για τους υπαλλήλους, όπου είχε ρυθμιστεί η πρόσβαση σε διάφορες λειτουργίες. Ταυτόχρονα, αυξήσαμε το πρώτο SSO, το οποίο βασίστηκε στην επαλήθευση των διακριτικών από την πλευρά του πελάτη και του διακομιστή εξουσιοδότησης, το διακριτικό μεταδόθηκε σε κρυπτογραφημένη μορφή με πολλές παραμέτρους και επαληθεύτηκε στον διακομιστή εξουσιοδότησης. Αυτή δεν ήταν η πιο βολική επιλογή, καθώς κάθε εσωτερική εφαρμογή έπρεπε να περιγράψει ένα σημαντικό επίπεδο λογικής και οι βάσεις δεδομένων των εργαζομένων ήταν πλήρως συγχρονισμένες με τον διακομιστή εξουσιοδότησης.

Μετά από κάποιο χρονικό διάστημα, αποφασίσαμε να απλοποιήσουμε το έργο της κεντρικής εξουσιοδότησης. Το SSO μεταφέρθηκε στον εξισορροπητή. Με τη βοήθεια του OpenResty, προστέθηκε ένα πρότυπο στο Lua που έλεγχε τα token, ήξερε σε ποια εφαρμογή θα πήγαινε το αίτημα και μπορούσε να ελέγξει αν υπήρχε πρόσβαση εκεί. Αυτή η προσέγγιση απλοποίησε πολύ το έργο του ελέγχου της πρόσβασης σε εσωτερικές εφαρμογές - στον κώδικα κάθε εφαρμογής, δεν ήταν πλέον απαραίτητο να περιγραφεί πρόσθετη λογική. Ως αποτέλεσμα, κλείσαμε την κίνηση εξωτερικά και η ίδια η εφαρμογή δεν γνώριζε τίποτα σχετικά με την εξουσιοδότηση.

Ωστόσο, ένα πρόβλημα παρέμενε άλυτο. Τι γίνεται με τις εφαρμογές που χρειάζονται πληροφορίες για τους εργαζόμενους; Ήταν δυνατό να γραφτεί ένα API για την υπηρεσία εξουσιοδότησης, αλλά στη συνέχεια θα έπρεπε να προσθέσετε επιπλέον λογική για κάθε τέτοια εφαρμογή. Επιπλέον, θέλαμε να απαλλαγούμε από την εξάρτηση από μια από τις αυτογραμμένες εφαρμογές μας, η οποία αργότερα θα μεταφραζόταν σε OpenSource, στον εσωτερικό μας διακομιστή εξουσιοδότησης. Θα το συζητήσουμε κάποια άλλη στιγμή. Η λύση και στα δύο προβλήματα ήταν ο ΟΑΥΘ.

σε κοινά πρότυπα

Το OAuth είναι ένα κατανοητό, γενικά αποδεκτό πρότυπο εξουσιοδότησης, αλλά επειδή μόνο η λειτουργικότητά του δεν είναι αρκετή, άρχισαν αμέσως να εξετάζουν το OpenID Connect (OIDC). Το ίδιο το OIDC είναι η τρίτη εφαρμογή του ανοιχτού προτύπου ελέγχου ταυτότητας, το οποίο έχει εισχωρήσει σε ένα πρόσθετο μέσω του πρωτοκόλλου OAuth 2.0 (ένα πρωτόκολλο ανοιχτής εξουσιοδότησης). Αυτή η λύση κλείνει το πρόβλημα της έλλειψης δεδομένων σχετικά με τον τελικό χρήστη και καθιστά επίσης δυνατή την αλλαγή του παρόχου εξουσιοδότησης.

Ωστόσο, δεν επιλέξαμε συγκεκριμένο πάροχο και αποφασίσαμε να προσθέσουμε ενοποίηση με το OIDC για τον υπάρχοντα διακομιστή εξουσιοδότησης. Υπέρ αυτής της απόφασης ήταν το γεγονός ότι η OIDC είναι πολύ ευέλικτη όσον αφορά την εξουσιοδότηση τελικού χρήστη. Έτσι, ήταν δυνατή η εφαρμογή υποστήριξης OIDC στον τρέχοντα διακομιστή εξουσιοδότησης.

OpenID Connect: εξουσιοδότηση εσωτερικών εφαρμογών από προσαρμοσμένη σε τυπική

Ο τρόπος μας να υλοποιούμε τον δικό μας διακομιστή OIDC

1) Έφερε τα δεδομένα στην επιθυμητή φόρμα

Για την ενσωμάτωση του OIDC, είναι απαραίτητο να φέρετε τα τρέχοντα δεδομένα χρήστη σε μορφή κατανοητή από το πρότυπο. Στο OIDC αυτό ονομάζεται Αξιώσεις. Οι αξιώσεις είναι ουσιαστικά τελικά πεδία στη βάση δεδομένων των χρηστών (όνομα, email, τηλέφωνο κ.λπ.). Υπάρχει τυπική λίστα γραμματοσήμων, και οτιδήποτε δεν περιλαμβάνεται σε αυτήν τη λίστα θεωρείται προσαρμοσμένο. Επομένως, το πρώτο σημείο που πρέπει να προσέξετε εάν θέλετε να επιλέξετε έναν υπάρχοντα πάροχο OIDC είναι η δυνατότητα εύκολης προσαρμογής νέων εμπορικών σημάτων.

Η ομάδα των χαρακτηριστικών συνδυάζεται στο ακόλουθο υποσύνολο - Πεδίο εφαρμογής. Κατά τη διάρκεια της εξουσιοδότησης, ζητείται πρόσβαση όχι σε συγκεκριμένες μάρκες, αλλά σε πεδία, ακόμη και αν ορισμένες από τις επωνυμίες από το πεδίο εφαρμογής δεν χρειάζονται.

2) Υλοποίησε τις απαραίτητες επιχορηγήσεις

Το επόμενο μέρος της ολοκλήρωσης του OIDC είναι η επιλογή και η εφαρμογή των τύπων αδειοδότησης, οι λεγόμενες επιχορηγήσεις. Το περαιτέρω σενάριο αλληλεπίδρασης μεταξύ της επιλεγμένης εφαρμογής και του διακομιστή εξουσιοδότησης θα εξαρτηθεί από την επιλεγμένη επιχορήγηση. Ένα υποδειγματικό σχέδιο για την επιλογή της σωστής επιχορήγησης φαίνεται στο παρακάτω σχήμα.

OpenID Connect: εξουσιοδότηση εσωτερικών εφαρμογών από προσαρμοσμένη σε τυπική

Για την πρώτη μας αίτηση, χρησιμοποιήσαμε την πιο κοινή επιχορήγηση, τον Κωδικό Εξουσιοδότησης. Η διαφορά του από άλλα είναι ότι είναι τριβήμα, δηλ. υποβάλλεται σε πρόσθετες δοκιμές. Πρώτα, ο χρήστης κάνει ένα αίτημα για άδεια εξουσιοδότησης, λαμβάνει ένα διακριτικό - Κωδικός εξουσιοδότησης, στη συνέχεια με αυτό το διακριτικό, σαν με ένα εισιτήριο για ταξίδι, ζητά ένα διακριτικό πρόσβασης. Όλη η κύρια αλληλεπίδραση αυτού του σεναρίου εξουσιοδότησης βασίζεται σε ανακατευθύνσεις μεταξύ της εφαρμογής και του διακομιστή εξουσιοδότησης. Μπορείτε να διαβάσετε περισσότερα για αυτήν την επιχορήγηση εδώ.

Το OAuth τηρεί την ιδέα ότι τα διακριτικά πρόσβασης που λαμβάνονται μετά την εξουσιοδότηση πρέπει να είναι προσωρινά και να αλλάζουν, κατά προτίμηση κάθε 10 λεπτά κατά μέσο όρο. Η χορήγηση του Κωδικού Εξουσιοδότησης είναι μια επαλήθευση τριών βημάτων μέσω ανακατευθύνσεων, κάθε 10 λεπτά για να κάνετε ένα τέτοιο βήμα, ειλικρινά, δεν είναι η πιο ευχάριστη εργασία για τα μάτια. Για την επίλυση αυτού του προβλήματος, υπάρχει μια άλλη επιχορήγηση - το Refresh Token, το οποίο χρησιμοποιήσαμε και στη χώρα μας. Όλα είναι πιο εύκολα εδώ. Κατά την επαλήθευση από άλλη επιχορήγηση, εκτός από το κύριο διακριτικό πρόσβασης, εκδίδεται ένα άλλο - Ανανέωση Token, το οποίο μπορεί να χρησιμοποιηθεί μόνο μία φορά και η διάρκεια ζωής του είναι συνήθως πολύ μεγαλύτερη. Με αυτό το διακριτικό ανανέωσης, όταν τελειώσει το TTL (Time to Live) του κύριου διακριτικού πρόσβασης, το αίτημα για νέο διακριτικό πρόσβασης θα φτάσει στο τελικό σημείο μιας άλλης επιχορήγησης. Το χρησιμοποιημένο Refresh Token μηδενίζεται αμέσως. Αυτός ο έλεγχος είναι δύο βημάτων και μπορεί να εκτελεστεί στο παρασκήνιο, ανεπαίσθητα από τον χρήστη.

3) Ρυθμίστε προσαρμοσμένες μορφές εξόδου δεδομένων

Μετά την υλοποίηση των επιλεγμένων επιχορηγήσεων, τις εργασίες εξουσιοδότησης, αξίζει να αναφερθεί η λήψη δεδομένων για τον τελικό χρήστη. Το OIDC έχει ένα ξεχωριστό τελικό σημείο για αυτό, όπου μπορείτε να ζητήσετε δεδομένα χρήστη με το τρέχον διακριτικό πρόσβασης και εάν είναι ενημερωμένα. Και αν τα δεδομένα του χρήστη δεν αλλάζουν τόσο συχνά και πρέπει να ακολουθήσετε τα τρέχοντα πολλές φορές, μπορείτε να καταλήξετε σε μια τέτοια λύση όπως τα διακριτικά JWT. Αυτά τα διακριτικά υποστηρίζονται επίσης από το πρότυπο. Το ίδιο το διακριτικό JWT αποτελείται από τρία μέρη: κεφαλίδα (πληροφορίες για το διακριτικό), ωφέλιμο φορτίο (οποιαδήποτε απαραίτητα δεδομένα) και υπογραφή (υπογραφή, το διακριτικό υπογράφεται από τον διακομιστή και μπορείτε αργότερα να ελέγξετε την πηγή της υπογραφής του).

Στην υλοποίηση του OIDC, το διακριτικό JWT ονομάζεται id_token. Μπορεί να ζητηθεί μαζί με ένα κανονικό διακριτικό πρόσβασης και το μόνο που απομένει είναι να επαληθεύσετε την υπογραφή. Ο διακομιστής εξουσιοδότησης έχει ένα ξεχωριστό τελικό σημείο για αυτό με μια δέσμη δημόσιων κλειδιών στη μορφή J.W.K.. Και μιλώντας για αυτό, αξίζει να αναφέρουμε ότι υπάρχει ένα άλλο τελικό σημείο, το οποίο, με βάση το πρότυπο RFC5785 αντικατοπτρίζει την τρέχουσα διαμόρφωση του διακομιστή OIDC. Περιέχει όλες τις διευθύνσεις τελικού σημείου (συμπεριλαμβανομένης της διεύθυνσης του δημόσιου δακτυλίου κλειδιού που χρησιμοποιείται για την υπογραφή), υποστηριζόμενες επωνυμίες και πεδία, χρησιμοποιημένους αλγόριθμους κρυπτογράφησης, υποστηριζόμενες επιχορηγήσεις κ.λπ.

Για παράδειγμα στο Google:

{
 "issuer": "https://accounts.google.com",
 "authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth",
 "device_authorization_endpoint": "https://oauth2.googleapis.com/device/code",
 "token_endpoint": "https://oauth2.googleapis.com/token",
 "userinfo_endpoint": "https://openidconnect.googleapis.com/v1/userinfo",
 "revocation_endpoint": "https://oauth2.googleapis.com/revoke",
 "jwks_uri": "https://www.googleapis.com/oauth2/v3/certs",
 "response_types_supported": [
  "code",
  "token",
  "id_token",
  "code token",
  "code id_token",
  "token id_token",
  "code token id_token",
  "none"
 ],
 "subject_types_supported": [
  "public"
 ],
 "id_token_signing_alg_values_supported": [
  "RS256"
 ],
 "scopes_supported": [
  "openid",
  "email",
  "profile"
 ],
 "token_endpoint_auth_methods_supported": [
  "client_secret_post",
  "client_secret_basic"
 ],
 "claims_supported": [
  "aud",
  "email",
  "email_verified",
  "exp",
  "family_name",
  "given_name",
  "iat",
  "iss",
  "locale",
  "name",
  "picture",
  "sub"
 ],
 "code_challenge_methods_supported": [
  "plain",
  "S256"
 ],
 "grant_types_supported": [
  "authorization_code",
  "refresh_token",
  "urn:ietf:params:oauth:grant-type:device_code",
  "urn:ietf:params:oauth:grant-type:jwt-bearer"
 ]
}

Έτσι, χρησιμοποιώντας το id_token, μπορείτε να μεταφέρετε όλα τα απαραίτητα χαρακτηριστικά στο ωφέλιμο φορτίο του διακριτικού και να μην επικοινωνείτε με τον διακομιστή εξουσιοδότησης κάθε φορά για να ζητήσετε δεδομένα χρήστη. Το μειονέκτημα αυτής της προσέγγισης είναι ότι η αλλαγή στα δεδομένα χρήστη από τον διακομιστή δεν έρχεται αμέσως, αλλά μαζί με ένα νέο διακριτικό πρόσβασης.

Αποτελέσματα υλοποίησης

Έτσι, αφού εφαρμόσαμε τον δικό μας διακομιστή OIDC και διαμορφώσαμε τις συνδέσεις σε αυτόν από την πλευρά της εφαρμογής, λύσαμε το πρόβλημα της μεταφοράς πληροφοριών σχετικά με τους χρήστες.
Δεδομένου ότι το OIDC είναι ένα ανοιχτό πρότυπο, έχουμε την επιλογή να επιλέξουμε έναν υπάρχοντα πάροχο ή εφαρμογή διακομιστή. Δοκιμάσαμε το Keycloak, το οποίο αποδείχθηκε πολύ βολικό στη διαμόρφωση, μετά τη ρύθμιση και την αλλαγή των διαμορφώσεων σύνδεσης στην πλευρά της εφαρμογής, είναι έτοιμο για χρήση. Από την πλευρά της εφαρμογής, το μόνο που μένει είναι να αλλάξετε τις διαμορφώσεις σύνδεσης.

Μιλώντας για υπάρχουσες λύσεις

Μέσα στον οργανισμό μας, ως ο πρώτος διακομιστής OIDC, συγκεντρώσαμε τη δική μας υλοποίηση, η οποία συμπληρώθηκε όπως ήταν απαραίτητο. Μετά από μια λεπτομερή ανασκόπηση άλλων έτοιμων λύσεων, μπορούμε να πούμε ότι αυτό είναι ένα αμφιλεγόμενο θέμα. Υπέρ της απόφασης να εφαρμόσουν τον δικό τους διακομιστή, υπήρχαν ανησυχίες από την πλευρά των παρόχων για την απουσία της απαραίτητης λειτουργικότητας, καθώς και την παρουσία ενός παλιού συστήματος στο οποίο υπήρχαν διαφορετικές προσαρμοσμένες εξουσιοδοτήσεις για ορισμένες υπηρεσίες και αρκετά δεδομένων σχετικά με τους υπαλλήλους ήταν ήδη αποθηκευμένα. Ωστόσο, σε έτοιμες υλοποιήσεις, υπάρχουν ευκολίες για ενσωμάτωση. Για παράδειγμα, το Keycloak έχει το δικό του σύστημα διαχείρισης χρηστών και τα δεδομένα αποθηκεύονται απευθείας σε αυτό και δεν θα είναι δύσκολο να προσπεράσετε τους χρήστες σας εκεί. Για να γίνει αυτό, το Keycloak διαθέτει ένα API που θα σας επιτρέψει να πραγματοποιήσετε πλήρως όλες τις απαραίτητες ενέργειες μεταφοράς.

Ένα άλλο παράδειγμα πιστοποιημένης, ενδιαφέρουσας, κατά τη γνώμη μου, υλοποίησης είναι το Ory Hydra. Είναι ενδιαφέρον γιατί αποτελείται από διαφορετικά στοιχεία. Για την ενσωμάτωση, θα χρειαστεί να συνδέσετε την υπηρεσία διαχείρισης χρηστών με την υπηρεσία εξουσιοδότησης και να την επεκτείνετε όπως απαιτείται.

Το Keycloak και το Ory Hydra δεν είναι οι μόνες λύσεις εκτός ραφιού. Είναι καλύτερο να επιλέξετε μια υλοποίηση πιστοποιημένη από το OpenID Foundation. Αυτές οι λύσεις έχουν συνήθως ένα σήμα πιστοποίησης OpenID.

OpenID Connect: εξουσιοδότηση εσωτερικών εφαρμογών από προσαρμοσμένη σε τυπική

Επίσης, μην ξεχνάτε τους υπάρχοντες παρόχους επί πληρωμή, εάν δεν θέλετε να διατηρήσετε τον διακομιστή OIDC. Σήμερα υπάρχουν πολλές καλές επιλογές.

Ποιο είναι το επόμενο

Στο εγγύς μέλλον, πρόκειται να κλείσουμε την κυκλοφορία στις εσωτερικές υπηρεσίες με διαφορετικό τρόπο. Σκοπεύουμε να μεταφέρουμε το τρέχον SSO μας στον εξισορροπητή χρησιμοποιώντας το OpenResty σε έναν διακομιστή μεσολάβησης που βασίζεται στο OAuth. Υπάρχουν ήδη πολλές έτοιμες λύσεις εδώ, για παράδειγμα:
github.com/bitly/oauth2_proxy
github.com/ory/oathkeeper
github.com/keycloak/keycloak-gatekeeper

Πρόσθετα υλικά

jwt.io – καλή υπηρεσία για την επικύρωση των κουπονιών JWT
openid.net/developers/certified - κατάλογος πιστοποιημένων εφαρμογών OIDC

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο