JSON Web Key Set là một tập hợp các public key JSON Web Key được cung cấp bởi Authorization Server, để cho Resource Server có thể verify access token được gửi bởi Client Application. Trong bài viết về Hiện thực OAuth Authorization Server sử dụng Spring Authorization Server, mình đã hướng dẫn các bạn cách định nghĩa JSON Web Key này sử dụng code. Thế nhưng cho các ứng dụng chạy trên production, vì vấn đề bảo mật, thông tin JSON Web Key thường sẽ được một bên khác quản lý, có thể là IT team. Họ sẽ generate một tập tin keystore, nhiệm vụ của chúng ta là sử dụng tập tin keystore này để định nghĩa JSON Web Key Set. Trong bài viết này, mình sẽ hướng dẫn các bạn cách định nghĩa JSON Web Key Set cho Authorization Server sử dụng Spring Authorization Server và tập tin PKCS12 key store các bạn nhé!
Đầu tiên, mình sẽ generate một tập tin keystore với định dạng PKCS12 để làm ví dụ.
Kết quả như sau:
Thông thường chúng ta sẽ expose biến môi trường trỏ đến đường dẫn của tập tin .pfx để cho IT team họ cấu hình. Nhưng để đơn giản trong bài viết này, mình sẽ để tập tin .pfx này vào thư mục src/main/resources của project ví dụ trong bài viết Hiện thực OAuth Authorization Server sử dụng Spring Authorization Server:
Chúng ta sẽ khởi tạo đối tượng KeyStore của Java Security để hold thông tin của tập tin .pfx như sau:
1 |
KeyStore keyStore = KeyStore.getInstance("pkcs12"); |
Có nhiều phương thức overload của phương thức getInstance() mà các bạn có thể sử dụng. Ở đây, mình đang sử dụng getInstance() với tham số là type của keystore file. Các bạn có thể xem tất cả các keystore type mà Java hỗ trợ ở đây.
Nếu các bạn sử dụng password để bảo vệ tập tin keystore thì có thể lấy nội dung của tập tin keystore như sau:
1 2 3 |
try (FileInputStream fis = new FileInputStream("src/main/resources/huongdanjava.pfx")) { keyStore.load(fis, "123456".toCharArray()); } |
123456 là password của tập tin keystore.
Sau khi đã load nội dung tập tin keystore thì các bạn có thể convert nội dung này qua đối tượng JWKSet của thư viện Nimbus, thư viện mà mà Spring Authorization Server đang sử dụng để làm việc với access token, như sau:
1 2 3 4 5 6 |
JWKSet jwkSet = JWKSet.load(keyStore, new PasswordLookup() { @Override public char[] lookupPassword(String name) { return "123456".toCharArray(); } }); |
Khi convert nội dung tập tin keystore qua đối tượng JWKSet, chúng ta cần truyền thông tin password của private key. Với keystore type PKCS12 thì password của private key giống với password của tập tin keystore các bạn nhé!
Toàn bộ nội dung thức build thông tin đối tượng JWKSet của mình như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
private JWKSet buildJWKSet() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException { KeyStore keyStore = KeyStore.getInstance("pkcs12"); try (FileInputStream fis = new FileInputStream("src/main/resources/huongdanjava.pfx")) { keyStore.load(fis, "123456".toCharArray()); return JWKSet.load(keyStore, new PasswordLookup() { @Override public char[] lookupPassword(String name) { return "123456".toCharArray(); } }); } } |
Các bạn có thể sử dụng phương thức này khi việc xây dựng Authorization Server sử dụng Spring Authorization Server như mình! Khai báo cho đối tượng JWKSource lúc này trong Spring container như sau:
1 2 3 4 5 6 7 |
@Bean public JWKSource<SecurityContext> jwkSource() throws NoSuchAlgorithmException, KeyStoreException, CertificateException, FileNotFoundException, IOException { JWKSet jwkSet = buildJWKSet(); return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet); } |
Các bạn có thể sử dụng đoạn code build JWKSet cho bất cứ keystore nào các bạn nhé!