ENG
- Services
- Unser Serviceportfolio
Wir erwecken Ihre digitale Produktvision zum Leben: Vom testbaren Prototypen bis zur fertigen Softwarelösung.
- Kooperationsmodelle
Kooperationsmodelle passend zu Ihren Bedürfnissen: Komplette Nearshoring Teams, deutschsprachige Experten vor Ort mit Nearshoring-Teams oder gemischte Teams mit unseren Partnern.
- Arbeitsweise
Durch enge Zusammenarbeit mit Ihrem Unternehmen schaffen wir maßgeschneiderte Lösungen, die auf Ihre Anforderungen abgestimmt sind und zu nachhaltigen Ergebnissen führen.
- Unser Serviceportfolio
- Über uns
- Wer wir sind
Wir sind ein Full-Service Nearshoring-Anbieter für digitale Softwareprodukte, ein perfekter Partner mit deutschsprachigen Experten vor Ort, Ihre Business-Anforderungen stets im Blick
- Unser Team
Das ProductDock Team ist mit modernen Technologien und Tools vertraut und setzt seit 15 Jahren zusammen mit namhaften Firmen erfolgreiche Projekte um.
- Unsere Standorte
Wir sind ProductDock, ein Full-Service Nearshoring-Anbieter für Softwareprodukte mit Hauptsitz in Berlin und Entwicklungs-Hubs in Lissabon, Novi Sad, Banja Luka und Doboj.
- Wozu Nearshoring
Wir kombinieren Nearshore- und Fachwissen vor Ort, um Sie während Ihrer gesamten digitalen Produktreise optimal zu unterstützen. Lassen Sie uns Ihr Business gemeinsam auf das nächste digitale Level anheben.
- Wer wir sind
- Unser Leistungen
- Karriere
- Arbeiten bei ProductDock
Unser Fokus liegt auf der Förderung von Teamarbeit, Kreativität und Empowerment innerhalb unseres Teams von über 120 talentierten Tech-Experten.
- Offene Stellen
Begeistert es dich, an spannenden Projekten mitzuwirken und zu sehen, wie dein Einsatz zu erfolgreichen Ergebnissen führt? Dann bist du bei uns richtig.
- Info Guide für Kandidaten
Wie suchen wir unsere Crew-Mitglieder aus? Wir sehen dich als Teil unserer Crew und erklären gerne unseren Auswahlprozess.
- Arbeiten bei ProductDock
- Newsroom
- News
Folgen Sie unseren neuesten Updates und Veröffentlichungen, damit Sie stets über die aktuellsten Entwicklungen von ProductDock informiert sind.
- Events
Vertiefen Sie Ihr Wissen, indem Sie sich mit Gleichgesinnten vernetzen und an unseren nächsten Veranstaltungen Erfahrungen mit Experten austauschen.
- News
- Blog
- Kontakt

