All Projects → raphaelDL → Spring Webflux Security Jwt

raphaelDL / Spring Webflux Security Jwt

A JWT authorization and authentication implementation with Spring Reactive Webflux, Spring Boot 2 and Spring Security 5

Programming Languages

java
68154 projects - #9 most used programming language

Projects that are alternatives of or similar to Spring Webflux Security Jwt

Simplemall
基于SpringCloud的微服务架构实战案例项目,以一个简单的购物流程为示例,融合spring cloud 相关组件,如spring-cloud-netflix、swagger等
Stars: ✭ 687 (+261.58%)
Mutual labels:  spring-boot, jwt, spring-security, jwt-authentication
Springboot Jwt Starter
A Spring Boot JWT starter kit for stateless and token-based authentication apps.
Stars: ✭ 538 (+183.16%)
Mutual labels:  spring-boot, jwt, spring-security, jwt-authentication
Spring Boot Webflux Jjwt
Example Spring Boot and WebFlux (Reactive Web) with Spring Security and JWT for token Authentication and Authorization
Stars: ✭ 71 (-62.63%)
Mutual labels:  reactive, spring-boot, jwt, spring-security
Webfluxtemplate
Spring Webflux template application with working Spring Security, Web-sockets, Rest, Web MVC, and Authentication with JWT.
Stars: ✭ 107 (-43.68%)
Mutual labels:  reactive, spring-boot, spring-security, jwt-authentication
Jwt Spring Security Demo
This is a demo for using JWT (JSON Web Token) with Spring Security and Spring Boot. I completely rewrote my first version. Now this solution is based on the code base from the JHipster Project. I tried to extract the minimal configuration and classes that are needed for JWT-Authentication and did some changes.
Stars: ✭ 2,843 (+1396.32%)
Mutual labels:  spring-boot, jwt, spring-security, jwt-authentication
Jwt Security Example
Spring Boot with Spring Security using JWT
Stars: ✭ 154 (-18.95%)
Mutual labels:  spring-boot, jwt, spring-security
Spring Boot Jwt
JWT auth service using Spring Boot, Spring Security and MySQL
Stars: ✭ 795 (+318.42%)
Mutual labels:  spring-boot, jwt, spring-security
Angular Spring Reactive Sample
RESTful API demos with Spring 5 WebFlux, Spring Boot 2, Spring Data Mongo, Spring Security, Spring Session and Angular 11
Stars: ✭ 153 (-19.47%)
Mutual labels:  reactive, spring-boot, spring-security
Ixortalk.aws.cognito.jwt.security.filter
Spring Boot security filter for decoding Cognito JWT IdTokens
Stars: ✭ 75 (-60.53%)
Mutual labels:  spring-boot, jwt, spring-security
Spring Boot In Action
Spring Boot 系列实战合集
Stars: ✭ 4,153 (+2085.79%)
Mutual labels:  spring-boot, jwt, spring-security
Eshop Soa
EShop基于Dubbo实现SOA服务化拆分,并基于RocketMQ解决了分布式事务(新版SpringBootSOASkeleton)
Stars: ✭ 65 (-65.79%)
Mutual labels:  spring-boot, jwt, spring-security
Easy Notes
🍋 简笔记(easy notes)打造你的轻便私人笔记。接口涉及Spring Security、OAuth2、Jwt、MongoDB,客户端采用 Vue.js 、Ant Design
Stars: ✭ 89 (-53.16%)
Mutual labels:  spring-boot, jwt, spring-security
Sample Spring Oauth2 Microservices
some examples that show basic and more advanced implementations of oauth2 authorization mechanism in spring-cloud microservices environment
Stars: ✭ 109 (-42.63%)
Mutual labels:  spring-boot, jwt, spring-security
Milkomeda
Spring extend componets which build from experience of bussiness, let developers to develop with Spring Boot as fast as possible.(基于Spring生态打造的一系列来自业务上的快速开发模块集合。)
Stars: ✭ 117 (-38.42%)
Mutual labels:  spring-boot, jwt, spring-security
Oidc Workshop Spring Io 2019
Workshop at Spring I/O 2019 on "Securing Microservices with OpenID Connect and Spring Security 5.1"
Stars: ✭ 43 (-77.37%)
Mutual labels:  spring-boot, jwt, spring-security
Cerberus
A demonstration of a completely stateless and RESTful token-based authorization system using JSON Web Tokens (JWT) and Spring Security.
Stars: ✭ 482 (+153.68%)
Mutual labels:  spring-boot, jwt, spring-security
Springboot Restful Angular
springBoot,restful,jwt,angular4 搭建的前后端分离后台管理系统
Stars: ✭ 121 (-36.32%)
Mutual labels:  spring-boot, jwt, spring-security
Xboot
基于Spring Boot 2.x的一站式前后端分离快速开发平台XBoot 微信小程序+Uniapp 前端:Vue+iView Admin 后端:Spring Boot 2.x/Spring Security/JWT/JPA+Mybatis-Plus/Redis/Elasticsearch/Activiti 分布式限流/同步锁/验证码/SnowFlake雪花算法ID 动态权限 数据权限 工作流 代码生成 定时任务 社交账号 短信登录 单点登录 OAuth2开放平台 客服机器人 数据大屏 暗黑模式
Stars: ✭ 3,432 (+1706.32%)
Mutual labels:  spring-boot, jwt, spring-security
His
HIS英文全称 hospital information system(医院信息系统http://59.110.234.89:9999/swagger-ui.html ),医疗信息就诊系统,系统主要功能按照数据流量、流向及处理过程分为临床诊疗、药品管理、财务管理、患者管理。诊疗活动由各工作站配合完成,并将临床信息进行整理、处理、汇总、统计、分析等。本系统包括以下工作站:门诊医生工作站、药房医生工作站、医技医生工作站、收费员工作站、对帐员工作站、管理员工作站。需求为东软提供的云医院。
Stars: ✭ 359 (+88.95%)
Mutual labels:  spring-boot, jwt, spring-security
Spring Security React Ant Design Polls App
Full Stack Polls App built using Spring Boot, Spring Security, JWT, React, and Ant Design
Stars: ✭ 1,336 (+603.16%)
Mutual labels:  spring-boot, jwt, spring-security

Authentication and Authorization using JWT with Spring WebFlux and Spring Security Reactive

Nice Docs to Read First

Before getting started I suggest you go through the next reference

Spring Webflux

Spring Security Reactive

Spring Security Architecture

Enable Spring WebFlux Security

First enable Webflux Security in your application with @EnableWebFluxSecurity

@SpringBootApplication
@EnableWebFluxSecurity
public class SecuredRestApplication {
....
}

Create an InMemory UserDetailsService

Define a custom UserDetailsService bean where an User with password and initial roles is added:

@Bean
    public MapReactiveUserDetailsService userDetailsRepository() {
        UserDetails user = User.withDefaultPasswordEncoder()
                .username("user")
                .password("user")
                .roles("USER", "ADMIN")
                .build();
        return new MapReactiveUserDetailsService(user);
    }

In this example user information will be stored in memory using a Map but it can be replaced by different strategies.

Before getting a Json Web Token an user should use another authentication mechanism, for example HTTP Basic Authentication and provided the right credentials a JWT will be issued which can be used to perform future API calls by changing the Authetication method from Basic to Bearer.

Starting from Basic Authentication

Below there's a simple way to define Basic Authentication with Spring Security. Customization is needed in order to return a JWT on succesful authentication.

@Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        http
            .authorizeExchange()
                .anyExchange().authenticated()
                .and()
            .httpBasic(); // Pure basic is not enough for us!
            
        return http.build();
    }

