1

I have integrated IdentityServer4 in spring Boot project.

I want to know how to add code_verifier to call "/connect/token" of IdentityServer?

I receive code in the redirecturl as follows,

First Redirect: https://idsrv4test.com/connect/authorize?response_type=code&client_id=client_id&scope=id_number%20openid%20email%20roles%20profile&state=SDGHMnvw0UJZyylFr752jBAWS2ahGIwBiavF0YsRtoI%3D&redirect_uri=https://127.0.0.1:9443/signin-oidc&code_challenge_method=S256&nonce=_8fJthx0jlqX_2tJKSkwvs_r4RfxIjU4NokGGpSZIF0&code_challenge=<this_encrypted_text>

Second Redirect https://127.0.0.1:9443/signin-oidc?code=returned_code&scope=id_number%20openid%20email%20roles%20profile&state=9KxStmaCkre_-cCqofOSfRO0eWahh-3e19upwYH1rJ8%3D&session_state=Sm-Zq8GcrX43Rc1Ve5elO7ua90aIyXTkJB6lT4tQRhY.ImGYr6V2186LxSMZdLcngg

I construct a resttemplate in my project to call "/connect/token" as per

POST /connect/token CONTENT-TYPE application/x-www-form-urlencoded

client_id=client_id&
client_secret=secret&
grant_type=authorization_code&
code=returned_code&
redirect_uri=https://127.0.0.1:9443/signin-oidc
code_verifier=<this_encrypted_text>

In the requestBody I set code_verifier=<this_encrypted_text> But I get "invalid_grant". It means as per the spec docs https://datatracker.ietf.org/doc/html/rfc7636#page-10 code_verifier == code_challenge. is flase

For your reference SecurityConfig class is as such

@EnableWebSecurity
public class ConfigSecurity extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {


        PortMapperImpl portMapper = new PortMapperImpl();
        portMapper.setPortMappings(Collections.singletonMap("9443","9443"));
        PortResolverImpl portResolver = new PortResolverImpl();
        portResolver.setPortMapper(portMapper);
        LoginUrlAuthenticationEntryPoint entryPoint = new LoginUrlAuthenticationEntryPoint(
                "/login");
        entryPoint.setPortMapper(portMapper);
        entryPoint.setPortResolver(portResolver);
        http.exceptionHandling()
                .authenticationEntryPoint(entryPoint)
                .and()
                .authorizeRequests()
                .antMatchers("/login","/css/*", "/images/*","/signin-oidc","/test")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .oauth2Login()
                .loginPage("/login")
                .and()
                .logout().logoutUrl("/logout")
                .logoutSuccessHandler(oidcLogoutSuccessHandler());


    }

    @Autowired
    private ClientRegistrationRepository clientRegistrationRepository;

    private LogoutSuccessHandler oidcLogoutSuccessHandler() {

        OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler =
                new OidcClientInitiatedLogoutSuccessHandler(
                        this.clientRegistrationRepository);

        oidcLogoutSuccessHandler.setPostLogoutRedirectUri(
                URI.create("http://localhost:9443"));

        return oidcLogoutSuccessHandler;
    }
}

And my application.yml is as follows,

server:
  port: 9443
  ssl:
    key-store: classpath:asif1.jks
    key-store-password: xxxxx
    key-store-type: pkcs12
    key-store-alias: server
spring:
  security:
    oauth2:
      client:
        registration:
          idsrv4:
            client-name: client_name_test
            client-id: client_id_test
            client-secret: Marines
            client-authentication-method: none
            authorization-grant-type: authorization_code
            redirect-uri: "https://127.0.0.1:9443/signin-oidc"

            scope: "id_number,openid,email,roles,profile"


        provider:
          idsrv4:
            authorization-uri: https://idsrv4test.com/connect/authorize
            issuer-uri: https://idsrv4test.com
            token-uri: https://idsrv4test.com/connect/token
            user-info-uri: https://idsrv4test.com/connect/userinfo
            user-name-attribute: sub
            jwk-set-uri: https://idsrv4test.com/.well-known/openid-configuration/jwks

Any help ?

1 Answer 1

1

I finally resolved this issue. But still not satisfied with the methodology. Yet, it works gracefully. What I expected from OAuth2AuthorizationRequestResolver that the request to get the jwt token gets created internally and I should be unaware of the random string generated as code_challenge(to implement PKCE).

I still request to share if somebody has a working example of authenticating and getting token by just providing required confs without me implementing and overriding OAuth2AuthorizationRequestResolver. So, here i go

To implement OAuth2AuthorizationRequestResolver please follow https://developer.okta.com/blog/2020/01/23/pkce-oauth2-spring-boot

then in method addPkceParameters

     String codeVerifier = this.secureKeyGenerator.generateKey();
    attributes.put(PkceParameterNames.CODE_VERIFIER, codeVerifier);

codeVerifier is the string which we need to send alongwith the request for /connect/token

Now, its all up to you how you get this randomly generated string in your controller to send the request.

I have hard coded it ;-) for time being. But this I know does not fulfill the purpose of PKCE.

Also, in your class extending WebSecurityConfigurerAdapter , configure(HttpSecurity http) method must contain "/oauth2/authorization" as base url

somethg like this

http.exceptionHandling()
                .authenticationEntryPoint(entryPoint)
                .and()
                .authorizeRequests()
                .antMatchers("/login","/css/*", "/static/**", "/images/*","/test","/signin-oidc","/logoutSession")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .oauth2Login()
                .authorizationEndpoint()
                .authorizationRequestResolver(new CustomAuthorizationRequestResolver(
                        clientRegistrationRepository, "/oauth2/authorization"
                ))
                .and()
                .loginPage("/login").and().logout().logoutUrl("/logout")
                .logoutSuccessHandler(oidcLogoutSuccessHandler());
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.