Showing posts with label jwt. Show all posts
Showing posts with label jwt. Show all posts

Tuesday, December 18, 2018

Firebase: Verify ID Token with Admin SDK in Java Backend Server

Halo geeks,

Kali ini saya akan membahas tentang implementasi Admin SDK - Verify ID Token untuk memeriksa apakah token yang dikirim oleh client app(android/iOS) sesuai dengan yang di-generate oleh Firebase atau telah dimanipulasi dari sisi client app.


PENGENALAN

Sebagai contoh, pada penerapan Google Sign-In pada client app, client app akan mengirimkan request menggunakan akun Gmail ke Firebase, yang kemudian client app mengambil ID Token yang berisi data terkait akun yang berhasil masuk dari GoogleSignInAccount objek, info pada ID Token ini yang kemudian akan diperiksa di backend server. 

Pada sisi client app, akan mengirim ID Token ke backend server melalui HTTPS POST request.
Untuk memastikan bahwa Token sesuai, dapat dipastikan dari beberapa poin ini:
  • ID Token memiliki signature yang diberikan oleh Google yang dapat diperiksa menggunakan Google Public Key (JWK atau PEM format).
  • aud pada ID Token harus sama dengan Project ID.
  • iss pada ID Token harus https://securetoken.google.com/<projectId> dimana <projectId> harus sama dengan aud
Pada sisi backend server, ID Token yang diterima akan diperiksa keasliannya dan mengambil uid dari token tersebut untuk mengidentifikasi user yang sedang mengakses aplikasi.

IMPLEMENTASI

Sebelum memulai, kita harus memiliki service account di firebase.

MENAMBAHKAN FIREBASE KE APLIKASI

Untuk menggunakan admin SDK, kita harus membuat Firebase Project terlebih dahulu yang akan digunakan untuk terhubung ke Firebase Service, dan file konfigurasi yang berisi credential akun project yang berformat JSON.
  1. Tambah Project baru di firebase jika belum ada, melalui halaman Firebase Console.
  2. Setelah berhasil menambahkan project baru, masuk halaman Service Account.
  3. Klik tombol Generate New Private Key pada bagian bawah Firebase Admin SDK.
Anda akan menerima file JSON yang berisi credential akun.


MENAMBAHKAN SDK

Tambahkan libary ke java backend server pada file pom.xml
<dependency>
  <groupId>com.google.firebase</groupId>
  <artifactId>firebase-admin</artifactId>
  <version>6.6.0</version>
</dependency>

INISIALISASI SDK

Pada bagian ini kita akan menginisialiasi SDK yang terdapat file JSON yang telah berhasil kita download dari firebase.

FileInputStream serviceAccount = new FileInputStream("path/to/serviceAccountKey.json");
FirebaseOptions options = new FirebaseOptions.Builder()
    .setCredentials(GoogleCredentials.fromStream(serviceAccount))
    .setDatabaseUrl("https://<DATABASE_NAME>.firebaseio.com/")
    .build();
FirebaseApp.initializeApp(options);
Note: database_name disesuaikan database yang pada Firebase Project.

VERIFIKASI ID TOKEN

Untuk memeriksa token dari akun yang sedang mengakses aplikasi, kita dapat menggunakan method verifyIdToken()yang telah tersedia di Admin SDK.
FirebaseToken decodedToken = FirebaseAuth.getInstance().verifyIdToken(idToken);
String uid = decodedToken.getUid();
untuk memeriksa ID Token, dibutuhkan project ID yang didapat dari field project_id pada file JSON tadi.

TAMBAHAN

Contoh file JSON yang berisik credential project pada firebase
json-firebase-credential

Contoh ID Token(JWT) yang diterima backend server dari clien app
{
 // These six fields are included in all Google ID Tokens.
 "iss": "https://accounts.google.com",
 "sub": "110169484474386276334",
 "azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
 "aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
 "iat": "1433978353",
 "exp": "1433981953",

 // These seven fields are only included when the user has granted the "profile" and
 // "email" OAuth scopes to the application.
 "email": "testuser@gmail.com",
 "email_verified": "true",
 "name" : "Test User",
 "picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg",
 "given_name": "Test",
 "family_name": "User",
 "locale": "en"
}

KESIMPULAN

Kita perlu melakukan verifikasi ID Token untuk memastikan bahwa user yang sedang mengakses aplikasi memang merupakan user yang asli/sah sehingga terhindar dari mallicious-ware yang dapat mencuri informasi dan menyebabkan kerugian baik sisi user maupun aplikasi.


Untuk kesalahan penulisan maupun pemahaman/konsep dapat ditambahkan pada kolom komentar.

Terimakasih.

sumber: firebase, google

Wednesday, June 15, 2016

Teori Implementasi JWT pada Spring Security

Bagaimana mengimplementasi JWT menggunakan Spring Security?


Setelah mempelajari JWT pada blog, saya mencoba untuk mengimplementasikan JWT menggunakan Spring Security. Google sana-sini, akhirnya berhasil juga. :)

Secara umum teori untuk dapat mengimplementasikan JWT pada Spring Security, kita memerlukan modul-modul :
  • spring-security-oauth2
  • <dependency>
       <groupId>org.springframework.security.oauth</groupId>
       <artifactId>spring-security-oauth2</artifactId>
       <version>2.0.9.RELEASE</version>
    </dependency>
  • spring-security-jwt
  • <dependency<
       <groupId>org.springframework.security</groupId>
       <artifactId>spring-security-jwt</artifactId>
       <version>1.0.4.RELEASE</version>
    </dependency>

