Mengautentikasi pengguna dengan Identity-Aware Proxy untuk Ruby

Aplikasi yang berjalan di platform terkelola seperti App Engine dapat menghindari pengelolaan autentikasi pengguna dan pengelolaan sesi dengan menggunakan Identity-Aware Proxy (IAP) untuk mengontrol akses ke aplikasi tersebut. Google Cloud IAP tidak hanya dapat mengontrol akses ke aplikasi, tetapi juga memberikan informasi tentang pengguna yang diautentikasi, termasuk alamat email dan ID persisten ke aplikasi dalam bentuk header HTTP baru.

Tujuan

  • Mewajibkan pengguna aplikasi App Engine Anda untuk mengautentikasi diri mereka sendiri dengan menggunakan IAP.

  • Akses identitas pengguna di aplikasi untuk menampilkan alamat email terautentikasi pengguna saat ini.

Biaya

Dalam dokumen ini, Anda akan menggunakan komponen Google Cloudyang dapat ditagih berikut:

Untuk membuat perkiraan biaya berdasarkan proyeksi penggunaan Anda, gunakan kalkulator harga.

Pengguna Google Cloud baru mungkin memenuhi syarat untuk mendapatkan uji coba gratis.

Setelah menyelesaikan tugas yang dijelaskan dalam dokumen ini, Anda dapat menghindari penagihan berkelanjutan dengan menghapus resource yang Anda buat. Untuk mengetahui informasi selengkapnya, baca bagian Pembersihan.

Sebelum memulai

  1. Login ke akun Google Cloud Anda. Jika Anda baru menggunakan Google Cloud, buat akun untuk mengevaluasi performa produk kami dalam skenario dunia nyata. Pelanggan baru juga mendapatkan kredit gratis senilai $300 untuk menjalankan, menguji, dan men-deploy workload.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  5. Verify that billing is enabled for your Google Cloud project.

  6. Siapkan lingkungan pengembangan Anda.

Latar belakang

Tutorial ini menggunakan IAP untuk mengautentikasi pengguna. Ini hanyalah salah satu dari beberapa kemungkinan pendekatan. Untuk mempelajari lebih lanjut berbagai metode untuk mengautentikasi pengguna, lihat bagian Konsep autentikasi.

Aplikasi Hello user-email-address

Aplikasi untuk tutorial ini adalah aplikasi App Engine Hello world minimal, dengan satu fitur yang tidak biasa: alih-alih "Hello world", aplikasi ini menampilkan "Hello user-email-address", dengan user-email-address adalah alamat email pengguna yang diautentikasi.

Fungsi ini dapat dilakukan dengan memeriksa informasi terautentikasi yang ditambahkan IAP ke setiap permintaan web yang diteruskan ke aplikasi Anda. Ada tiga header permintaan baru yang ditambahkan ke setiap permintaan web yang mencapai aplikasi Anda. Dua header pertama adalah string teks biasa yang dapat Anda gunakan untuk mengidentifikasi pengguna. Header ketiga adalah objek yang ditandatangani secara kriptografis dengan informasi yang sama.

  • X-Goog-Authenticated-User-Email: Alamat email pengguna mengidentifikasi pengguna tersebut. Jangan menyimpan informasi pribadi jika aplikasi Anda dapat menghindarinya. Aplikasi ini tidak menyimpan data apa pun; aplikasi ini hanya mengembalikan data tersebut kepada pengguna.

  • X-Goog-Authenticated-User-Id: ID pengguna yang ditetapkan oleh Google ini tidak menampilkan informasi tentang pengguna, tetapi memungkinkan aplikasi mengetahui bahwa pengguna yang login adalah pengguna yang sama dengan yang sebelumnya terlihat.

  • X-Goog-Iap-Jwt-Assertion: Anda dapat mengonfigurasi aplikasi Google Cloud untuk menerima permintaan web dari aplikasi cloud lain, dengan melewati IAP, selain permintaan web internet. Jika aplikasi dikonfigurasi demikian, permintaan tersebut dapat memiliki header palsu. Daripada menggunakan salah satu header teks biasa yang disebutkan sebelumnya, Anda dapat menggunakan dan memverifikasi header yang ditandatangani secara kriptografis ini untuk memeriksa apakah informasi diberikan oleh Google. Alamat email pengguna dan ID pengguna persisten tersedia sebagai bagian dari header yang ditandatangani ini.

Jika Anda yakin bahwa aplikasi dikonfigurasi sehingga hanya permintaan web internet yang dapat menjangkaunya, dan tidak ada yang dapat menonaktifkan layanan IAP untuk aplikasi tersebut, maka pengambilan ID pengguna unik hanya memerlukan satu baris kode:

user_id = request.env["HTTP_X_GOOG_AUTHENTICATED_USER_ID"]

Namun, aplikasi yang tangguh harus mengantisipasi terjadinya kesalahan, termasuk masalah konfigurasi atau lingkungan yang tidak terduga, jadi kami merekomendasikan pembuatan fungsi yang menggunakan dan memverifikasi header yang ditandatangani secara kriptografis. Tanda tangan header tersebut tidak dapat dipalsukan, dan jika diverifikasi, dapat digunakan untuk menampilkan identifikasi.

Buat kode sumber

  1. Gunakan editor teks untuk membuat file bernama app.rb, lalu tempelkan kode berikut di dalamnya:

    require "base64"
    require "json"
    require "jwt"
    require "net/http"
    require "openssl"
    require "sinatra"
    require "uri"
    
    def certificates
      uri = URI.parse "https://www.gstatic.com/iap/verify/public_key"
      response = Net::HTTP.get_response uri
      JSON.parse response.body
    end
    
    set :certificates, certificates
    
    def get_metadata item_name
      endpoint = "http://metadata.google.internal"
      path = "/computeMetadata/v1/project/#{item_name}"
      uri = URI.parse endpoint + path
    
      http = Net::HTTP.new uri.host, uri.port
      request = Net::HTTP::Get.new uri.request_uri
      request["Metadata-Flavor"] = "Google"
      response = http.request request
      response.body
    end
    
    def audience
      project_number = get_metadata "numeric-project-id"
      project_id = get_metadata "project-id"
      "/projects/#{project_number}/apps/#{project_id}"
    end
    
    set :audience, audience
    
    def validate_assertion assertion
      a_header = Base64.decode64 assertion.split(".")[0]
      key_id = JSON.parse(a_header)["kid"]
      cert = OpenSSL::PKey::EC.new settings.certificates[key_id]
      info = JWT.decode assertion, cert, true, algorithm: "ES256", aud: settings.audience
      [info[0]["email"], info[0]["sub"]]
    rescue StandardError => e
      puts "Failed to validate assertion: #{e}"
      [nil, nil]
    end
    
    get "/" do
      assertion = request.env["HTTP_X_GOOG_IAP_JWT_ASSERTION"]
      email, _user_id = validate_assertion assertion
      "<h1>Hello #{email}</h1>"
    end

    File app.rb ini dijelaskan secara mendetail di bagian Memahami kode di bagian selanjutnya dalam tutorial ini.

  2. Di jendela terminal, buka folder yang sama dengan app.rb yang baru saja Anda buat, lalu jalankan bundle init.

  3. Tambahkan kode berikut ke Gemfile yang dihasilkan:

    gem "jwt", "~> 2.2"
    gem "sinatra", "~> 2.0"

    Gemfile mencantumkan library Ruby non-standar yang dibutuhkan aplikasi Anda App Engine untuk dimuat:

    • Sinatra adalah framework web ruby yang digunakan untuk aplikasi.

    • jwt menyediakan metode pemeriksaan dan decoding JWT.

  4. Instal dependensi yang tercantum dalam Gemfile:

    bundle install
    
  5. Buat file bernama app.yaml dan tempelkan teks berikut di dalamnya:

    runtime: ruby25
    entrypoint: bundle exec ruby app.rb

    File app.yaml memberi tahu App Engine lingkungan bahasa yang diperlukan kode Anda.

Memahami kode

Bagian ini menjelaskan cara kerja kode dalam file app.rb. Jika hanya ingin menjalankan aplikasi, Anda dapat langsung membuka bagian Deploy aplikasi.

  • Saat aplikasi menerima HTTP GET permintaan ke halaman beranda, Sinatra akan mengeksekusi blok berikut:

    get "/" do
      assertion = request.env["HTTP_X_GOOG_IAP_JWT_ASSERTION"]
      email, _user_id = validate_assertion assertion
      "<h1>Hello #{email}</h1>"
    end
  • Blok ini mendapatkan nilai header pernyataan JWT yang ditambahkan IAP dari permintaan masuk dan memanggil metode untuk memvalidasi nilai yang ditandatangani secara kriptografis tersebut. Nilai pertama yang ditampilkan (email) kemudian digunakan di halaman web minimal yang dibuat Sinatra.

    def validate_assertion assertion
      a_header = Base64.decode64 assertion.split(".")[0]
      key_id = JSON.parse(a_header)["kid"]
      cert = OpenSSL::PKey::EC.new settings.certificates[key_id]
      info = JWT.decode assertion, cert, true, algorithm: "ES256", aud: settings.audience
      [info[0]["email"], info[0]["sub"]]
    rescue StandardError => e
      puts "Failed to validate assertion: #{e}"
      [nil, nil]
    end
  • Metode validate_assertion menggunakan metode JWT.decode dari library jwt pihak ketiga untuk memverifikasi bahwa pernyataan ditandatangani dengan benar, dan untuk mengekstrak informasi payload dari pernyataan. Informasi tersebut adalah alamat email pengguna yang diautentikasi dan ID unik persisten untuk pengguna. Jika pernyataan tidak dapat didekode, metode ini akan menampilkan nil untuk setiap nilai tersebut dan mencetak pesan untuk mencatat error.

  • Memvalidasi pernyataan JWT memerlukan pengetahuan tentang sertifikat kunci publik entitas yang menandatangani pernyataan (Google dalam hal ini), dan audiens yang dituju oleh pernyataan tersebut. Untuk aplikasi App Engine, audiens adalah string dengan Google Cloud informasi identifikasi project di dalamnya. Metode ini mendapatkan sertifikat tersebut dan string audiens dari metode sebelumnya.

    def audience
      project_number = get_metadata "numeric-project-id"
      project_id = get_metadata "project-id"
      "/projects/#{project_number}/apps/#{project_id}"
    end
    
    set :audience, audience
  • Anda dapat mencari ID dan nama numerik project, lalu memasukkan nilai tersebut ke dalam kode sumber sendiri, tetapi metode audience melakukannya untuk Anda dengan mengkueri layanan metadata standar yang tersedia untuk setiap aplikasi App Engine. Karena layanan metadata bersifat eksternal terhadap kode aplikasi, hasil tersebut disimpan ke objek settings framework Sinatra. Google Cloud

    def get_metadata item_name
      endpoint = "http://metadata.google.internal"
      path = "/computeMetadata/v1/project/#{item_name}"
      uri = URI.parse endpoint + path
    
      http = Net::HTTP.new uri.host, uri.port
      request = Net::HTTP::Get.new uri.request_uri
      request["Metadata-Flavor"] = "Google"
      response = http.request request
      response.body
    end
  • Layanan metadata App Engine (dan layanan metadata serupa untuk layanan komputasiGoogle Cloud lainnya) terlihat seperti situs web dan dikueri oleh kueri web standar. Namun, sebenarnya bukan situs eksternal, melainkan fitur internal yang menampilkan informasi yang diminta tentang aplikasi yang sedang berjalan, sehingga aman untuk menggunakan permintaan http, bukan https. Di sini, layanan metadata App Engine digunakan untuk mendapatkan Google Cloud ID saat ini yang diperlukan untuk menentukan audiens yang dituju pernyataan JWT.

    def certificates
      uri = URI.parse "https://www.gstatic.com/iap/verify/public_key"
      response = Net::HTTP.get_response uri
      JSON.parse response.body
    end
    
    set :certificates, certificates
  • Verifikasi tanda tangan digital memerlukan sertifikat kunci publik penanda tangan. Google menyediakan situs yang menampilkan semua sertifikat kunci publik yang saat ini digunakan. Hasil ini di-cache jika diperlukan lagi dalam instance aplikasi yang sama.

