1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.bremersee.web.reactive.function.client;
18
19 import org.bremersee.security.authentication.AccessTokenProvider;
20 import org.bremersee.security.authentication.AccessTokenRetriever;
21 import org.bremersee.security.authentication.AccessTokenRetrieverProperties;
22 import org.bremersee.security.authentication.ReactiveAccessTokenProviders;
23 import org.springframework.http.HttpHeaders;
24 import org.springframework.lang.NonNull;
25 import org.springframework.util.Assert;
26 import org.springframework.util.StringUtils;
27 import org.springframework.web.reactive.function.client.ClientRequest;
28 import org.springframework.web.reactive.function.client.ClientResponse;
29 import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
30 import org.springframework.web.reactive.function.client.ExchangeFunction;
31 import reactor.core.publisher.Mono;
32
33
34
35
36
37
38 public class AccessTokenAppender implements ExchangeFilterFunction {
39
40 private final AccessTokenProvider<Mono<String>> accessTokenProvider;
41
42
43
44
45
46
47 public AccessTokenAppender(AccessTokenProvider<Mono<String>> accessTokenProvider) {
48 Assert.notNull(accessTokenProvider, "Access token provider must be present.");
49 this.accessTokenProvider = accessTokenProvider;
50 }
51
52 @NonNull
53 @Override
54 public Mono<ClientResponse> filter(@NonNull ClientRequest request, @NonNull ExchangeFunction next) {
55 return accessTokenProvider.getAccessToken()
56 .switchIfEmpty(Mono.just(""))
57 .flatMap(tokenValue -> exchangeWithToken(request, tokenValue, next));
58 }
59
60 private Mono<ClientResponse> exchangeWithToken(
61 ClientRequest request,
62 String tokenValue,
63 ExchangeFunction next) {
64
65 if (StringUtils.hasText(tokenValue)) {
66 return next.exchange(ClientRequest
67 .from(request)
68 .headers(headers -> headers.set(HttpHeaders.AUTHORIZATION, "Bearer " + tokenValue))
69 .build());
70 } else {
71 return next.exchange(request);
72 }
73 }
74
75
76
77
78
79
80 public static AccessTokenAppender fromAuthentication() {
81 return new AccessTokenAppender(ReactiveAccessTokenProviders.fromAuthentication());
82 }
83
84
85
86
87
88
89
90 @SuppressWarnings("unused")
91 public static AccessTokenAppender withAccessTokenRetriever(
92 final AccessTokenRetrieverProperties properties) {
93 return new AccessTokenAppender(
94 ReactiveAccessTokenProviders.withAccessTokenRetriever(properties));
95 }
96
97
98
99
100
101
102
103
104 public static AccessTokenAppender withAccessTokenRetriever(
105 final AccessTokenRetriever<Mono<String>> retriever,
106 final AccessTokenRetrieverProperties properties) {
107 return new AccessTokenAppender(
108 ReactiveAccessTokenProviders.withAccessTokenRetriever(retriever, properties));
109 }
110
111 }