Sedangkan untuk konfigurasi Authorization Server, minimal kita harus mengimplementasi interface berikut :
  • org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurer
  • Interface ini berguna untuk mengkonfigurasi dan mendefinisikan bean-bean yang dibutuhkan sebagai Authorization Server untuk meng-authentikasi Client Detail seperti :
    • AuthenticationManager
    • PasswordEncoder
    • ClientDetailsService
    • TokenStore
    • TokenEnhancer
    • AccessTokenConverter
    • dll
  • org.springframework.security.oauth2.provider.ClientDetailsService
  • Interface ini berguna untuk mendefinisikan Client Detail yang digunakan untuk Authorization Server.
  • org.springframework.security.core.userdetails.UserDetailsService
  • Interface ini berguna untuk mendefinisikan User yang digunakan untuk Authorization Server.
  • org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
  • Interface ini berguna untuk mengkonfigurasi dan mendefinisikan bean-bean yang dibutuhkan sebagai Authorization Server untuk meng-authentikasi User seperti :
    • AuthenticationManager
    • PasswordEncoder
    • UserDetailsService
    • HttpSecurity
    • dll

Apabila ingin menjadikan sebagai Resource Server, maka perlu mengimplementasi interface :
  • org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurer
  • Interface ini berguna untuk mengkonfigurasi dan mendefinisikan bean-bean yang dibutuhkan sebagai Resource Server untuk meng-authentikasi User seperti :
    • TokenStore
    • AccessTokenConverter
    • HttpSecurity
    • dll

Sekian sharing tentang JWT + Spring Security, pada blog selanjutnya saya akan share implementasi(source code) JWT pada Spring Security. Semoga bermanfaat. :)

JWT (JSON Web Token)

JSON Web Token atau lebih dikenal dengan JWT, merupakan sebuah token berbentuk JSON yang padat (ukurannya), informasi mandiri untuk ditransmisikan antar pihak yang terkait. Token tersebut ini dapat diverifikasi dan dipercaya karena sudah di-sign secara digital. Token JWT bisa di-sign dengan menggunakan secret (algoritma HMAC) atau pasangan public / private key (algoritma RSA).

Kenapa dibilang JSON yang padat ?, karena ukurannya yang kecil, token JWT dapat dikirim melalui URL, Parameter Http POST atau di dalam Header Http. Dan juga karena ukurannya yang kecil maka dapat ditransmisikan dengan lebih cepat.

Dan kenapa dibilang Informasi mandiri ?, karena isi dari tokennya mengandung informasi dari user yang dibutuhkan, sehingga tidak perlu query ke database lebih dari 1 kali.

Untuk lebih memperjelas mari kita lihat contoh tokennya :
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.EkN-DOsnsuRjRO6BxXemmJDm3HbxrbRzXglbN2S4sOkopdU4IsDxTI8jO19W_A4K8ZPJijNLis4EZsHeY559a4DFOd50_OqgHGuERTqYZyuhtF39yxJPAjUESwxk2J5k_4zM3O-vtd1Ghyo4IbqKKSy6J9mTniYJPenn5-HIirE
Pada contoh token tersebut terdapat 3 bagian yaitu :
  1. Header (Algoritma & Jenis Token)
  2. eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9
  3. Payload (Data)
  4. eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
  5. Signature (Verify Signature)
  6. EkN-DOsnsuRjRO6BxXemmJDm3HbxrbRzXglbN2S4sOkopdU4IsDxTI8jO19W_A4K8ZPJijNLis4EZsHeY559a4DFOd50_OqgHGuERTqYZyuhtF39yxJPAjUESwxk2J5k_4zM3O-vtd1Ghyo4IbqKKSy6J9mTniYJPenn5-HIirE
    Untuk lebih jelas, bisa cek ke https://jwt.io/#debugger dengan memasukan token seperti diatas.

Kapan sebaiknya kita menggunakan JWT ?


JWT umumnya digunakan untuk :
  • Autentikasi
  • Ketika user/client melakukan autentikasi dan mendapatkan token, maka untuk seterusnya setiap request harus menyertakan token tersebut.
  • Pertukaran Informasi
  • Dengan token yang sudah di-sign misal dengan algoritma RSA, kita dapat mengetahui dan yakin siapa yang melakukan request tersebut. Terlebih dengan isi pada bagian Signature merupakan gabungan dari isi Header dan Payload, jadi jika isi Header/Payload dirubah maka isi Signature menjadi tidak valid.

Bagaimana JWT bekerja ?


Umumnya ketika user berhasil melakukan login, maka server akan mengembalikan token JWT dan akan disimpan pada Local Storage / Cookies Browser. Selanjutnya untuk setiap request yang akan mengakses API yang terproteksi harus menyertakan token tersebut.

Umumnya token tersebut akan disertakan pada Authorization Header dengan Bearer schema, contohnya seperti ini :
Authorization: Bearer <token>

Ini merupakan mekanisme autentikasi yang stateless, karena state user yang login tidak disimpan pada memory server. Jadi setiap request kepada API yang terproteksi akan dicek apakah token JWT yang ada di Authorization header valid atau tidak, bila valid maka request akan diijinkan dan diproses.

Dan karena semua informasi yang dibutuhkan pada JWT sudah lengkap, maka setiap proses pengecekan tersebut sudah tidak perlu lagi melakukan query ke database.

Sekian sharing kali ini, semoga menambah wawasan kita semua. :)