Men-deploy aplikasi

Sekarang Anda dapat men-deploy aplikasi, lalu mengaktifkan IAP untuk mewajibkan pengguna mengautentikasi diri sebelum dapat mengakses aplikasi.

  1. Di jendela terminal, buka direktori yang berisi file app.yaml, lalu deploy aplikasi ke App Engine:

    gcloud app deploy
    
  2. Jika diminta, pilih wilayah di sekitar.

  3. Saat ditanya apakah Anda ingin melanjutkan operasi deployment, tekan Y.

    Dalam beberapa menit, aplikasi Anda akan ditayangkan di internet.

  4. Melihat aplikasi:

    gcloud app browse
    

    Di output, salin web-site-url, alamat web untuk aplikasi.

  5. Di jendela browser, tempel web-site-url untuk membuka aplikasi.

    Tidak ada email yang ditampilkan karena Anda belum menggunakan IAP, sehingga tidak ada informasi pengguna yang dikirim ke aplikasi.

Mengaktifkan IAP

Setelah instance App Engine ada, Anda dapat melindunginya dengan IAP:

  1. Di konsol Google Cloud , buka halaman Identity-Aware Proxy.

    Buka halaman Identity-Aware Proxy

  2. Karena ini pertama kalinya Anda mengaktifkan opsi autentikasi untuk project ini, Anda akan melihat pesan bahwa Anda harus mengonfigurasi layar izin OAuth sebelum dapat menggunakan IAP.

    Klik Konfigurasi Layar Persetujuan.

  3. Pada tab Layar Izin OAuth di halaman Kredensial, lengkapi kolom berikut:

    • Jika akun Anda berada di organisasi Google Workspace, pilih Eksternal lalu klik Buat. Untuk memulai, aplikasi hanya akan tersedia bagi pengguna yang Anda izinkan secara eksplisit.

    • Di kolom Nama aplikasi, masukkan IAP Example.

    • Di kolom Email dukungan, masukkan alamat email Anda.

    • Di kolom Authorized domain, masukkan bagian nama host dari URL aplikasi, misalnya, iap-example-999999.uc.r.appspot.com. Tekan tombol Enter setelah memasukkan nama host di kolom.

    • Di kolom Link halaman beranda aplikasi, masukkan URL aplikasi Anda, misalnya, https://iap-example-999999.uc.r.appspot.com/.

    • Di kolom Baris kebijakan privasi aplikasi, gunakan URL yang sama dengan link halaman beranda untuk tujuan pengujian.

  4. Klik Simpan. Saat diminta untuk membuat kredensial, Anda dapat menutup jendela.

  5. Di konsol Google Cloud , buka halaman Identity-Aware Proxy.

    Buka halaman Identity-Aware Proxy

  6. Untuk memuat ulang halaman, klik Muat ulang . Halaman ini menampilkan daftar resource yang dapat Anda lindungi.

  7. Di kolom IAP, klik untuk mengaktifkan IAP bagi aplikasi.

  8. Di browser Anda, buka web-site-url lagi.

  9. Bukan halaman web, layar login muncul untuk mengautentikasi diri Anda. Saat login, Anda ditolak aksesnya karena IAP tidak memiliki daftar pengguna yang diizinkan untuk mengakses aplikasi.

Menambahkan pengguna yang diberi otorisasi ke aplikasi

  1. Di Konsol Google Cloud , buka halaman Identity-Aware Proxy.

    Buka halaman Identity-Aware Proxy

  2. Centang kotak untuk aplikasi App Engine, lalu klik Add Principal.

  3. Masukkan allAuthenticatedUsers, lalu pilih peran Cloud IAP/IAP-Secured Web App User.

  4. Klik Simpan.

