All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.firebase.database.core.JvmAuthTokenProvider Maven / Gradle / Ivy

/*
 * Copyright 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.firebase.database.core;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.auth.oauth2.AccessToken;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.auth.oauth2.OAuth2Credentials;
import com.google.auth.oauth2.OAuth2Credentials.CredentialsChangedListener;
import com.google.firebase.FirebaseApp;
import com.google.firebase.ImplFirebaseTrampolines;
import com.google.firebase.database.util.GAuthToken;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.Executor;

public class JvmAuthTokenProvider implements AuthTokenProvider {

  private final GoogleCredentials credentials;
  private final Map authVariable;
  private final Executor executor;

  JvmAuthTokenProvider(FirebaseApp firebaseApp, Executor executor) {
    this(firebaseApp, executor, true);
  }

  JvmAuthTokenProvider(FirebaseApp firebaseApp, Executor executor, boolean autoRefresh) {
    this(firebaseApp, executor, autoRefresh, ImplFirebaseTrampolines.getCredentials(firebaseApp));
  }

  JvmAuthTokenProvider(FirebaseApp firebaseApp, Executor executor, boolean autoRefresh,
      GoogleCredentials customCredentials) {
    this.credentials = customCredentials;
    this.authVariable = firebaseApp.getOptions().getDatabaseAuthVariableOverride();
    this.executor = executor;
    if (autoRefresh) {
      ImplFirebaseTrampolines.startTokenRefresher(firebaseApp);
    }
  }

  @Override
  public void getToken(boolean forceRefresh, final GetTokenCompletionListener listener) {
    try {
      if (forceRefresh) {
        credentials.refresh();
      }

      // The typical way to use a GoogleCredentials instance is to call its getRequestMetadata(),
      // and include the metadata in your request. Since we are accessing the token directly via
      // getAccessToken(), we must first call getRequestMetadata() to ensure the token is available
      // (refreshed if necessary).
      credentials.getRequestMetadata();

      AccessToken accessToken = credentials.getAccessToken();
      listener.onSuccess(wrapOAuthToken(accessToken, authVariable));
    } catch (Exception e) {
      listener.onError(e.toString());
    }
  }

  @Override
  public void addTokenChangeListener(TokenChangeListener listener) {
    CredentialsChangedListener listenerWrapper = new TokenChangeListenerWrapper(
        listener, executor, authVariable);
    credentials.addChangeListener(listenerWrapper);
  }

  private static String wrapOAuthToken(AccessToken result, Map authVariable) {
    if (result == null) {
      // This shouldn't happen in the actual production SDK, but can happen in tests.
      return null;
    }

    GAuthToken googleAuthToken = new GAuthToken(result.getTokenValue(), authVariable);
    return googleAuthToken.serializeToString();
  }

  /**
   * Wraps a TokenChangeListener instance inside a CredentialsChangedListener. Equality
   * comparisons are delegated to the TokenChangeListener so that listener addition and removal will
   * work as expected.
   */
  private static class TokenChangeListenerWrapper implements CredentialsChangedListener {

    private final TokenChangeListener listener;
    private final Executor executor;
    private final Map authVariable;

    TokenChangeListenerWrapper(
        TokenChangeListener listener,
        Executor executor,
        Map authVariable) {
      this.listener = checkNotNull(listener, "Listener must not be null");
      this.executor = checkNotNull(executor, "Executor must not be null");
      this.authVariable = authVariable;
    }

    @Override
    public void onChanged(OAuth2Credentials credentials) throws IOException {
      // When this event fires, it is guaranteed that credentials.getAccessToken() will return a
      // valid OAuth2 token.
      final AccessToken accessToken = credentials.getAccessToken();

      // Notify the TokenChangeListener on database's thread pool to make sure that
      // all database work happens on database worker threads.
      executor.execute(
          new Runnable() {
            @Override
            public void run() {
              listener.onTokenChange(wrapOAuthToken(accessToken, authVariable));
            }
          });
    }

    @Override
    public int hashCode() {
      return listener.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
      return obj != null
          && obj instanceof TokenChangeListenerWrapper
          && ((TokenChangeListenerWrapper) obj).listener.equals(listener);
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy