App Identity API untuk layanan paket lama

ID region

REGION_ID adalah kode singkat yang ditetapkan Google berdasarkan region yang Anda pilih saat membuat aplikasi. Kode ini tidak sesuai dengan negara atau provinsi, meskipun beberapa ID region mungkin tampak mirip dengan kode negara dan provinsi yang umum digunakan. Untuk aplikasi yang dibuat setelah Februari 2020, REGION_ID.r disertakan dalam URL App Engine. Untuk aplikasi lama yang dibuat sebelum tanggal tersebut, ID region bersifat opsional dalam URL.

Pelajari ID region lebih lanjut.

App Identity API memungkinkan aplikasi menemukan ID aplikasinya (juga disebut ID project). Dengan menggunakan ID ini, aplikasi App Engine dapat menegaskan identitasnya ke Aplikasi App Engine lainnya, Google API, serta aplikasi dan layanan pihak ketiga. ID aplikasi juga dapat digunakan untuk membuat URL atau alamat email, atau untuk membuat keputusan run-time.

Mendapatkan ID project

Project ID dapat ditemukan menggunakan metode ApiProxy.getCurrentEnvironment().getAppId().

Mendapatkan nama host aplikasi

Secara default, aplikasi App Engine disalurkan dari URL dalam bentuk https://PROJECT_ID.REGION_ID.r.appspot.com, dengan ID project merupakan bagian dari nama host. Jika aplikasi disajikan dari domain kustom, aplikasi tersebut mungkin perlu mengambil seluruh komponen nama host. Anda dapat melakukannya menggunakan atribut com.google.appengine.runtime.default_version_hostname dari CurrentEnvironment.

@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
  resp.setContentType("text/plain");
  ApiProxy.Environment env = ApiProxy.getCurrentEnvironment();
  resp.getWriter().print("default_version_hostname: ");
  resp.getWriter()
      .println(env.getAttributes().get("com.google.appengine.runtime.default_version_hostname"));
}

Menyatakan identitas ke aplikasi App Engine lainnya

Jika ingin menentukan identitas aplikasi App Engine yang membuat permintaan ke aplikasi App Engine Anda, Anda dapat menggunakan header permintaan X-Appengine-Inbound-Appid. Header ini ditambahkan ke permintaan oleh layanan URLFetch dan tidak dapat diubah oleh pengguna, sehingga dengn aman menunjukkan project ID aplikasi yang melakukan permintaan, jika ada.

Persyaratan:

  • Hanya panggilan yang dilakukan ke domain appspot.com aplikasi Anda yang akan berisi header X-Appengine-Inbound-Appid. Panggilan ke domain kustom tidak berisi header.
  • Permintaan Anda harus ditetapkan agar tidak mengikuti pengalihan. Jika Anda menggunakan class URLFetchService, aplikasi Anda harus menentukan doNotFollowRedirect. Aplikasi yang berjalan pada runtime Java 8 tidak menggunakan layanan URLFetch secara default. Untuk mengaktifkan URLFetch, ikuti petunjuk berikut.
  • Jika aplikasi Anda menggunakan java.net, perbarui kode agar tidak mengikuti pengalihan:
    connection.setInstanceFollowRedirects(false);

Di pengendali aplikasi, Anda dapat memeriksa ID masuk dengan membaca header X-Appengine-Inbound-Appid dan membandingkannya dengan daftar ID yang diizinkan untuk membuat permintaan.

Menyatakan identitas ke Google API

Google API menggunakan protokol OAuth 2.0 untuk autentikasi dan otorisasi. App Identity API dapat membuat token OAuth yang dapat digunakan untuk menyatakan bahwa sumber permintaan adalah aplikasi itu sendiri. Metode getAccessToken() menampilkan token akses untuk cakupan, atau daftar cakupan. Token ini kemudian dapat ditetapkan dalam header HTTP panggilan untuk mengidentifikasi aplikasi panggilan.

Contoh berikut menunjukkan cara menggunakan App Identity API untuk melakukan panggilan REST ke Google URL Shortener API.

/**
 * Returns a shortened URL by calling the Google URL Shortener API.
 *
 * <p>Note: Error handling elided for simplicity.
 */
public String createShortUrl(String longUrl) throws Exception {
  ArrayList<String> scopes = new ArrayList<>();
  scopes.add("https://www.googleapis.com/auth/urlshortener");
  final AppIdentityService appIdentity = AppIdentityServiceFactory.getAppIdentityService();
  final AppIdentityService.GetAccessTokenResult accessToken = appIdentity.getAccessToken(scopes);
  // The token asserts the identity reported by appIdentity.getServiceAccountName()
  JSONObject request = new JSONObject();
  request.put("longUrl", longUrl);

  URL url = new URL("https://www.googleapis.com/urlshortener/v1/url?pp=1");
  HttpURLConnection connection = (HttpURLConnection) url.openConnection();
  connection.setDoOutput(true);
  connection.setRequestMethod("POST");
  connection.addRequestProperty("Content-Type", "application/json");
  connection.addRequestProperty("Authorization", "Bearer " + accessToken.getAccessToken());

  OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
  request.write(writer);
  writer.close();

  if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
    // Note: Should check the content-encoding.
    //       Any JSON parser can be used; this one is used for illustrative purposes.
    JSONTokener responseTokens = new JSONTokener(connection.getInputStream());
    JSONObject response = new JSONObject(responseTokens);
    return (String) response.get("id");
  } else {
    try (InputStream s = connection.getErrorStream();
        InputStreamReader r = new InputStreamReader(s, StandardCharsets.UTF_8)) {
      throw new RuntimeException(
          String.format(
              "got error (%d) response %s from %s",
              connection.getResponseCode(), CharStreams.toString(r), connection.toString()));
    }
  }
}

Perlu diperhatikan bahwa identitas aplikasi direpresentasikan oleh nama akun layanan, yang biasanya adalah applicationid@appspot.gserviceaccount.com. Anda bisa mendapatkan nilai yang tepat menggunakan metode getServiceAccountName(). Untuk layanan yang menawarkan ACL, Anda dapat memberikan akses aplikasi dengan memberikan akses akun ini.

Menyatakan identitas ke layanan pihak ketiga

Token yang dibuat oleh getAccessToken() hanya berfungsi pada layanan Google. Namun, Anda bisa menggunakan teknologi penandatanganan yang mendasarinya untuk menegaskan identitas aplikasi Anda ke layanan lain. Metode signForApp() akan menandatangani byte menggunakan kunci pribadi yang unik untuk aplikasi Anda, dan metode getPublicCertificatesForApp() akan menampilkan sertifikat yang dapat digunakan untuk memvalidasi tanda tangan.

Berikut adalah contoh yang menunjukkan cara menandatangani blob dan memvalidasi tanda tangannya:
// Note that the algorithm used by AppIdentity.signForApp() and
// getPublicCertificatesForApp() is "SHA256withRSA"

private byte[] signBlob(byte[] blob) {
  AppIdentityService.SigningResult result = appIdentity.signForApp(blob);
  return result.getSignature();
}

private byte[] getPublicCertificate() throws UnsupportedEncodingException {
  Collection<PublicCertificate> certs = appIdentity.getPublicCertificatesForApp();
  PublicCertificate publicCert = certs.iterator().next();
  return publicCert.getX509CertificateInPemFormat().getBytes("UTF-8");
}

private Certificate parsePublicCertificate(byte[] publicCert)
    throws CertificateException, NoSuchAlgorithmException {
  InputStream stream = new ByteArrayInputStream(publicCert);
  CertificateFactory cf = CertificateFactory.getInstance("X.509");
  return cf.generateCertificate(stream);
}

private boolean verifySignature(byte[] blob, byte[] blobSignature, PublicKey pk)
    throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
  Signature signature = Signature.getInstance("SHA256withRSA");
  signature.initVerify(pk);
  signature.update(blob);
  return signature.verify(blobSignature);
}

private String simulateIdentityAssertion()
    throws CertificateException, UnsupportedEncodingException, NoSuchAlgorithmException,
    InvalidKeyException, SignatureException {
  // Simulate the sending app.
  String message = "abcdefg " + Calendar.getInstance().getTime().toString();
  byte[] blob = message.getBytes();
  byte[] blobSignature = signBlob(blob);
  byte[] publicCert = getPublicCertificate();

  // Simulate the receiving app, which gets the certificate, blob, and signature.
  Certificate cert = parsePublicCertificate(publicCert);
  PublicKey pk = cert.getPublicKey();
  boolean isValid = verifySignature(blob, blobSignature, pk);

  return String.format(
      "isValid=%b for message: %s\n\tsignature: %s\n\tpublic cert: %s",
      isValid, message, Arrays.toString(blobSignature), Arrays.toString(publicCert));
}

Mendapatkan nama Bucket Cloud Storage default

Setiap aplikasi dapat memiliki satu bucket Cloud Storage default, yang mencakup penyimpanan gratis 5 GB dan kuota gratis untuk operasi I/O.

Untuk mendapatkan nama bucket default, Anda dapat menggunakan App Identity API. Panggil AppIdentityService.getDefaultGcsBucketName.