Sekarang, setiap pengguna yang dapat diautentikasi oleh Google dapat mengakses aplikasi. Jika mau, Anda dapat membatasi akses lebih lanjut dengan hanya menambahkan satu atau beberapa orang atau grup sebagai prinsipal:

  • Alamat email Gmail atau Google Workspace apa pun

  • Alamat email Google Grup

  • Nama domain Google Workspace

Mengakses aplikasi

  1. Di browser Anda, buka web-site-url.

  2. Untuk memuat ulang halaman, klik Muat ulang .

  3. Di layar login, login dengan kredensial Google Anda.

    Halaman menampilkan halaman "Hello user-email-address" dengan alamat email Anda.

    Jika Anda masih melihat halaman yang sama seperti sebelumnya, mungkin ada masalah dengan browser yang tidak sepenuhnya memperbarui permintaan baru setelah Anda mengaktifkan IAP. Tutup semua jendela browser, buka kembali, lalu coba lagi.

Konsep autentikasi

Ada beberapa cara agar aplikasi dapat mengautentikasi penggunanya dan membatasi akses hanya untuk pengguna yang diberi otorisasi. Metode autentikasi umum, dalam tingkat upaya yang menurun untuk aplikasi, tercantum di bagian berikut.

Opsi Kelebihan Kekurangan
Autentikasi aplikasi
  • Aplikasi dapat berjalan di platform apa pun, dengan atau tanpa koneksi internet
  • Pengguna tidak perlu menggunakan layanan lain untuk mengelola autentikasi
  • Aplikasi harus mengelola kredensial pengguna dengan aman, melindungi dari pengungkapan
  • Aplikasi harus mempertahankan data sesi untuk pengguna yang login
  • Aplikasi harus menyediakan pendaftaran pengguna, perubahan sandi, pemulihan sandi
OAuth2
  • Aplikasi dapat berjalan di platform yang terhubung ke internet, termasuk workstation developer
  • Aplikasi tidak memerlukan pendaftaran pengguna, perubahan sandi, atau fungsi pemulihan sandi.
  • Risiko pengungkapan informasi pengguna didelegasikan ke layanan lain
  • Langkah-langkah keamanan login baru yang ditangani di luar aplikasi
  • Pengguna harus mendaftar ke layanan identitas
  • Aplikasi harus mempertahankan data sesi untuk pengguna yang login
IAP
  • Aplikasi tidak perlu memiliki kode apa pun untuk mengelola pengguna, otentikasi, atau status sesi
  • Aplikasi tidak memiliki kredensial pengguna yang mungkin dilanggar
  • Aplikasi hanya dapat berjalan di platform yang didukung oleh layanan. Secara khusus, layanan Google Cloud tertentu yang mendukung IAP, seperti App Engine.

Autentikasi yang dikelola aplikasi

Dengan metode ini, aplikasi mengelola sendiri setiap aspek autentikasi pengguna. Aplikasi harus mengelola database kredensial pengguna sendiri dan mengelola sesi pengguna, serta harus menyediakan fungsi untuk mengelola akun dan sandi pengguna, memeriksa kredensial pengguna, serta mengeluarkan, memeriksa, dan memperbarui sesi pengguna dengan setiap login yang diautentikasi. Diagram berikut menggambarkan metode autentikasi yang dikelola aplikasi.

Alur yang dikelola aplikasi

Seperti yang ditunjukkan dalam diagram, setelah pengguna login, aplikasi akan membuat dan mempertahankan informasi tentang sesi pengguna. Saat pengguna membuat permintaan ke aplikasi, permintaan harus menyertakan informasi sesi yang menjadi tanggung jawab aplikasi untuk memverifikasinya.

