Spring Authorization Server und OAuth2/OIDC
Spring Authorization Server stellt Bausteine für OAuth2- und OpenID-Connect-Authorization-Server bzw. Identity-Provider bereit.
Fachliche Einordnung
In Enterprise-Architekturen sollte nicht jede Anwendung eigene Login- und Tokenlogik bauen. Ein Authorization Server zentralisiert Clients, Grants, Token und Schlüssel.
Enterprise-Merksatz: Spring Authorization Server stellt Bausteine für OAuth2- und OpenID-Connect-Authorization-Server bzw. Identity-Provider bereit.
Technische Darstellung
Kernkonzepte
- RegisteredClient und ClientAuthentication.
- Authorization Code Flow mit PKCE.
- JWT, JWK Set und Key Rotation.
- Scopes, Claims und Consent.
- Abgrenzung zu Resource Servern und externen IdPs.
Wann einsetzen?
- Du betreibst eigenen internen Identity Provider oder OAuth2 Server.
- Du brauchst maschinenlesbare Token für Microservices.
- Du willst bestehende Benutzerquelle mit OIDC verbinden.
Typische Fehler und Risiken
- Eigenen Authorization Server bauen, obwohl ein Unternehmens-IdP existiert.
- Refresh Tokens ohne Rotation und Lebensdauerregeln.
- Claims mit Berechtigungen überladen.
Legacy- und Modernisierungssicht
Form Login, LDAP-Login oder proprietäre SSO-Lösungen werden schrittweise an OIDC/OAuth2 angebunden; APIs validieren danach Tokens als Resource Server.
Ausführliches Beispiel
Das Beispiel zeigt bewusst nicht nur Annotationen, sondern auch die Verantwortung der Schicht. In echten Projekten sollte der technische Spring-Code an Adapter- oder Konfigurationsrändern bleiben, während die Fachlogik testbar und möglichst frameworkarm bleibt.
@Configuration
class AuthorizationServerConfiguration {
@Bean
RegisteredClientRepository registeredClients(PasswordEncoder encoder) {
RegisteredClient client = RegisteredClient.withId(UUID.randomUUID().toString())
.clientId("order-portal")
.clientSecret(encoder.encode("change-me"))
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri("https://portal.example.com/login/oauth2/code/order")
.scope("openid")
.scope("order.write")
.clientSettings(ClientSettings.builder().requireProofKey(true).build())
.build();
return new InMemoryRegisteredClientRepository(client);
}
}
Checkliste für Reviews
- Ist die Verantwortung des Bausteins klar: Framework steuert Lebenszyklus, Library wird gezielt benutzt?
- Ist die Fachlogik außerhalb von Controller, Listener, Repository-Implementierung oder Konfiguration?
- Sind Fehlerfälle, Timeouts, Security, Monitoring und Tests sichtbar modelliert?
- Gibt es klare Grenzen zwischen DTO, Domäne, Persistence und Infrastruktur?