From 2c103f34e3eaf6b74ae529bcb9029aec929b98ce Mon Sep 17 00:00:00 2001 From: Eleftheria Stein Date: Tue, 24 Mar 2020 10:29:11 -0400 Subject: [PATCH] Add password storage Kotlin samples to docs Issue gh-8172 --- .../authentication/password-storage.adoc | 120 ++++++++++++++++-- 1 file changed, 112 insertions(+), 8 deletions(-) diff --git a/docs/manual/src/docs/asciidoc/_includes/about/authentication/password-storage.adoc b/docs/manual/src/docs/asciidoc/_includes/about/authentication/password-storage.adoc index 018fa0dc16..83a61b3927 100644 --- a/docs/manual/src/docs/asciidoc/_includes/about/authentication/password-storage.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/about/authentication/password-storage.adoc @@ -68,18 +68,26 @@ You can easily construct an instance of `DelegatingPasswordEncoder` using `Pass .Create Default DelegatingPasswordEncoder ==== -[source,java] +.Java +[source,java,role="primary"] ---- PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); ---- + +.Kotlin +[source,kotlin,role="secondary"] +---- +val passwordEncoder: PasswordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder() +---- ==== Alternatively, you may create your own custom instance. For example: .Create Custom DelegatingPasswordEncoder ==== -[source,java] +.Java +[source,java,role="primary"] ---- String idForEncode = "bcrypt"; Map encoders = new HashMap<>(); @@ -92,6 +100,20 @@ encoders.put("sha256", new StandardPasswordEncoder()); PasswordEncoder passwordEncoder = new DelegatingPasswordEncoder(idForEncode, encoders); ---- + +.Kotlin +[source,kotlin,role="secondary"] +---- +val idForEncode = "bcrypt" +val encoders: MutableMap = mutableMapOf() +encoders[idForEncode] = BCryptPasswordEncoder() +encoders["noop"] = NoOpPasswordEncoder.getInstance() +encoders["pbkdf2"] = Pbkdf2PasswordEncoder() +encoders["scrypt"] = SCryptPasswordEncoder() +encoders["sha256"] = StandardPasswordEncoder() + +val passwordEncoder: PasswordEncoder = DelegatingPasswordEncoder(idForEncode, encoders) +---- ==== [[authentication-password-storage-dpe-format]] @@ -180,7 +202,8 @@ There are convenience mechanisms to make this easier, but this is still not inte .withDefaultPasswordEncoder Example ==== -[source,java,attrs="-attributes"] +.Java +[source,java,role="primary",attrs="-attributes"] ---- User user = User.withDefaultPasswordEncoder() .username("user") @@ -190,13 +213,26 @@ User user = User.withDefaultPasswordEncoder() System.out.println(user.getPassword()); // {bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG ---- + +.Kotlin +[source,kotlin,role="secondary",attrs="-attributes"] +---- +val user = User.withDefaultPasswordEncoder() + .username("user") + .password("password") + .roles("user") + .build() +println(user.password) +// {bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG +---- ==== If you are creating multiple users, you can also reuse the builder. .withDefaultPasswordEncoder Reusing the Builder ==== -[source,java] +.Java +[source,java,role="primary"] ---- UserBuilder users = User.withDefaultPasswordEncoder(); User user = users @@ -210,6 +246,22 @@ User admin = users .roles("USER","ADMIN") .build(); ---- + +.Kotlin +[source,kotlin,role="secondary"] +---- +val users = User.withDefaultPasswordEncoder() +val user = users + .username("user") + .password("password") + .roles("USER") + .build() +val admin = users + .username("admin") + .password("password") + .roles("USER", "ADMIN") + .build() +---- ==== This does hash the password that is stored, but the passwords are still exposed in memory and in the compiled source code. @@ -273,7 +325,10 @@ The `BCryptPasswordEncoder` implementation uses the widely supported https://en. In order to make it more resistent to password cracking, bcrypt is deliberately slow. Like other adaptive one-way functions, it should be tuned to take about 1 second to verify a password on your system. -[source,java] +.BCryptPasswordEncoder +==== +.Java +[source,java,role="primary"] ---- // Create an encoder with strength 16 BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16); @@ -281,6 +336,16 @@ String result = encoder.encode("myPassword"); assertTrue(encoder.matches("myPassword", result)); ---- +.Kotlin +[source,kotlin,role="secondary"] +---- +// Create an encoder with strength 16 +val encoder = BCryptPasswordEncoder(16) +val result: String = encoder.encode("myPassword") +assertTrue(encoder.matches("myPassword", result)) +---- +==== + [[authentication-password-storage-argon2]] == Argon2PasswordEncoder @@ -290,7 +355,10 @@ In order to defeat password cracking on custom hardware, Argon2 is a deliberatel Like other adaptive one-way functions, it should be tuned to take about 1 second to verify a password on your system. The current implementation if the `Argon2PasswordEncoder` requires BouncyCastle. -[source,java] +.Argon2PasswordEncoder +==== +.Java +[source,java,role="primary"] ---- // Create an encoder with all the defaults Argon2PasswordEncoder encoder = new Argon2PasswordEncoder(); @@ -298,6 +366,16 @@ String result = encoder.encode("myPassword"); assertTrue(encoder.matches("myPassword", result)); ---- +.Kotlin +[source,kotlin,role="secondary"] +---- +// Create an encoder with all the defaults +val encoder = Argon2PasswordEncoder() +val result: String = encoder.encode("myPassword") +assertTrue(encoder.matches("myPassword", result)) +---- +==== + [[authentication-password-storage-pbkdf2]] == Pbkdf2PasswordEncoder @@ -306,7 +384,10 @@ In order to defeat password cracking PBKDF2 is a deliberately slow algorithm. Like other adaptive one-way functions, it should be tuned to take about 1 second to verify a password on your system. This algorithm is a good choice when FIPS certification is required. -[source,java] +.Pbkdf2PasswordEncoder +==== +.Java +[source,java,role="primary"] ---- // Create an encoder with all the defaults Pbkdf2PasswordEncoder encoder = new Pbkdf2PasswordEncoder(); @@ -314,6 +395,16 @@ String result = encoder.encode("myPassword"); assertTrue(encoder.matches("myPassword", result)); ---- +.Kotlin +[source,kotlin,role="secondary"] +---- +// Create an encoder with all the defaults +val encoder = Pbkdf2PasswordEncoder() +val result: String = encoder.encode("myPassword") +assertTrue(encoder.matches("myPassword", result)) +---- +==== + [[authentication-password-storage-scrypt]] == SCryptPasswordEncoder @@ -321,7 +412,10 @@ The `SCryptPasswordEncoder` implementation uses https://en.wikipedia.org/wiki/Sc In order to defeat password cracking on custom hardware scrypt is a deliberately slow algorithm that requires large amounts of memory. Like other adaptive one-way functions, it should be tuned to take about 1 second to verify a password on your system. -[source,java] +.SCryptPasswordEncoder +==== +.Java +[source,java,role="primary"] ---- // Create an encoder with all the defaults SCryptPasswordEncoder encoder = new SCryptPasswordEncoder(); @@ -329,6 +423,16 @@ String result = encoder.encode("myPassword"); assertTrue(encoder.matches("myPassword", result)); ---- +.Kotlin +[source,kotlin,role="secondary"] +---- +// Create an encoder with all the defaults +val encoder = SCryptPasswordEncoder() +val result: String = encoder.encode("myPassword") +assertTrue(encoder.matches("myPassword", result)) +---- +==== + [[authentication-password-storage-other]] == Other PasswordEncoders