Keuntungan utama pendekatan ini adalah pendekatan ini mandiri dan berada di bawah kontrol aplikasi. Aplikasi bahkan tidak perlu tersedia di internet. Kerugian utamanya adalah aplikasi kini bertanggung jawab untuk menyediakan semua fungsi pengelolaan akun dan melindungi semua data kredensial sensitif.

Autentikasi eksternal dengan OAuth2

Alternatif yang baik untuk menangani semuanya dalam aplikasi adalah dengan menggunakan layanan identitas eksternal, seperti Google, yang menangani semua informasi dan fungsi akun pengguna serta bertanggung jawab untuk mengamankan kredensial sensitif. Saat pengguna mencoba login ke aplikasi, permintaan akan dialihkan ke layanan identitas, yang akan mengautentikasi pengguna dan kemudian mengalihkan permintaan kembali ke aplikasi dengan informasi autentikasi yang diperlukan. Untuk mengetahui informasi selengkapnya, lihat Menggunakan OAuth 2.0 untuk Aplikasi Server Web.

Diagram berikut mengilustrasikan autentikasi eksternal dengan metode OAuth2.

Alur OAuth2

Alur dalam diagram dimulai saat pengguna mengirim permintaan untuk mengakses aplikasi. Alih-alih merespons secara langsung, aplikasi mengalihkan browser pengguna ke platform identitas Google, yang menampilkan halaman untuk login ke Google. Setelah berhasil login, browser pengguna akan diarahkan kembali ke aplikasi. Permintaan ini mencakup informasi yang dapat digunakan aplikasi untuk mencari informasi tentang pengguna yang kini diautentikasi, dan aplikasi kini merespons pengguna.

Metode ini memiliki banyak keuntungan bagi aplikasi. Metode ini mendelegasikan semua fungsi dan risiko pengelolaan akun ke layanan eksternal, yang dapat meningkatkan keamanan login dan akun tanpa perlu mengubah aplikasi. Namun, seperti yang ditunjukkan dalam diagram sebelumnya, aplikasi harus memiliki akses ke internet untuk menggunakan metode ini. Aplikasi juga bertanggung jawab untuk mengelola sesi setelah pengguna diautentikasi.

Identity-Aware Proxy

Pendekatan ketiga, yang dibahas dalam tutorial ini, adalah menggunakan IAP untuk menangani semua autentikasi dan pengelolaan sesi dengan perubahan apa pun pada aplikasi. IAP mencegat semua permintaan web ke aplikasi Anda, memblokir permintaan yang belum diautentikasi, dan meneruskan permintaan lainnya dengan data identitas pengguna yang ditambahkan ke setiap permintaan.

Penanganan permintaan ditampilkan dalam diagram berikut.

Alur IAP

Permintaan dari pengguna dicegat oleh IAP, yang memblokir permintaan yang tidak diautentikasi. Permintaan yang diautentikasi diteruskan ke aplikasi, asalkan pengguna yang diautentikasi ada dalam daftar pengguna yang diizinkan. Permintaan yang diteruskan melalui IAP memiliki header yang ditambahkan ke permintaan tersebut untuk mengidentifikasi pengguna yang membuat permintaan.

Aplikasi tidak perlu lagi menangani informasi akun atau sesi pengguna. Setiap operasi yang perlu mengetahui ID unik untuk pengguna dapat memperolehnya langsung dari setiap permintaan web yang masuk. Namun, hal ini hanya dapat digunakan untuk layanan komputasi yang mendukung IAP, seperti App Engine dan load balancer. Anda tidak dapat menggunakan IAP di komputer pengembangan lokal.

Pembersihan

Agar tidak perlu membayar biaya pada akun Google Cloud Anda untuk resource yang digunakan dalam tutorial ini, hapus project yang berisi resource tersebut, atau simpan project dan hapus setiap resource.

  1. Di Konsol Google Cloud , buka halaman Manage resources.

    Buka Kelola resource

  2. Pada daftar project, pilih project yang ingin Anda hapus, lalu klik Delete.
  3. Pada dialog, ketik project ID, lalu klik Shut down untuk menghapus project.