github.com/phrase/openapi@v0.0.0-20240514140800-49e8a106740e/openapi-generator/templates/java/libraries/retrofit2/auth/OAuth.mustache (about)

     1  package {{invokerPackage}}.auth;
     2  
     3  import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
     4  import static java.net.HttpURLConnection.HTTP_FORBIDDEN;
     5  
     6  import java.io.IOException;
     7  import java.util.Map;
     8  
     9  import org.apache.oltu.oauth2.client.OAuthClient;
    10  import org.apache.oltu.oauth2.client.request.OAuthBearerClientRequest;
    11  import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
    12  import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder;
    13  import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder;
    14  import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse;
    15  import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
    16  import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
    17  import org.apache.oltu.oauth2.common.message.types.GrantType;
    18  import org.apache.oltu.oauth2.common.token.BasicOAuthToken;
    19  
    20  import okhttp3.Interceptor;
    21  import okhttp3.OkHttpClient;
    22  import okhttp3.Request;
    23  import okhttp3.Request.Builder;
    24  import okhttp3.Response;
    25  
    26  public class OAuth implements Interceptor {
    27  
    28      public interface AccessTokenListener {
    29          public void notify(BasicOAuthToken token);
    30      }
    31  
    32      private volatile String accessToken;
    33      private OAuthClient oauthClient;
    34  
    35      private TokenRequestBuilder tokenRequestBuilder;
    36      private AuthenticationRequestBuilder authenticationRequestBuilder;
    37  
    38      private AccessTokenListener accessTokenListener;
    39  
    40      public OAuth( OkHttpClient client, TokenRequestBuilder requestBuilder ) {
    41          this.oauthClient = new OAuthClient(new OAuthOkHttpClient(client));
    42          this.tokenRequestBuilder = requestBuilder;
    43      }
    44  
    45      public OAuth(TokenRequestBuilder requestBuilder ) {
    46          this(new OkHttpClient(), requestBuilder);
    47      }
    48  
    49      public OAuth(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) {
    50          this(OAuthClientRequest.tokenLocation(tokenUrl).setScope(scopes));
    51          setFlow(flow);
    52          authenticationRequestBuilder = OAuthClientRequest.authorizationLocation(authorizationUrl);
    53      }
    54  
    55      public void setFlow(OAuthFlow flow) {
    56          switch(flow) {
    57          case accessCode:
    58          case implicit:
    59              tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE);
    60              break;
    61          case password:
    62              tokenRequestBuilder.setGrantType(GrantType.PASSWORD);
    63              break;
    64          case application:
    65              tokenRequestBuilder.setGrantType(GrantType.CLIENT_CREDENTIALS);
    66              break;
    67          default:
    68              break;
    69          }            
    70      }
    71  
    72      @Override
    73      public Response intercept(Chain chain)
    74              throws IOException {
    75  
    76          return retryingIntercept(chain, true);
    77      }
    78  
    79      private Response retryingIntercept(Chain chain, boolean updateTokenAndRetryOnAuthorizationFailure) throws IOException {
    80          Request request = chain.request();
    81  
    82          // If the request already have an authorization (eg. Basic auth), do nothing
    83          if (request.header("Authorization") != null) {
    84              return chain.proceed(request);
    85          }
    86  
    87          // If first time, get the token
    88          OAuthClientRequest oAuthRequest;
    89          if (getAccessToken() == null) {
    90              updateAccessToken(null);
    91          }
    92  
    93          if (getAccessToken() != null) {
    94              // Build the request
    95              Builder rb = request.newBuilder();
    96  
    97              String requestAccessToken = new String(getAccessToken());
    98              try {
    99                  oAuthRequest = new OAuthBearerClientRequest(request.url().toString())
   100                          .setAccessToken(requestAccessToken)
   101                          .buildHeaderMessage();
   102              } catch (OAuthSystemException e) {
   103                  throw new IOException(e);
   104              }
   105  
   106              for ( Map.Entry<String, String> header : oAuthRequest.getHeaders().entrySet() ) {
   107                  rb.addHeader(header.getKey(), header.getValue());
   108              }
   109              rb.url( oAuthRequest.getLocationUri());
   110  
   111              //Execute the request
   112              Response response = chain.proceed(rb.build());
   113  
   114              // 401/403 most likely indicates that access token has expired. Unless it happens two times in a row.
   115              if ( response != null && (response.code() == HTTP_UNAUTHORIZED || response.code() == HTTP_FORBIDDEN) && updateTokenAndRetryOnAuthorizationFailure ) {
   116                  try {
   117                      if (updateAccessToken(requestAccessToken)) {
   118                          response.body().close();
   119                          return retryingIntercept( chain, false );
   120                      }
   121                  } catch (Exception e) {
   122                      response.body().close();
   123                      throw e;
   124                  }
   125              }
   126              return response;
   127          } else {
   128              return chain.proceed(chain.request());
   129          }
   130      }
   131  
   132      /*
   133       * Returns true if the access token has been updated
   134       */
   135      public synchronized boolean updateAccessToken(String requestAccessToken) throws IOException {
   136          if (getAccessToken() == null || getAccessToken().equals(requestAccessToken)) {    
   137              try {
   138                  OAuthJSONAccessTokenResponse accessTokenResponse = oauthClient.accessToken(this.tokenRequestBuilder.buildBodyMessage());
   139                  if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) {
   140                      setAccessToken(accessTokenResponse.getAccessToken());
   141                      if (accessTokenListener != null) {
   142                          accessTokenListener.notify((BasicOAuthToken) accessTokenResponse.getOAuthToken());
   143                      }
   144                      return !getAccessToken().equals(requestAccessToken);
   145                  } else {
   146                      return false;
   147                  }
   148              } catch (OAuthSystemException e) {
   149                  throw new IOException(e);
   150              } catch (OAuthProblemException e) {
   151                  throw new IOException(e);
   152              }
   153          }
   154          return true;
   155      }
   156  
   157      public void registerAccessTokenListener(AccessTokenListener accessTokenListener) {
   158          this.accessTokenListener = accessTokenListener;
   159      }
   160  
   161      public synchronized String getAccessToken() {
   162          return accessToken;
   163      }
   164  
   165      public synchronized void setAccessToken(String accessToken) {
   166          this.accessToken = accessToken;
   167      }
   168  
   169      public TokenRequestBuilder getTokenRequestBuilder() {
   170          return tokenRequestBuilder;
   171      }
   172  
   173      public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) {
   174          this.tokenRequestBuilder = tokenRequestBuilder;
   175      }
   176  
   177      public AuthenticationRequestBuilder getAuthenticationRequestBuilder() {
   178          return authenticationRequestBuilder;
   179      }
   180  
   181      public void setAuthenticationRequestBuilder(AuthenticationRequestBuilder authenticationRequestBuilder) {
   182          this.authenticationRequestBuilder = authenticationRequestBuilder;
   183      }
   184  
   185  }