Introduction to OAuth 2.0 and JWT Authorization in Java
Modern web applications and APIs require reliable authentication and authorization mechanisms. Two standards that have become de facto in the world of Java development are OAuth 2.0 and JWT (JSON Web Tokens). OAuth 2.0 provides a protocol for delegating access, while JWT is a compact and self-contained data transfer format. In this article, we will explore how to combine these technologies in Java using Spring Security and popular libraries.
You will learn how to configure an authorization server, generate and validate JWT tokens, and protect your REST endpoints. This material will be useful for both beginner and experienced Java developers looking to deepen their knowledge in security.
OAuth 2.0 Basics: Flows and Roles
OAuth 2.0 defines four roles: Resource Owner, Client (application), Authorization Server, and Resource Server. The most popular flows (grants) include:
- Authorization Code — for web applications with a server-side component.
- Client Credentials — for server-to-server communication.
- Resource Owner Password — for trusted clients (deprecated).
- Implicit — for SPAs (no longer recommended).
In Java, we can implement an OAuth 2.0 server using spring-security-oauth2-authorization-server. Let's look at an example of configuring a basic authorization server.
Setting up an Authorization Server on Spring Boot
Add dependencies to pom.xml:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-authorization-server</artifactId></dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency>Create the configuration SecurityConfig.java:
@Configuration@EnableWebSecuritypublic class SecurityConfig {
@Bean @Order(1) public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception { OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http); 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 registeredClient = RegisteredClient.withId("client-id") .clientId("my-client") .clientSecret("{noop}secret") .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) .redirectUri("http://localhost:8080/login/oauth2/code/my-client") .scope("read") .scope("write") .build(); return new InMemoryRegisteredClientRepository(registeredClient); }}JWT: Token Structure and Generation
JWT consists of three parts: Header, Payload, and Signature. The Header contains the token type and encryption algorithm. The Payload includes claims such as sub (subject), exp (expiration time), and roles. The Signature ensures data integrity.
For working with JWT in Java, we use the io.jsonwebtoken:jjwt library. Add the dependenc