Search code examples
javaspring-bootspring-securityspring-restcontroller

How to make programmatically a call to /oauth/token from the same application where we have it without actual http call?


I have a case, where I need to get access token without http call to predefined by Oauth Spring Security /oauth/token endpoint, but instead, have a call for some api, available for the anonymous user, and among the other business data bring the access token back.

I try this code:

        String username = "username";
        String password = "2134";
//
        AccountInitSetting accountSetting = accountService.getInitSetting(username);
        try {
            agentService.createTempCredentials(username, accountSetting.getAccountType(),
                    null, accountSetting.getRoleId(), accountSetting.getGroupId(),
                    ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getHeader("x-forwarded-for"),
                    null, false);
        } catch (UserInterfaceException e) {
            throw new RuntimeException(e);
        }


        Map<String, String> parameters = new HashMap<>();
        parameters.put("grant_type","password");
        parameters.put("username", username);
        parameters.put("password", password);
        parameters.put("scope","all");

        try {
            return tokenEndpoint.postAccessToken(principal, parameters).getBody().getValue();

        } catch (HttpRequestMethodNotSupportedException e) {
            throw new OAuth2Exception(e.getMessage(), e);
        }

    }

please note, that Principal is taken from the @RestController's endpoint method paramether and thus passed to this method.

And I'm getting the below exception:

22:40:33.007 [http-bio-9090-exec-2] ERROR com.openpayment.site.web.service.init.WebServiceExceptionHandler - There is no client authentication. Try adding an appropriate authentication filter.
org.springframework.security.authentication.InsufficientAuthenticationException: There is no client authentication. Try adding an appropriate authentication filter.

What I'm missing?


Solution

  • I had to add explicitly new Authentication with isAuthenticated() true and getName() as the application expect.

        String username = "username";
        String password = "2134";
      Map<String, String> parameters = new HashMap<>();
        parameters.put("grant_type","password");
        parameters.put("username", username);
        parameters.put("password", password);
        //parameters.put("clientId","clientId4");
        parameters.put("scope","all");
        Principal principal1 = new Authentication() {
            @Override
            public Collection<? extends GrantedAuthority> getAuthorities() {
                return null;
            }
    
            @Override
            public Object getCredentials() {
                return null;
            }
    
            @Override
            public Object getDetails() {
                return null;
            }
    
            @Override
            public Object getPrincipal() {
                return null;
            }
    
            @Override
            public boolean isAuthenticated() {
                return true;
            }
    
            @Override
            public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
    
            }
    
            @Override
            public String getName() {
                return "clientId4";
            }
        };
    
        try {
            return tokenEndpoint.postAccessToken(principal1, parameters).getBody().getValue();
    
        } catch (HttpRequestMethodNotSupportedException e) {
            throw new OAuth2Exception(e.getMessage(), e);
        }
    
    }