23. Mai 2024 •2 minutes read
Exploring the Spring Authorization Server
ProductDock
Bojan Ćorić, our software engineer, delivered a talk at the year-end conference titled “Exploring the Spring Authorization Server.” He explored the functionalities of a relatively new authorization server from the Spring ecosystem, offering a potential solution tailored to your requirements.
Spring Authorization Server allows us to build a fully customizable OAuth2 and OpenID Authorization server. In this talk, we will customize the authorization server using common extension points while following best practices.
Spring Authorization Server in practice
Spring Authorization Server is a powerful and flexible identity and access management solution built on top of the Spring ecosystem, specifically designed to simplify the process of securing your applications and APIs. It provides robust authentication and authorization mechanisms, allowing you to control access to your resources effectively. It implements the OAuth 2.1 and OpenId Connect 1.0, simplifying integration with systems compliant with either of these specifications.
Minimal configuration
It works out of the box with minimal configuration. If you go to start.spring.io to generate a new project, the only dependency that you need is the OAuth2 Authorization Server (link to generate project).
The following configuration is required when starting the application as an authorization server:
# https://docs.spring.io/spring-boot/docs/current/reference/html/web.html#web.security.oauth2.authorization-server
spring:
security:
user:
name: user
password: password
oauth2:
authorizationserver:
client:
productdock:
registration:
client-id: "productdock"
client-secret: "{bcrypt}$2a$10$aXhyiUX2incAVeTnN85tueTYgUkqH/hh86i4Ex9FaeoRAyTU71n4i" # bcrypt of productdock
client-authentication-methods:
- "client_secret_basic"
authorization-grant-types:
- "authorization_code"
- "refresh_token"
- "client_credentials"
redirect-uris:
- "http://127.0.0.1/login/oauth2/code/productdock"
scopes:
- "openid"
- "profile"
- "email"
- "phone"
- "address"
require-authorization-consent: true
server:
port: 9090
Explicit configuration
In case you don’t want to configure this via yml file, you can do that explicitly from your code by defining the following beans:
@Bean
public UserDetailsService userDetailsService() {
return new InMemoryUserDetailsManager(
User.builder().username("user").password("{bcrypt}$2a$10$K4nPRbjfGTPLmrRu07PMT.h6TWPJvSGuZRUzATYyDHJ1JZBsRrNoi").build()
);
}
@Bean
public DaoAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
var authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
return authProvider;
}
// https://docs.spring.io/spring-authorization-server/reference/getting-started.html#defining-required-components
@Bean
@Order(1)
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
.oidc(Customizer.withDefaults());
http.exceptionHandling(exceptions -> exceptions.authenticationEntryPoint(
new LoginUrlAuthenticationEntryPoint("/login")))
.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()));
return http.build();
}
@Bean
@Order(2)
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(authorize -> authorize.anyRequest().authenticated())
.formLogin(Customizer.withDefaults());
return http.build();
}
@Bean
public RegisteredClientRepository registeredClientRepository() {
RegisteredClient client = RegisteredClient.withId(UUID.randomUUID().toString())
.clientId("productdock")
.clientSecret("{bcrypt}$2a$10$0lAOvcI202G9go0h7MD75OczUgjNb4cp2KlPsH13NFqQ0NtipN7dq")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.redirectUri("http://127.0.0.1/login/oauth2/code/productdock")
.scope(OidcScopes.OPENID)
.scope(OidcScopes.PROFILE)
.scope(OidcScopes.EMAIL)
.scope(OidcScopes.PHONE)
.scope(OidcScopes.ADDRESS)
.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
.build();
return new InMemoryRegisteredClientRepository(client);
}
If you try now to access your resource server that is protected by this authorization server you will be redirected to the authorization server where you have to input your credentials.
Steps towards production
While this is nice for demonstration purposes, it is not so useful in real-life scenarios.
The first step to making this production-ready is to add some persistent storage so that our state is not lost when the application restarts.
Lets update pom.xml with additional dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
Update the application.yml with database credentials:
spring:
datasource:
username: authservice-rw
password: authservice-rw
url: jdbc:postgresql://localhost:5432/authservice
server:
port: 9090
To use persistent storage instead of in-memory, update the following beans:
@Bean
public RegisteredClientRepository registeredClientRepository(JdbcTemplate jdbcTemplate) {
return new JdbcRegisteredClientRepository(jdbcTemplate);
}
@Bean
public JdbcUserDetailsManager jdbcUserDetailsManager(DataSource dataSource) {
return new JdbcUserDetailsManager(dataSource);
}
@Bean
public JdbcOAuth2AuthorizationConsentService jdbcOAuth2AuthorizationConsentService(
JdbcOperations jdbcOperations, RegisteredClientRepository registeredClientRepository) {
return new JdbcOAuth2AuthorizationConsentService(jdbcOperations, registeredClientRepository);
}
@Bean
public JdbcOAuth2AuthorizationService jdbcOAuth2AuthorizationService(
JdbcOperations jdbcOperations,
RegisteredClientRepository registeredClientRepository) {
return new JdbcOAuth2AuthorizationService(jdbcOperations, registeredClientRepository);
}
Database scripts for this work
If you wonder how where to find related database scripts for this to work, it is on your classpath:
- classpath:org/springframework/security/oauth2/server/authorization/client/oauth2-registered-client-schema.sql
- classpath:org/springframework/security/oauth2/server/authorization/oauth2-authorization-consent-schema.sql
- classpath:org/springframework/security/oauth2/server/authorization/oauth2-authorization-schema.sql
Managing keys
Another important part of the authorization server is managing keys that are used to sign tokens. Here is an example of how to generate in-memory keys:
@Bean
public JWKSource<SecurityContext> jwkSource() {
KeyPair keyPair = generateRsaKey();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
RSAKey rsaKey = new RSAKey.Builder(publicKey)
.privateKey(privateKey)
.keyID(UUID.randomUUID().toString())
.build();
JWKSet jwkSet = new JWKSet(rsaKey);
return new ImmutableJWKSet<>(jwkSet);
}
private static KeyPair generateRsaKey() {
KeyPair keyPair;
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
keyPair = keyPairGenerator.generateKeyPair();
}
catch (Exception ex) {
throw new IllegalStateException(ex);
}
return keyPair;
}
Note that this is not a secure way to store your keys. Instead, use secure storage mechanisms such as environment variables, encrypted files, or key vault services such as HashiCorp Vault.
Next steps
With these key concepts, we built a usable authorization server that can be used in real-life scenarios. You can build an admin console to manage clients, users, sessions, etc. You can extend it with your chosen social login provider, such as Google, GitHub, Okta, etc. You can add two-factor authentication.
New Spring Authorization server solution
Bojan explored the functionalities of a relatively new authorization server from the Spring ecosystem. He concluded that the Spring Authorization Server allows us to build a fully customizable OAuth2 and OpenID Authorization server and customize it using common extension points while following best practices. To check how to protect your resources using the Spring Authorization Server check our GitHub repository.
Explore our blog section for exciting topics we’ll share with you soon.