Inspect AuthenticationFilter, improvise, adapt overcome

With Spring Reactive, requests go through a chain of filters, each filter can aprove or discard requests according to different rules. Advantage is taken to perform request authentication. Different types of WebFilter are grouped by a WebFilterChain, in Spring Security there's AuthenticationWebFilter which outlines how authentication should be performed on requests matching a criteria.

AuthenticationWebFilter implements all the required behavior for Basic Authentication, take a look at it:

public class AuthenticationWebFilter implements WebFilter {

	private final ReactiveAuthenticationManager authenticationManager;

	private ServerAuthenticationSuccessHandler authenticationSuccessHandler = new WebFilterChainServerAuthenticationSuccessHandler(); 
  // WE NEED A DIFFERENT SUCCESS HANDLER!!!!!!

	private Function<ServerWebExchange, Mono<Authentication>> authenticationConverter = new ServerHttpBasicAuthenticationConverter();

	private ServerAuthenticationFailureHandler authenticationFailureHandler = new ServerAuthenticationEntryPointFailureHandler(new HttpBasicServerAuthenticationEntryPoint());

	private ServerSecurityContextRepository securityContextRepository = NoOpServerSecurityContextRepository.getInstance();

	private ServerWebExchangeMatcher requiresAuthenticationMatcher = ServerWebExchangeMatchers.anyExchange();

....

The behavior that needs to be changed is what happens once an user has been authenticated using user/password credentials. The WebFilterChainServerAuthenticationSuccessHandler will pass the request through the filter chain. A custom implementation is needed in this step where a Json Web Token is generated and added to the response, then the exchange will follow its way.

Create custom SuccessHandler to make Basic Authentication return a Json Web Token

Create a custom ServerAuthenticationSuccessHandler, this handler is executed once the authentication with user/password has been successful, it receives the current exchange and Authentication object. A JWT is generated using the Exchange and Authentication object. In this way BasicAuthenticationSuccessHandler implements the desired behavior:

...
 @Override
    public Mono<Void> onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) {
    // Create and attach a JWT before passing the exchange to the filter chain
        ServerWebExchange exchange = webFilterExchange.getExchange();
        exchange.getResponse()
                .getHeaders()
                .add(HttpHeaders.AUTHORIZATION, getHttpAuthHeaderValue(authentication));
        return webFilterExchange.getChain().filter(exchange);
    }
