3232import java .io .IOException ;
3333import java .net .InetSocketAddress ;
3434import java .net .URI ;
35+ import java .nio .charset .StandardCharsets ;
3536import java .security .MessageDigest ;
3637import java .security .NoSuchAlgorithmException ;
3738import java .security .SecureRandom ;
3839import java .util .Base64 ;
40+ import java .util .UUID ;
3941import java .util .concurrent .CompletableFuture ;
4042import java .util .concurrent .ExecutionException ;
4143import java .util .concurrent .TimeUnit ;
4244import java .util .concurrent .TimeoutException ;
43- import java .util .concurrent .atomic .AtomicReference ;
44- import java .awt .Desktop ;
45- import java .awt .Desktop .Action ;
45+ import java .util .logging .Logger ;
4646
4747import com .sun .net .httpserver .HttpExchange ;
4848import com .sun .net .httpserver .HttpHandler ;
5555 * To complete the additional requirements.
5656 */
5757public final class AuthCodePkceTokenRequestBuilder extends TokenRequestBuilder <AuthCodePkceTokenRequestBuilder > {
58-
58+ private static final Logger LOGGER = Logger . getLogger ( AuthCodePkceTokenRequestBuilder . class . getName ());
5959 @ Override
6060 OAuth2Token retrieveToken () throws IOException {
6161
6262 OAuth2Token retVal = null ;
6363 // https://datatracker.ietf.org/doc/html/rfc7636#section-4.1
6464 try {
65- byte [] verifierBytes = new byte [128 ];
65+ byte [] verifierBytes = new byte [64 ];
6666 SecureRandom .getInstanceStrong ().nextBytes (verifierBytes );
6767 Base64 .Encoder b64encoder = Base64 .getUrlEncoder ().withoutPadding ();
6868 final String verifier = b64encoder .encodeToString (verifierBytes );
69+ final String originalState = UUID .randomUUID ().toString ();
6970
7071 MessageDigest md = MessageDigest .getInstance ("SHA-256" );
71- final String challenge = b64encoder .encodeToString (md .digest (verifierBytes ));
72+ final String challenge = b64encoder .encodeToString (md .digest (verifier . getBytes ( StandardCharsets . US_ASCII ) ));
7273 HttpServer server = HttpServer .create (new InetSocketAddress ("localhost" , 0 ), 0 );
7374 int port = server .getAddress ().getPort ();
7475 String host = server .getAddress ().getHostName ();
@@ -82,7 +83,7 @@ public void handle(HttpExchange exchange) throws IOException {
8283 Result ret = null ;
8384
8485 final String query = exchange .getRequestURI ().getQuery ();
85- System . out . println ("Got auth server response." + query );
86+ LOGGER . finest ("Got auth server response." + query );
8687 final QueryParameters parameters = QueryParameters .parse (query );
8788 if (!parameters .get ("error" ).isEmpty ()) {
8889 String error = parameters .get ("error" ).get (0 );
@@ -91,9 +92,10 @@ public void handle(HttpExchange exchange) throws IOException {
9192 } else {
9293 String code = parameters .get ("code" ).get (0 );
9394 String state = parameters .get ("state" ).get (0 );
94- ret = Result .success (code ,state );
95+ String session_state = parameters .get ("session_state" ).get (0 );
96+ ret = Result .success (code ,state , session_state );
9597 }
96- System . out . println ( "Finishing " );
98+ LOGGER . finest ( "Returning result back to thread. " );
9799 server .stop (0 );
98100 future .complete (ret );
99101 }
@@ -108,25 +110,30 @@ public void handle(HttpExchange exchange) throws IOException {
108110 .set ("code_challenge_method" , "S256" )
109111 .set ("code_challenge" , challenge )
110112 .set ("redirect_uri" , redirectUri )
111- .set ("kc_idp_hint " , "login.gov" );
113+ .set ("state " , originalState );
112114 String urlStr = String .format ("%s?%s" , getAuthUrl ().getApiRoot (), authParameters .encode ());
113115 // start server to listen
114116 server .start ();
115- System .out .println (urlStr );
117+ LOGGER .info ("Handling Auth Request" );
118+ LOGGER .finer ("Auth Request URL: " + urlStr );
116119 this .authCallBack .accept (URI .create (urlStr ));
117120
118- Result result = future .get (1 , TimeUnit .MINUTES ); // The user is now required to perform manual operations.
119- System . out . println ( "Next steps ." );
121+ Result result = future .get (3 , TimeUnit .MINUTES ); // The user is now required to perform manual operations.
122+ LOGGER . info ( "Retrieving Token ." );
120123 if (result .error != null ) {
121124 throw new IOException (String .format ("Unable to login. %s : %s" , result .error , result .errorDescription ));
122125 }
126+ if (!result .state .equals (originalState )) {
127+ throw new IOException ("Unable to continue login sequence, incorrect state value returned." );
128+ }
123129 final UrlEncodedFormData formData = new UrlEncodedFormData ();
124130 formData .addClientId (getClientId ())
125131 .addGrantType ("authorization_code" )
126132 .addParameter ("code_verifier" , verifier )
127133 .addScopes ("openid" , "profile" )
128134 .addParameter ("redirect_uri" , redirectUri )
129- .addParameter ("session_state" , result .state )
135+ .addParameter ("state" , result .state )
136+ .addParameter ("session_state" , result .session_state )
130137 .addParameter ("code" , result .code )
131138 .addParameter ("response_mode" , "fragment" )
132139 .addParameter ("response_type" , "id_token token" );
@@ -153,23 +160,25 @@ public void handle(HttpExchange exchange) throws IOException {
153160 private static class Result {
154161 public final String code ;
155162 public final String state ;
163+ public final String session_state ;
156164
157165 public final String error ;
158166 public final String errorDescription ;
159167
160- private Result (String code , String state , String error , String errorDescription ) {
168+ private Result (String code , String state , String session_state , String error , String errorDescription ) {
161169 this .code = code ;
162170 this .state = state ;
171+ this .session_state = session_state ;
163172 this .error = error ;
164173 this .errorDescription = errorDescription ;
165174 }
166175
167- public static Result success (String code , String state ) {
168- return new Result (code , state , null , null );
176+ public static Result success (String code , String state , String session_state ) {
177+ return new Result (code , state , session_state , null , null );
169178 }
170179
171180 public static Result failure (String error , String errorDescription ) {
172- return new Result (null , null , error , errorDescription );
181+ return new Result (null , null , null , error , errorDescription );
173182 }
174183 };
175184}
0 commit comments