Zugriffskontrolle (SSO,JWT,SAML,XACML)
Einleitung
Zugriffskontrolle ( engl. access control ) soll die Authentizität (Wer ist das?) und Autorisierung (Darf der das?) von Nutzern bei Zugriff auf Ressourcen sicher stellen.
Single Sign On (SSO)
Durch die Proliferation von gemeinen Haushaltsgeräten mit integriertem Computer (umg. IoT-Geräte) ist die herkömmliche Zugriffskontrolle per Login- und Passwortabfrage unpraktisch. Das Ziel von Single Sign On soll dieses Problem lösen, indem Identitäten zentral verwaltet werden und diese genutzt werden kann um sich überall an- und abzumelden.
SSO Kernidee
Anders wie bei herkömmlichen Verbindung, bei der sich zwei verschiedene Domänen auf Grund der Same Origin Policy nicht eine Sitzung zu einem Nutzer teilen können, verwendet ein SSO-Kontext einen Identity Provider/SSO-Server über dem die Authentifizierung durchgeführt wird und dann die Sitzung mit den Service Providern teilt. Bei diesem Vorgang spricht man von Cross-Domain SSO. Somit hat der Nutzer das Gefühl, dass er sich bei nur einer Domäne authentifiziert hat und dann auf Ressourcen in der anderen Domäne zugreifen, ohne sich ein zweites Mal anmelden zu müssen.
Protokolle
SSO wird durch verschiedene Protokolle implementiert. Die weit verbreitesten sind SAML, OpenID, Auth0 und Facebook Connect. An all diese Protokolle werden folgende Anforderungen gestellt:
Erhöhte Sicherheit
Durch Verwendung von verschiedenen und starken Authentifizierungsverfahren, die Bereitstellung von Single Sign Off - die Beendingung der gesamten Sitzung mit nur einer einzigen Abmeldung – und Forced Renewal - erzwungene erneute Authentifizierung u.a. wenn der Nutzer sein Passwort wechselt - soll SSO sicher gemacht werden.
Integrationsmöglichkeiten von bestehenden Systemen
SSO Frameworks bieten verschiedene Adapter an um die verschiedenen Bausteine eines Systems zu einem SSO-Kontext zu integrieren. Zugang zu Nutzerdaten wie Login,Passwort, Zertifikate für die Authentifizierung und Rollenzuweisung erhält der SSO-Server über Connectors zu Datenbanken und Vereichnisdienste. Anwendungen können mit Hilfe von SSO-Agents mit dem SSO Server kommunizieren.
Robustheit und Administrierbarkeit
Durch die Abhängigkeit vieler verschiedener Anwendungen von einem SSO-Server muss dieser sehr robust und leicht zu administieren sein.
Vorteile und Nachteile
Vorteile
Dem Kerngedanken von Smart Homes und IoT entsprechend erspahrt SSO Nutzern viel Zeit und Aufwand, da er sich nicht auf den verschiedenen Anwendungen an-und wieder abmelden muss. Dem Nutzer reicht es sich ein Passwort zu merken, sodass dieses zu hoher Wahrscheinlichkeit komplexer und somit sicherer ist, als dass er sich viele verschiedene unsichere merkt. Auch eine einzige Übertragung von Passwort und Kenndaten bietet eine kleinere Angriffsfläche als mehrere. Der SSO Server ist verantwortlich für die Authentifizierung, sodass auch sichere Sitzungen mit IoT-Geräten möglich sind, die nicht genug Energie, Rechenkapazität oder Speicherplatz haben um komplexe Authentifizierungsalgorithmen durchführen zu können. Durch den Zusammenschluss mehrerer Domänen innerhalb eines SSO-Kontextes enfällt die fehleranfällige und zeitraubende Konfiguration mehrerer Kennungen an unterschiedlichen Datenbanken.
Nachteile
Der Zusammenschluss mehrerer Identitäten bringt auch ein erhöhtes Risiko mit sich. Diebstahl der SSO-Identität erlaubt den Täter Zugriff auf viele verschiedene Systeme und der SSO-Anbieter kann die Abfolge der besuchten Services unbefugt mitverfolgen und die Daten zweckentfremden. Außerdem ist die Verfügbarkeit der verschiedenen Services/Ressourcen nicht nur von der eigenen Verfügbarkeit abhängen sondern zusätzlich von der Zuverlässlichkeit des SSO-Systems.
SAML/XACML
Json Web Token (JWT)
JSON Web Token sind ein kompaktes, URL-kodierbares Nachrichtenformat, welches zum Ziel hat "Claims" zu sicher zu übertragen. "Sicher" bedeutet hier, dass entweder nur die Integrität als auch die Integrität und Vertraulichkeit geschützt werden kann. Hauptsächlich liegt der Augenmerk laut homepage jedoch auch der Integrität.
Ein JWT besteht aus drei Teilen: BASE64URL kodierten Header, getrennt mit Punkt vom BASE64URL kodierten Payload und der BASE64URL kodierten Signatur. Diese Signatur besteht aus der konkatentation von Header und Payload.
Beispiel JWT
Header mit Signatur- oder Verschlüsselungsalgorithmus (hier HMAC SHA256) und dem Typ des Tokens (hier JWT)
{ "alg": "HS256", "typ": "JWT" }
Payload besteht hier aus Subject, Name und Issued At Zeitstempel:
{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }
Signatur besteht aus:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), Passw0rt1234 )
Dies generiert das Token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ. WetwNp0BkAboJQMpyRPNJ2MiVw5Af-Iyt3mU1DX_GiY
Minimum Working Example
In einem minimum working example soll das Zusammenspiel der im Artikel besprochenen Elemente vergegenwärtigt werden. Die Architektur basiert auf der vorgestellten SAML-XACML Architektur, wobei nur der Policy Decicision Point, die Policy Enforcement Points und der Identity Provider implementiert werden. Zusätzlich wurden der SAML Prozess durch einen JWT-basierten Tokenaustausch ersetzt. Der Messageaustausch geschieht durch HTTP REST.
Setup
1. Code laden von github
2. Requirements laut Readme.md installieren
Beispielablauf eines Servicerequests
JWT holen
POST gegen den Registrierungsendpunkt oder Loginendpunkt des IDP:
POST /login HTTP/1.1 Host: 127.0.0.1:3000 Content-Type: application/x-www-form-urlencoded Cache-Control: no-cache username=stepo&password=stepo
Antwort mit Json Web Token im Payload:
HTTP/1.1 200 status: 200 content-type: application/json content-length: 610 {"message": "Logged in as stepo", "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MzcwOTcxNTYsIm5iZiI6MTUzNzA5NzE1NiwianRpIjoi NGI1ZjY2M2ItNTRkMi00NzY2LTkxOWUtNThlZjdhZGUxZDljIiwiZXhwIjoxNTM3MDk4MDU2LCJpZGVudGl0eSI6InN0ZX BvIiwiZnJlc2giOmZhbHNlLCJ0eXBlIjoiYWNjZXNzIn0.QCtGHX4odS5togFgnJnPlNWfum5SWJkud2yXwA_xnE4", "refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MzcwOTcxNTYsIm5iZiI6MTUzNz A5NzE1NiwianRpIjoiNGYwODgwOTEtOThjMi00MWVhLWFmZmUtN2U1N2JlYTY5MjU2IiwiZXhwIjoxNTM5Njg5MTU2LCJp ZGVudGl0eSI6InN0ZXBvIiwidHlwZSI6InJlZnJlc2gifQ.H9SqGRcY5RKla23jcp_lNUUflsfepHCfbkPaahGxTSU"}
Service Anfragen mit JWT
POST gegen Serviceendpunkt:
POST /protected_toaster HTTP/1.1 Host: 127.0.0.1:4000 Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MzcwOTY2NjksIm5iZiI6MTU zNzA5NjY2OSwianRpIjoiZmZhNDlmZGMtMTJhNC00OTk1LTk5NjctMmVkOTc2NDUyNzM3IiwiZXhwIjoxNTM3MDk3NTY5L CJpZGVudGl0eSI6InN0ZXBvIiwiZnJlc2giOmZhbHNlLCJ0eXBlIjoiYWNjZXNzIn0.egBiDeU2IC4hb7hBoUVGkAbo-c4 _UYCrisAJreLVIuM Cache-Control: no-cache
Serviceendpunkt schickt POST gegen Policy Decision Point für eine Autorisierung:
POST /services/pdp HTTP/1.1 Host: localhost:10000 Content-Type: application/xacml+json Cache-Control: no-cache {"Request":{"ReturnPolicyIdList":false,"CombinedDecision":false,"Category":[ {"CategoryId":"urn:oasis:names:tc:xacml:1.0:subject-category:access-subject","Attribute":[{"IncludeInResult":false,"AttributeId":"urn:oasis:names:tc:xacml:1.0:subject:subject-id","DataType":"http://www.w3.org /2001/XMLSchema#string","Value":[ "stepo" ]}]} ,{"CategoryId":"urn:oasis:names:tc:xacml:3.0:attribute-category:resource","Attribute":[{"IncludeInResult":false,"AttributeId":"urn:oasis:names:tc:xacml:1.0:resource:resource-id","DataType":"http://www.w3.org /2001/XMLSchema#anyURI","Value":[ "protected_toaster" ]}]} ,{"CategoryId":"urn:oasis:names:tc:xacml:3.0:attribute-category:action","Attribute":[{"IncludeInResult":false,"AttributeId":"urn:oasis:names:tc:xacml:1.0:action:action-id","DataType":"http://www.w3.org /2001/XMLSchema#string","Value":[ "post" ]}]} ,{"CategoryId":"urn:oasis:names:tc:xacml:3.0:attribute-category:environment","Attribute":[]} ]}}
Der Policy Decision Point überprüft seine Datenbank nach der XACML Regel für diesen User und Endpunkt:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <Policy xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" PolicyId="urn:oasis:names:tc:xacml:2.0:conformance-test:IIA1:policy" RuleCombiningAlgId="urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:deny-overrides" Version="1.0"> <Description> Policy for Conformance Test IIA001. </Description> <Target/> <Rule Effect="Permit" RuleId="urn:oasis:names:tc:xacml:2.0:conformance-test:IIA1:rule"> <Description> stepo can post to green and red resource </Description> <Target> <AnyOf> <AllOf> <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal"> <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">stepo</AttributeValue> <AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id" Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false"/> </Match> </AllOf> </AnyOf> <AnyOf> <AllOf> <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:anyURI-equal"> <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#anyURI">protected_toaster</AttributeValue> <AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" DataType="http://www.w3.org/2001/XMLSchema#anyURI" MustBePresent="false"/> </Match> </AllOf> <AllOf> <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:anyURI-equal"> <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#anyURI">protected_tv</AttributeValue> <AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" DataType="http://www.w3.org/2001/XMLSchema#anyURI" MustBePresent="false"/> </Match> </AllOf> </AnyOf> <AnyOf> <AllOf> <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal"> <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">post</AttributeValue> <AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false"/> </Match> </AllOf> </AnyOf> </Target> </Rule> </Policy>
Da die Anfrage eine Regel findet wird autorisiert mit:
HTTP/1.1 200 status: 200 date: Sun, 16 Sep 2018 11:38:31 GMT content-type: application/json transfer-encoding: chunked {"Response":[{"Decision":"Permit"}]}
Der Serviceendpunkt antwortet an den Konsumenten final:
HTTP/1.1 200 status: 200 content-type: application/json content-length: 23 {"message": "success"}