View Javadoc
1   package com.guinetik.rr.auth;
2   
3   import com.guinetik.rr.http.RocketHeaders;
4   import java.util.function.BooleanSupplier;
5   
6   /**
7    * Authentication strategy that uses Bearer token authentication.
8    *
9    * <p>This strategy adds an {@code Authorization: Bearer <token>} header to all requests.
10   * It's suitable for APIs that use API keys, JWT tokens, or other bearer-style authentication.
11   *
12   * <h2>Basic Usage</h2>
13   * <pre class="language-java"><code>
14   * // Create via factory (recommended)
15   * AuthStrategy auth = AuthStrategyFactory.createBearerToken("my-api-token");
16   *
17   * // Configure client
18   * RocketRestConfig config = RocketRestConfig.builder("https://api.example.com")
19   *     .authStrategy(auth)
20   *     .build();
21   * </code></pre>
22   *
23   * <h2>With Custom Refresh Logic</h2>
24   * <p>For tokens that expire, you can provide custom refresh logic:
25   * <pre class="language-java"><code>
26   * AtomicReference&lt;String&gt; tokenRef = new AtomicReference&lt;&gt;("initial-token");
27   *
28   * AuthStrategy auth = AuthStrategyFactory.createBearerToken(tokenRef.get(), () -&gt; {
29   *     try {
30   *         String newToken = myAuthService.refreshToken();
31   *         tokenRef.set(newToken);
32   *         return true;
33   *     } catch (Exception e) {
34   *         return false;
35   *     }
36   * });
37   * </code></pre>
38   *
39   * <h2>For OAuth Tokens</h2>
40   * <p>If your bearer token comes from an OAuth flow, consider using the dedicated OAuth strategies
41   * which handle token refresh automatically:
42   * <ul>
43   *   <li>{@link OAuth2ClientCredentialsStrategy}</li>
44   *   <li>{@link OAuth2PasswordStrategy}</li>
45   *   <li>{@link OAuth2AssertionStrategy}</li>
46   * </ul>
47   *
48   * @author guinetik &lt;guinetik@gmail.com&gt;
49   * @see AuthStrategy
50   * @see AuthStrategyFactory#createBearerToken(String)
51   * @since 1.0.0
52   */
53  public class BearerTokenStrategy implements AuthStrategy {
54  
55      private final String token;
56      private final BooleanSupplier refreshTokenLogic;
57  
58      /**
59       * Creates a new BearerTokenStrategy with no custom refresh logic.
60       * In this case, {@link #refreshCredentials()} will always return {@code false}.
61       *
62       * @param token the bearer token
63       */
64      public BearerTokenStrategy(String token) {
65          this(token, () -> false);
66      }
67  
68      /**
69       * Creates a new BearerTokenStrategy with custom token refresh logic.
70       *
71       * @param token             the bearer token
72       * @param refreshTokenLogic a {@link BooleanSupplier} that will be invoked by {@link #refreshCredentials()}.
73       *                          It should return {@code true} if the token was successfully refreshed, {@code false} otherwise.
74       */
75      public BearerTokenStrategy(String token, BooleanSupplier refreshTokenLogic) {
76          this.token = token;
77          this.refreshTokenLogic = refreshTokenLogic != null ? refreshTokenLogic : () -> false;
78      }
79  
80      @Override
81      public AuthType getType() {
82          return AuthType.BEARER_TOKEN;
83      }
84  
85      @Override
86      public RocketHeaders applyAuthHeaders(RocketHeaders headers) {
87          if (token != null && !token.isEmpty()) {
88              headers.bearerAuth(token);
89          }
90          return headers;
91      }
92  
93      @Override
94      public boolean needsTokenRefresh() {
95          return false;
96      }
97  
98      /**
99       * {@inheritDoc}
100      * <p>
101      * If a custom {@code refreshTokenLogic} was provided during construction,
102      * this method will invoke it and return its result.
103      * <p>
104      * If no custom logic was provided, this method always returns {@code false},
105      * as this strategy itself does not handle credential refresh.
106      */
107     @Override
108     public boolean refreshCredentials() {
109         return this.refreshTokenLogic.getAsBoolean();
110     }
111 }