PKCE Code Verifier and Code Challenge in Java

In this tutorial, you will learn how to generate the OAuth PKCE Code Verifier and the Code Challenge in Java.

For video lessons on how to secure your Spring Boot application with OAuth 2.0. and Spring Security 5, please checkout my complete video course OAuth 2.0. in Spring Boot applications.

The Code Verifier and the Code Challenge are used in the OAuth PKCE-enhanced Authorization Code Grant flow and the specs on how these two should be generated can be found here RFC7636.

To learn how to perform the PKCE-enhanced Authorization Code Grant flow to acquire an access token, please refer to this tutorial: PKCE Verification in Authorization Code Grant.

Code Verifier

The Code Verifier and the Code Challenge need to be generated for each OAuth 2 authorization request. For detailed specification, on code verifier please refer to RFC7636 but in simple words, the code verifier is a Base64 URL encoded alphanumeric string of characters with a minimum length of 43 characters and a maximum length of 128 characters.

 
package com.appsdeveloperblog.pkce;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
 
public class PkceUtil {
 
    String generateCodeVerifier() throws UnsupportedEncodingException {
        SecureRandom secureRandom = new SecureRandom();
        byte[] codeVerifier = new byte[32];
        secureRandom.nextBytes(codeVerifier);
        return Base64.getUrlEncoder().withoutPadding().encodeToString(codeVerifier);
    }
 
}

Code Challenge

Now when we have generated the code verifier we can use it to generate the code challenge.

The official specification tells us to generate the code challange the following way:

code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))

We can implement it in Java with the following function.

String generateCodeChallange(String codeVerifier) throws UnsupportedEncodingException, NoSuchAlgorithmException {
    byte[] bytes = codeVerifier.getBytes("US-ASCII");
    MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
    messageDigest.update(bytes, 0, bytes.length);
    byte[] digest = messageDigest.digest();

    return Base64.getUrlEncoder().withoutPadding().encodeToString(digest);
}

Complete Code Example

Let’s put the above code into a single Java class and run it. I will put the above two functions that generate the code verifier and the code challange into a single class called PkceUtil.

package com.appsdeveloperblog.pkce;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
 
public class PkceUtil {

    String generateCodeVerifier() throws UnsupportedEncodingException {
        SecureRandom secureRandom = new SecureRandom();
        byte[] codeVerifier = new byte[32];
        secureRandom.nextBytes(codeVerifier);

        return Base64.getUrlEncoder().withoutPadding().encodeToString(codeVerifier);
    }

    String generateCodeChallange(String codeVerifier) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        byte[] bytes = codeVerifier.getBytes("US-ASCII");
        MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
        messageDigest.update(bytes, 0, bytes.length);
        byte[] digest = messageDigest.digest();

        return Base64.getUrlEncoder().withoutPadding().encodeToString(digest);
    }
}

I can now run it with a simple Java application.

package com.appsdeveloperblog.pkce;

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
import java.util.logging.Logger;

public class PkceExample {

    public static void main(String[] args) {

        try {
            
            PkceUtil pkce = new PkceUtil();
 
            String codeVerifier = pkce.generateCodeVerifier();
            System.out.println("Code verifier = " + codeVerifier);
            
            String codeChallenge = pkce.generateCodeChallange(codeVerifier);
            System.out.println("Code challenge = " + codeChallenge);
 
        } catch (UnsupportedEncodingException | NoSuchAlgorithmException ex) {
            Logger.getLogger(PkceExample.class.getName()).log(Level.SEVERE, null, ex);
        }

    }
 
}

The output:

Code verifier = jWJS7olsI78LF-hcNHO1QBMqVX06iN5Z837vD6UXO3g
Code challenge = WIwW8sZaGckIxtqi_L2h4-Mgk06-X2ffV95NdDo1_bw

To learn how to use the code verifier and the code challenge in the PKCE-inhanced Authorization Code flow, you can read the following tutorial: PKCE Verification in Authorization Code Grant.

Happy learning! 🙋🏻‍♂️

Leave a Reply

Your email address will not be published. Required fields are marked *