Nutzungsvorgaben Security
Java Bibliothek / IT-System
Name | Art | Version |
---|---|---|
|
Bibliothek |
v3.0.2 |
1. Einleitung
Dieses Dokument beschreibt, wie der Baustein Security und die von ihm bereitgestellte Bibliothek isy-security verwendet werden, um die Autorisierung innerhalb von IT-Systemen umzusetzen. Es richtet sich an Entwickler, die ein IT-System gemäß den Vorgaben der IsyFact mit der Fähigkeit zur Autorisierung ausstatten müssen und beschreibt, wie und in welchen Teilen einer Anwendung die Autorisierung umzusetzen ist. Der Baustein Security ist OAuth2.0 konform und greift hauptsächlich auf die Möglichkeiten von Spring Security zurück.
Die folgenden Kapitel leiten durch die Funktionen des Bausteins isy-security
.
Schließlich beschreibt das letzte Kapitel Testunterstützung, welche Hilfen der Baustein isy-security zum Erstellen von (automatisierten) Tests bereitstellt.
Die konzeptionellen Aspekte der Authentifizierung und Autorisierung werden im Security - Konzept beschrieben.
2. Software-Architektur des Security Bausteins
Die Software-Architektur des Security-Bausteins bildet das Fundament für die Sicherheit von Anwendungen in modernen Softwarelösungen. Die korrekte Gestaltung und Implementierung dieser Architektur ist entscheidend, um Schutzmechanismen gegen potenzielle Sicherheitsbedrohungen zu etablieren. In diesem Kapitel wird detailliert auf die verschiedenen Aspekte der Software-Architektur des Security-Bausteins eingegangen und bewährte Methoden sowie bewährte Praktiken vorgestellt, um eine robuste und zuverlässige Sicherheitsinfrastruktur zu schaffen.
Im Folgenden werden die Interfaces des Bausteins Security genauer erläutert.
2.1. Security
Das Interface Security
stellt die zentrale Schnittstelle bereit, über die auf den Baustein zugegriffen wird.
Es empfiehlt sich, die Beans direkt zu 'autowiren' und das Interface hauptsächlich für eine Migration vom alten Sicherheitsbaustein isy-sicherheit auf den neuen Baustein isy-security zu verwenden.
|
Die folgenden Methoden bieten Zugriff auf eine Liste von allen im System hinterlegten Rollen, den Berechtigungsmanager und den optionalen Authentifizierungsmanager:
Set<String> getAlleRollen()
-
Liefert die Menge aller im System konfigurierten Rollen.
Berechtigungsmanager getBerechtigungsManager()
-
Stellt eine Referenz auf das
Berechtigungsmanager
Bean bereit. Optional<Authentifizierungsmanager> getAuthentifizierungsManager()
-
Liefert ein
Optional
, das eine Referenz auf denAuthentifizierungsmanager
enthält, odernull
falls die Anwendung als Resource-Server agiert und keinAuthentifizierungsmanager
benötigt wird.
2.2. Authentifizierungsmanager
Zur Authentifizierung von OAuth 2.0 Clients stehen folgende Methoden zur Verfügung:
void authentifiziere(String oauth2ClientRegistrationId)
-
Authentifiziert einen OAuth 2.0 Client anhand seiner Client-Registration-ID. Unterstützt den
client_credentials
(Client Credentials Flow) undpassword
(Resource Owner Password Credentials Flow) GrantType. Zusätzliche Authentifizierungsmerkmale werden aus den IsyFact spezifischen Konfigurationsparametern mit der entsprechenden Client-Registration-ID abgefragt:-
bhknz
: Das BHKNZ kann als optionaler Parameter übergeben werden. Wird aktuell nur für den Resource Owner-Password Credentials Flow ausgewertet. -
username
undpassword
: Die Zugangsdaten des technischen Nutzers (Resource Owner), welche für den Resource Owner Password Credentials Flow erforderlich sind.
-
void authentifiziereClient(String issuerLocation, String clientId, String clientSecret)
void authentifiziereClient(String issuerLocation, String clientId, String clientSecret, String bhknz)
-
Authentifiziert einen OAuth 2.0 Client gegen die angegebene
issuerLocation
anhand seinerclientId
undclientSecret
. Dasbhknz
kann als optionaler Parameter übergeben werden, wird aber für die Client-Authentifizierung noch nicht ausgewertet. void authentifiziereSystem(String issuerLocation, String clientId, String clientSecret, String username, String password)
void authentifiziereSystem(String issuerLocation, String clientId, String clientSecret, String username, String password, String bhknz)
-
Authentifiziert einen technischen Nutzer (Resource Owner) gegen die angegebene
issuerLocation
anhand derclientId
undclientSecret
des zu verwendenden OAuth 2.0 Clients und demusername
undpassword
des Resource Owners. Dasbhknz
kann als optionaler Parameter übergeben werden und wird in den konfigurierten Header zur Zwei-Faktor-Authentifizierung gesetzt.
2.3. Berechtigungsmanager
Berechtigungsprüfungen können ebenso an beliebiger Stelle im Quellcode erfolgen.
Dazu stellt der Baustein isy-security
über die Schnittstelle Berechtigungsmanager entsprechende Funktionen bereit.
Der Berechtigungsmanager ist ein Container für die Rechte und Rollen des aktuell authentifizierten Anwenders.
Zur Formulierung von Berechtigungsprüfungen stehen folgende Methoden des Berechtigungsmanagers zur Verfügung:
Set<String> getRollen()
-
Liefert die Menge aller Rollen des Anwenders.
Set<String> getRechte()
-
Liefert die Menge aller Rechte des Anwenders.
boolean hatRecht(String recht)
-
Ermittelt, ob der Anwender ein bestimmtes Recht besitzt.
void pruefeRecht(String recht)
-
Prüft, ob der Anwender das angegebene Recht besitzt und erzeugt einen Fehler vom Typ
AccessDeniedException
, wenn das nicht der Fall ist. Object getTokenAttribute(String key)
-
Fragt einen Wert im Access Token des Security Contexts ab.
Primär sollte die Berechtigungsprüfung über die Spring Annotation @Secured und nicht über die hier erwähnte Methode pruefeRecht(String recht) erfolgen.
|
3. Aufrufen von Nachbarsystemen
Der Aufruf von Nachbarsystemen erfolgt auf Basis des reaktiven Spring WebClient
.
Um Nachbarsysteme aufzurufen, die auf Basis von OAuth 2.0
abgesichert sind, ist grundlegend die Authentifizierung bei einem IAM-Service
mit gültiger client_id
, client_secret
sowie grant_type
erforderlich.
Dieser liefert ein Bearer-Token zurück, in dem die Rollen und somit die Zugriffsmöglichkeiten der aufrufenden Anwendung definiert sind.
3.1. Maven Dependencies
Für die Authentifizierung mit einem OAuth 2.0
-Client sind die folgenden Abhängigkeiten erforderlich:
<dependency>
<groupId>de.bund.bva.isyfact</groupId>
<artifactId>isy-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
3.2. Konfigurationsparameter
Konfigurationsparameter sind essenziell, um Bausteine in technischen Anwendungen anzupassen und zu steuern. Sie bieten die Möglichkeit, die Funktionalität und das Verhalten eines Bausteins entsprechend spezifischer Anforderungen anzupassen. In diesem Kapitel werden alle möglichen Optionen der Konfigurationsparameter vorgestellt, um einen umfassenden Überblick über deren Anwendungsmöglichkeiten zu geben.
3.2.1. Spring OAuth2 Client Konfigurationsparameter
Für die korrekte Anbindung an den IAM-Service
ist die Angabe einiger Konfigurationsparameter notwendig, welche in der Konfigurationsdatei der Anwendung eingetragen werden müssen.
Das Präfix sämtlicher Konfigurationsparameter spring.security.oauth2
wird zur Vereinfachung in der folgenden Liste weggelassen.
Parameter | Wertebereich | Beschreibung |
---|---|---|
|
|
Identifier der Client-Applikation im Autorisierungsserver. |
|
|
Secret, das nur der Anwendung und dem Autorisierungsserver bekannt ist. |
|
|
Methode, durch welche die Anwendung ein Bearer-Token erhält. Abhängig von dem zu verwendenden Flow auf |
|
|
(Optional) ID des zu verwendenden Client-Providers, falls diese nicht mit der Registration-ID übereinstimmt. |
|
|
Der OpenID Connect Issuer Identifier für die Konfiguration des Clients über den Discovery Endpoint, beispielsweise in der Form |
3.2.2. Isyfact spezifische Konfigurationsparameter
Zugangsdaten für technische Nutzer zur Authentifizierung von Tasks und Batches mit dem Resource-Owner-Password-Credential Flow können über die folgenden Parameter konfiguriert werden:
Parameter | Wertebereich | Default | Beschreibung |
---|---|---|---|
|
|
|
Benutzername für Grant-Type |
|
|
|
Benutzerpassword für Grant-Type |
|
|
|
Behördenkennzeichen für Grant-Type |
|
|
|
Konfigurierbarer Headername für Zwei-Faktor-Authentifizierung. |
|
|
|
Organisational Unit, die in Verbindung mit bhknz verwendet wird, um den Wert für bhknz-header-name zu bilden. (Muss gesetzt werden, wenn eine |
3.3. Tokenweitergabe an Nachbarsysteme
Für authentifizierte Anwendungen besteht die Möglichkeit der Tokenweitergabe an Nachbarsysteme durch Erweiterung des WebClient
um die ServletBearerExchangeFilterFunction
.
Diese liest die aktuelle Authentifizierung aus dem SecurityContext und fügt ausgehenden Requests das dort befindliche OAuth 2.0 Token dem Authorization Header hinzu.
@Configuration
public class ExampleWebClientConfiguration {
@Bean
WebClient webClient() {
ServletBearerExchangeFilterFunction bearer = new ServletBearerExchangeFilterFunction();
return WebClient.builder()
.filter(bearer).build();
}
}
3.4. Tokenweitergabe bei generierten Clients
Der von Open API Tools generierte ApiClient
erlaubt die Initialisierung mit einem Spring WebClient
im Konstruktor. Demzufolge kann die oben beschriebene Konfiguration zur Tokenweitergabe analog angewendet werden. Für das folgende Code-Beispiel wird somit unterstellt, dass ein WebClient
vorliegt, der die ServletBearerExchangeFunction
beinhaltet:
public class ExampleClass {
// ...
ApiClient apiClient = new ApiClient(webClient);
}
3.5. Mögliche Fehler bei der Tokenweitergabe
Bei der Tokenweitergabe können verschiedene Fehler auftreten. Im Folgenden werden diesbezüglich die naheliegendsten Fehler beschrieben.
3.5.1. Ungültigkeit des Tokens
Wenn das Token im SecurityContext ungültig ist, wird eine InvalidBearerTokenException
geworfen und der Fehlercode 401: Unauthorized
zurückgegeben. Die Ungültigkeit kann auf verschiedenste Gründe zurückzuführen sein, beispielsweise könnte das Token abgelaufen oder fehlerhaft sein. Eine detaillierte Beschreibung des jeweiligen Fehlers ist unter der Error-URI
zu finden:
HTTP/1.1 401 Unauthorized WWW-Authenticate: Bearer error_code="invalid_token", error_description="Unsupported algorithm of none", error_uri="https://tools.ietf.org/html/rfc6750#section-3.1"
3.5.2. Kein Token im Security Context hinterlegt
Wenn im SecurityContext kein Token vorliegt, beispielsweise weil die Anwendung nicht authentifiziert ist, hat dies zur Folge, dass der ausgehende Request nicht um Authentifizierungsinformationen im Header ergänzt wird.
Der aufgerufene Server liefert in diesem Fall außer dem Fehlercode 401: Unauthorized
keine tiefergehenden Fehlerinformationen zurück.
HTTP/1.1 401 Unauthorized WWW-Authenticate: Bearer realm="example"
3.6. Authentifizierung eines OAuth 2.0 Clients mit dem Authentifizierungsmanager
Ein OAuth 2.0 Client kann über den Authentifizierungsmanager authentifiziert werden, welcher entsprechende Methoden zur Verwendung mit und ohne zuvor konfigurierte ClientRegistrations
bereitstellt.
-
Authentifizierung per
oauth2ClientRegistrationId
. Die Auswahl des Flows (Client Credentials oder Resource Owner Password Credentials) wird dabei über denauthorization-grant-type
der vollständig konfiguriertenClientRegistration
getroffen (siehe Beispiel: Spring Security OAuth 2.0 Client-Registrations). Diese Methode eignet sich in Anwendungen, wenn die Zugangsdaten für technische Nutzer zur Konfiguration bekannt sind. -
Authentifizierung per
issuerLocation
,clientId
undclientSecret
. Diese Methode nutzt den Client Credentials Flow und kann verwendet werden, wenn die Zugangsdaten des OAuth 2.0 Clients (clientId
undclientSecret
) erst zur Laufzeit bekannt sind. DieissuerLocation
verweist auf den OpenID Connect Provider, in dem der für den Client Credentials Flow konfigurierte OAuth 2.0 Client hinterlegt ist und als IAM-Service die Authentifizierung mit den übergebenen Authentifizierungsdaten durchgeführt wird. -
Authentifizierung per
issuerLocation
,clientId
,clientSecret
,username
undpassword
. Diese Methode nutzt den Resource Owner Password Credentials Flow und kann verwendet werden, wenn die Zugangsdaten des technischen Nutzers (username
undpassword
des Resource Owners) erst zur Laufzeit bekannt sind. Die Zugangsdaten des Vermittlers (clientId
undclientSecret
) werden benötigt, um die Authentifizierungsabfrage selbst zu autorisieren. DieissuerLocation
verweist auf den OpenID Connect Provider, gegen den die Authentifizierung mit dem dort für den Resource Owner Password Credentials Flow konfigurierten OAuth 2.0 Client durchgeführt werden soll. Die im Beispiel: Spring Security OAuth 2.0 Client-Registrations konfigurierten IsyFact-spezifischen ClientRegistration-Properties werden nicht benötigt, da die Zugangsdaten der Methode direkt übergeben werden.
[...]
spring.security.oauth2.client.provider.testrealm.issuer-uri=http://localhost:9095/auth/realms/testrealm
### Beispiel: ClientRegistration für den Client Credentials Flow
# Spring Security Konfiguration
spring.security.oauth2.client.registration.client1.client-id=client-credentials-client
spring.security.oauth2.client.registration.client1.client-secret=client-credentials-secret
spring.security.oauth2.client.registration.client1.authorization-grant-type=client_credentials
spring.security.oauth2.client.registration.client1.provider=testrealm
### Beispiel: ClientRegistration für den Resource Owner Password Credentials Flow
# Spring Security Konfiguration
spring.security.oauth2.client.registration.client2.client-id=client-credentials-client
spring.security.oauth2.client.registration.client2.client-secret=client-credentials-secret
spring.security.oauth2.client.registration.client2.authorization-grant-type=password
spring.security.oauth2.client.registration.client2.provider=testrealm
# Isyfact spezifische ClientRegistration properties für den Resource Owner Password Credentials Flow
isy.security.oauth2.client.registration.client2.username=testuser
isy.security.oauth2.client.registration.client2.password=testpassword
isy.security.oauth2.client.registration.client2.bhknz=123456
# Organizational Unit zur Verwendung mit bhknz
isy.security.oauth2.client.default-certificate-ou=TESTOU
3.7. Automatische Authentifizierung eines WebClient mit Client Credentials
Mit dem OAuth 2.0
-Grant client_credentials
steht eine vereinfachte Zugriffskontrolle für eine Client-Anwendung im Rahmen des Client Credentials Flow zur Verfügung.
Spring Security bietet umfassenden Support für OAuth 2.0
und unterstützt die Authentifizierung interner Systeme auf Basis des Client Credentials Flow
, wobei auf Spring interne Mechanismen zugegriffen wird.
Um clientseitig die automatische Konfiguration einer Anwendung zu ermöglichen, werden zunächst die oben aufgeführten Abhängigkeiten eingebunden und eine Client-Registration für den Client Credentials Flow
angelegt.
Um im Rahmen des Client Credentials Flows
HTTP-Anfragen an einen Ressourcenserver stellen zu können, ist zusätzlich die Konfiguration des reaktiven WebClient
erforderlich.
Hierzu wird die Standardimplementierung mit dem Zusatz eines OAuth2-Autorisierungsfilters verwendet.
Die "registrationId" ist hierbei auf die ID der für den Client Credentials Flow
konfigurierten Client-Registration zu setzen.
@Configuration
public class OAuth2WebClientConfiguration {
@Bean("webclient")
WebClient webClient(@Qualifier(ISY_AUTHORIZED_CLIENT_MANAGER_BEAN) OAuth2AuthorizedClientManager authorizedClientManager) {
ServletOAuth2AuthorizedClientExchangeFilterFunction oauth =
new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
oauth.setDefaultClientRegistrationId("registrationId");
return WebClient.builder().filter(oauth).build();
}
}
4. Authentifizierung über das SGW am IAM-Service
Die Authentifizierung über das Service Gateway (SGW) stellt einen wichtigen Schritt in der Sicherung von Anwendungen dar. Um diesen Prozess effektiv umzusetzen, empfiehlt sich die Verwendung des neu entwickelten Authentifizierungsmanagers und dessen Methoden.
Die Methoden erlauben es technische Nutzer zur Laufzeit mit ihren Zugangsdaten über den IAM-Service zu authentifizieren. Mit diesem Mechanismus wird sichergestellt, dass nur autorisierte Clients Zugriff auf die Ressourcen erhalten. Durch die Nutzung dieses speziellen Authentifizierungsmechanismus wird eine robuste und zuverlässige Sicherheitsschicht implementiert, um unautorisierten Zugriff und potenzielle Sicherheitslücken zu verhindern.
Weitere Informationen und detaillierte Anleitungen zur Verwendung können im Abschnitt zum Authentifizierungsmanager gefunden werden.
5. Absicherung von Batches und Tasks
Für detaillierte Informationen und Anleitung zur Absicherung von Batches und Tasks wird auf die Dokumentation unter
verwiesen. Diese bieten praxisorientierte Richtlinien zur Gewährleistung der Sicherheit von Batches und Tasks.
6. Absicherung von Service-Schnittstellen
Spring Security unterstützt die automatische Absicherung von Endpunkten einer Anwendung und eine feingranulare Autorisierung im Rahmen von OAuth 2.0
.
6.1. Maven Dependency
Dazu ist die Einbindung der folgenden Abhängigkeiten notwendig:
<dependency>
<groupId>de.bund.bva.isyfact</groupId>
<artifactId>isy-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
6.2. Spring Konfiguration
Um eine Anwendung auf Basis von OAuth 2.0
und unter Verwendung von JWT-Bearer-Tokens zu sichern, werden die oben aufgeführten Abhängigkeiten eingebunden. Die Verwendung der Abhängigkeit spring-security-oauth2-resource-server
führt dazu, dass die anwendungsspezifische SecurityFilterChain
um den Filter .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
erweitert wird.
Bietet die Applikation keine SecurityFilterChain
an, wird durch Spring Boot automatisch die folgende Konfiguration eingebunden:
@Configuration
@EnableWebSecurity
public class OAuth2ServerSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(authorize -> authorize.anyRequest().authenticated())
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
return http.build();
}
}
6.3. Konfigurationsparameter
Für die korrekte Anbindung an den IAM-Service
ist die Angabe der folgenden Konfigurationsparameter notwendig. Das Präfix sämtlicher Konfigurationsparameter spring.security.oauth2
wird zur Vereinfachung in der Liste unten weggelassen.
Parameter | Wertebereich | Default | Beschreibung |
---|---|---|---|
|
|
|
Auto-Konfiguration des IAM-Services zur Validierung des Bearer Tokens, beispielsweise in der Form "http://<identity-provider>/auth/realms/<realm>/protocol/openid-connect/certs" |
Zusätzlich sind folgende Isyfact-spezifischen Konfigurationsparameter notwendig.
Parameter | Wertebereich | Default | Beschreibung |
---|---|---|---|
|
|
|
Name des Claims im JWT Token der die Rollen enthält |
6.4. Konfiguration von Rollen und Rechten
Jede Geschäftsanwendung spezifiziert im Rahmen ihrer Systemspezifikation Rechte und bildet diese auf fachliche und technische Rollen ab. Bei der technischen Umsetzung müssen alle spezifizierten Rollen und Rechte konfiguriert und korrekt zugeordnet werden.
Der Pfad der Datei kann wie folgt angepasst werden:
Parameter | Wertebereich | Default | Beschreibung |
---|---|---|---|
|
|
|
Pfad zu der XML-Datei, welche die Rollen-/Berechtigungszuordnungen enthält. |
Der Baustein liefert ein XML-Schema für den Aufbau der Konfigurationsdatei mit.
Die Bereitstellung einer Datei mit den erforderlichen Rollen und Rechten erfolgt optional. Im Falle einer nicht vorhandenen Datei verbleibt die Liste der Rollen und Rechte leer, d. h. eine Absicherung der Anwendung findet nicht statt. Die Verantwortung zur korrekten Bereitstellung der erforderlichen Rollen und Rechten liegt bei der Anwendung. |
Dieser Zusammenhang wird mit einem Beispiel verdeutlicht: Die Geschäftsanwendung X spezifiziert zwei Rechte, DialogA.Aufrufen
und DialogB.Aufrufen
.
Aus diesen werden zwei fachliche Rollen gebildet:
-
FAX_DialogNutzerA
darf nur Dialog A aufrufen, -
FAX_DialogNutzerAlle
darf Dialog A und Dialog B aufrufen.
Dieses Beispiel führt zu folgender Konfigurationsdatei:
<tns:Anwendung AnwendungsId="GeschäftsanwendungX"
xmlns:tns="http://www.isyfact.de/RollenRechteSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.isyfact.de/RollenRechteSchema RollenRechteSchema.xsd ">
<!-- Definition der Rechte -->
<tns:rechte>
<tns:rechtId Id="DialogA.Aufrufen" />
</tns:rechte>
<tns:rechte>
<tns:rechtId Id="DialogB.Aufrufen" />
</tns:rechte>
<!-- Definition der Rollen -->
<tns:rollen RolleId="FAX_DialogNutzerA">
<tns:rechtId Id="DialogA.Aufrufen" />
</tns:rollen>
<tns:rollen RolleId="FAX_DialogNutzerAlle">
<tns:rechtId Id="DialogA.Aufrufen" />
<tns:rechtId Id="DialogB.Aufrufen"/>
</tns:rollen>
</tns:Anwendung>
6.5. Zusammenhang von Rechten und Rollen
Innerhalb jeder Rolle werden gemäß Spezifikation die zugeordneten Rechte festgelegt. Rollen können überlappende Teilmengen von Rechten enthalten.
Die Konfiguration muss die folgenden Anforderungen erfüllen:
-
Es sind alle in der Geschäftsanwendung spezifizierten Rechte definiert.
-
Es sind alle in der Geschäftsanwendung spezifizierten Rollen definiert.
Werden in Überprüfungen Rollen oder Rechte verwendet, die hier nicht definiert sind, wird ein technischer Fehler erzeugt. Die Konfiguration gibt also verlässlich Auskunft darüber, welche Rollen und Rechte in der Geschäftsanwendung überprüft werden.
Der Baustein Security ermöglicht eine Autorisierung nur auf Basis von Rechten, nicht von Rollen. Jeder Rolle muss also zumindest ein Recht zugeordnet werden, um anhand dessen eine Autorisierung durchführen zu können. Werden im Lebenszyklus der Geschäftsanwendung weitere Rollen (z.B. für neu hinzukommende Akteure) spezifiziert und mit bestehenden Rechten ausgestattet, sind neben den Änderungen in der Konfigurationsdatei keine weiteren Änderungen notwendig.
6.6. Autorisierung an einer Service-Schnittstelle
Zentral für die Autorisierung ist die von Spring bereitgestellte Annotation @Secured
, die alle benötigten Rechte des Aufrufers überprüft.
Eine Autorisierung direkt über die Rollen des Aufrufers ist nicht möglich.
Die Annotation kommt in der Service-Schicht zur Anwendung und autorisiert den Zugriff auf eine Service-Methode. Sollten alle Methoden die gleiche Autorisierung erfordern, kann alternativ die Annotation auch an der Service-Klasse verwendet werden.
Folgendes Beispiel (Absichern einer Service-Methode) verdeutlicht die Implementierung einer abgesicherten Service-Methode.
@Secured({ "PRIV_RechtA", "PRIV_RechtB" })
public void abgesicherteMethode(...) {
...
}
Als Parameter wird ein Array von Rechten übergeben.
Die Rechte sind disjunktiv verknüpft.
Die Autorisierung erfolgt dementsprechend wenn der Nutzer mindestens eins der in der Secured
Annotation übergebenen Rechte besitzt.
7. Attribute aus dem Bearer Token abfragen
Bei der Befüllung des Spring Security Context wird das zur Befüllung genutzte Bearer Token ebenfalls im Context abgelegt. Dadurch ist der Zugriff auf Attribute des Bearer Tokens über den Spring Security Context möglich. Der Zugriff kann über den Berechtigungsmanager oder direkt über den Spring Security Context erfolgen.
Für Zugriff über den Berechtigungsmanager kann die Methode getTokenAttribute(String key)
genutzt werden.
Das Beispiel Zugriff auf das Behördenkennzeichen veranschaulicht den Zugriff auf das im Attribut bhknz
gespeicherte Behördenkennzeichen.
String bhknz = (String) this.berechtigungsmanager.getTokenAttribute(BEARER_TOKEN_ATTR_BHKNZ);
Für den direkten Zugriff per Security Context kann die Authentication
abgefragt und per Cast als ein AbstractOAuth2TokenAuthenticationToken
zugegriffen werden.
Detaillierte Informationen hierzu können der Spring Dokumentation entnommen werden.
8. Automatische Authentifizierung innerhalb von Methoden
Wenn Client Registrations für OAuth 2.0 Clients in der Anwendung angelegt wurden (vgl. Konfigurationsparameter), kann die @Authenticate
-Annotation verwendet werden, um anhand dieses Clients automatisch Aufrufe innerhalb der mit der Annotation versehenen Methode zu authentifizieren.
Der dabei verwendete OAuth 2.0 Flow wird anhand der Konfiguration der Client Registration ausgewählt.
Dafür muss in der Annotation die Client Registration ID des zu verwendenden OAuth 2.0 Clients angegeben werden.
Dies kann entweder durch Hardcoden der ID oder über die dynamische Auflösung eines Property Placeholders erfolgen.
Die Client Registration ID kann über verschiedene Attribute der Annotation (kein Attribut, value
-Attribut, oauth2ClientRegistrationId
-Attribut) angegeben werden, welche von der Funktionalität identisch sind.
Die einzige Voraussetzung ist, dass die Client Registration ID in einem dieser Attribute angegeben wurde.
@Authenticate("my-auth-client") (1)
void methodThatNeedsAuthentication() {
...
}
@Authenticate("${test.auth.client-id}") (2)
void methodThatNeedsAuthentication() {
...
}
@Authenticate(oauth2ClientRegistrationId = "my-auth-client") (3)
void methodThatNeedsAuthentication() {
...
}
1 | Angabe der Client Registration ID ohne Verwendung von Attributnamen |
2 | Auflösung der Client Registration ID aus dem Wert der Property test.auth.client-id |
3 | Angabe der Client Registration ID mit dem Attributnamen oauth2ClientRegistrationId |
9. Testunterstützung
In diesem Abschnitt wird isy-security-test beschrieben, das zum Erstellen von (automatisierten) Tests einen OpenId Connect Provider Mock bereitstellt. Der OpenId Connect Provider Mock wurde mithilfe von WireMock realisiert. Es werden die folgenden OAuth2 und OpenID Connect Verfahren unterstützt.
-
Client Credentials Flow
-
Resource Owner Password Credentials Flow
Das folgende Beispiel zeigt die Initialisierung des EmbeddedOidcProviderMock mit einem Client mit genau einer Rolle und mit einem User mit derselben Rolle:
EmbeddedOidcProviderMock embeddedOidcProvider = new EmbeddedOidcProviderMock("localhost", 9095, "/auth/realms/testrealm");
embeddedOidcProvider.addClient("client-credentials-client", "supersecretpassword", Collections.singleton("Test_Role"));
embeddedOidcProvider.addUser("ressource-owner-password-credentials-client", "hypersecretpassword", "admin", "adminpassword", Optional.of("123456"), Collections.singleton("Test_Role"));
Detaillierte Informationen zur Verwendung des EmbeddedOidcProviderMock können dem JavaDoc der Klasse entnommen werden.
10. Anhang
10.1. Anhang A: Rollen-Rechte-Schema
Im Folgenden ist der Inhalt der Datei RollenRechteSchema.xsd
wiedergegeben, die das Format der Konfigurationsdatei für Rollen und Rechte (rollenrechte.xml
) festlegt.
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.isyfact.de/RollenRechteSchema"
xmlns:tns="http://www.isyfact.de/RollenRechteSchema"
elementFormDefault="qualified">
<include schemaLocation=""></include>
<complexType name="Rolle">
<sequence>
<element name="rechtId" type="tns:RechtId" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
<attribute name="RolleId" type="string" use="required"/>
</complexType>
<complexType name="Recht">
<sequence>
<element name="rechtId" type="tns:RechtId" minOccurs="1" maxOccurs="1"/>
</sequence>
</complexType>
<element name="Anwendung" type="tns:Anwendung"/>
<complexType name="Anwendung">
<sequence>
<element name="rollen" type="tns:Rolle" minOccurs="1" maxOccurs="unbounded"/>
<element name="rechte" type="tns:Recht" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
<attribute name="AnwendungsId" type="string" use="required"/>
</complexType>
<complexType name="RechtId">
<attribute name="Id" type="string" use="required"/>
</complexType>
</schema>