...

The response from the current exchange is updated with the HTTP Authorization header with a new JWT that contains data from the Authentication object.

Create a Basic Authentication filter that returns a JWT

Now create a new AuthenticationFilter with a custom handler:

...
UserDetailsRepositoryReactiveAuthenticationManager authManager;
        AuthenticationWebFilter basicAuthenticationFilter;
        ServerAuthenticationSuccessHandler successHandler;
        
        authManager = new UserDetailsRepositoryReactiveAuthenticationManager(userDetailsRepository());
        successHandler = new  BasicAuthenticationSuccessHandler();

        basicAuthenticationFilter = new AuthenticationWebFilter(authManager);
        basicAuthenticationFilter.setAuthenticationSuccessHandler(successHandler);

...

Add this filter to ServerHttpSecurity

Add this to our ServerHttpSecurity:

...
http
                .authorizeExchange()
                    .pathMatchers("/login", "/")
                    .authenticated()
                .and()
                    .addFilterAt(basicAuthenticationFilter, SecurityWebFiltersOrder.HTTP_BASIC)
...

The functionality that returns a JWT when authenticating using User and Password is now implemented.

Handle Requests with Bearer token Authorization Header

Now let's build the functionality that will take a request with the HTTP Authorization Header containing a Bearer token. The same way the AuthenticationWebFilter was customized before, customize another to create a new filter.

When using JWT all information needed to authenticate and authorize a user lives within a token. Perform the next steps:

Filter requests containing a Bearer token within its HTTP Authorization Header, verify that are well formed, confirm that it has a valid signature and then build an Authorization object with all information contained in the payload. If the JWT is invalid, there won't be Authorization resulting in an unauthorized response.

Because all information needed is contained in the JWT payload all invalid tokens will be rejected in the filtering step, but the contract defined by the AuthenticationWebFilter requires a non null AuthenticationManager. Create a dummy manager that will authenticate all exchanges. Why? Because all invalid JWT did not resulted in an authorization object and did not make it into this step.

Generate an Authentication object using only the information contained in the token

Create a converter ServerHttpBearerAuthenticationConverter that takes a request ServerWebExchange and returns an Authorization object created with the information extracted from the token:

...
 public Mono<Authentication> apply(ServerWebExchange serverWebExchange) {
        return Mono.justOrEmpty(serverWebExchange)
                .flatMap(AuthorizationHeaderPayload::extract)
                   .filter(matchBearerLength)
                .flatMap(isolateBearerValue)
                .flatMap(jwtVerifier::check)
                .flatMap(UsernamePasswordAuthenticationBearer::create).log();
    }
...

Create a dummy AuthenticationManager

Now implement a dummy AuthenticationManager called BearerTokenReactiveAuthenticationManager:

...
 public Mono<Authentication> authenticate(Authentication authentication) {
        return Mono.just(authentication);
    }
  
...

Add the new filter to ServerHttpSecurity

Finally chain this filter in the ServerHttpSecurity configuration object:

...
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {

        http
                .authorizeExchange()
                    .pathMatchers("/login", "/")
                    .authenticated()
                .and()
                    .addFilterAt(basicAuthenticationFilter(), SecurityWebFiltersOrder.HTTP_BASIC)
                       .authorizeExchange()
                    .pathMatchers("/api/**")
                    .authenticated()
                .and()
                    .addFilterAt(bearerAuthenticationFilter(), SecurityWebFiltersOrder.AUTHENTICATION);

        return http.build();
    }
...

Create a REST Controller and configure access rules

...
 @GetMapping("/api/private")
    @PreAuthorize("hasRole('USER')")
    public Flux<FormattedMessage> privateMessage() {
        return messageService.getCustomMessage("User");
    }

...

Run the Application

With Maven

$ mvn spring-boot:run

With Gradle

$ ./gradlew bootRun

Test it

Login using HTTP Basic

$ curl -v  -u user:user localhost:8080/login

Inspect the response contents and find the authorization header. It should look like:

Authorization: Bearer eyJhbGciOiJIUzI1Ni.....

Use that in another request:

$ curl -v  -H "Authorization: Bearer eyJhbGciOiJIUzI1Ni....."  localhost:8080/api/admin

You should be able to consume the API

That's all

Hope you enjoy it.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].