Refactor PKCE API to prevent incorrect use of code_challenge in AuthenticationRequest

Issue #202 resolved
Dark Eye created an issue

If you create an AuthenticationRequest as follows:

AuthenticationRequest authenticationRequest = new AuthenticationRequest.Builder(
                new ResponseType(ResponseType.Value.CODE),
                scopes,
                client_id,
                redirectUri
        ).endpointURI(providerMetadata.getAuthorizationEndpointURI())
                .state(state)
                .codeChallenge(new CodeChallenge("test"), CodeChallengeMethod.S256)
                .build();

The resulting URI still have the code_challenge parameter without computing:

http://localhost:8080/openid-connect-server-webapp/authorize?response_type=code&client_id=mcptt_client&redirect_uri=http%3A%2F%2Fhttpbin.org%2Fget&scope=openid&state=ke_1EdjcjLUUXvsIJ6ZtEEs1XczjITXEzxmykS6aHfY&code_challenge=test&code_challenge_method=S256

A call to CodeChallenge.compute() should be issued in the process of AuthenticationRequest URL building

Comments (8)

  1. Connect2id OSS

    Here is an example correct request with code_challenge:

    // Compute PKCE
    CodeVerifier pkceVerifier = new CodeVerifier();
    CodeChallenge pkceChallenge = CodeChallenge.compute(CodeChallengeMethod.S256, pkceVerifier);
    
    URI authRequest = new AuthenticationRequest.Builder(
        new ResponseType("code"),
        new Scope("openid"),
        new ClientID("123"),
        URI.create("myapp://openid-connect-callback"))
        .state(new State())
        .codeChallenge(pkceChallenge, CodeChallengeMethod.S256)
        .requestObject(jwt)
        .endpointURI(URI.create("https://openid.c2id.com"))
        .build()
        .toURI();
    

    The CodeChallenge object is intended for holding the computed challenge, not the verifier. The CodeChallenge(String) constructor is there to allow recreation of the code_challenge object on the server side (where the code verifier is obviously not present).

    https://tools.ietf.org/html/rfc7636#section-4.1

    Possible ways to prevent such confusion:

    1. Make the CodeChallenge String constructor private, and introduce a static parse(String) method. Developers will then be forced to take a closer look at the API / JavaDocs.

    2. Deprecate the existing builder method, and introduce a new codeChallenge(CodeChallengeMethod, CodeVerifier) method.

  2. Log in to comment