Monday 28 January 2019

Can not get keycloak authorization token in spring

I have web application which and i am trying to make keycloak authorizations on JavaScript side I am going on keycloak login page and authenticating successfully. Here is my code

var keycloak = Keycloak({
            realm: 'demo',
            url: 'localhost:8080/auth',
            clientId: 'justice'
        });
        keycloak.init({ onLoad: 'login-required' }).success(function(authenticated) {
            alert(authenticated ? 'authenticated' : 'not authenticated');
        }).error(function() {
            alert('failed to initialize');
        });

then I am calling Rest web service on java side

$.ajax({
                    type: "POST",
                    url: "login",
                    headers: {
                        "Authorization":"Bearer "+ keycloak.token
                    },
                    success: function (response) {
                        location.reload();

                    },
                    error: function (jqXHR, textStatus, errorThrown) {
                        console.log(textStatus, errorThrown);
                    }
                });

Here is everything okay, I am taking token and putting in header,But I have problem on java side, Can not take this authorization token, user role and some other properties from this token.

Here is my configuration class which uses spring security config

import javax.servlet.http.HttpServletRequest;
import org.keycloak.adapters.springsecurity.KeycloakConfiguration;
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
import org.keycloak.adapters.springsecurity.client.KeycloakClientRequestFactory;
import org.keycloak.adapters.springsecurity.client.KeycloakRestTemplate;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
import org.keycloak.representations.AccessToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@KeycloakConfiguration
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    @Autowired
    KeycloakClientRequestFactory keycloakClientRequestFactory;

    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new NullAuthenticatedSessionStrategy();
    }

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public KeycloakRestTemplate keycloakRestTemplate() {
        return new KeycloakRestTemplate(keycloakClientRequestFactory);
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(keycloakAuthenticationProvider);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .sessionAuthenticationStrategy(sessionAuthenticationStrategy()).and().authorizeRequests()
                .antMatchers("/login*").hasRole("ADMIN").anyRequest().permitAll();
    }

    @Bean
    @Scope(scopeName = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public AccessToken getAccessToken() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
                .getRequest();
        return ((KeycloakAuthenticationToken) request.getUserPrincipal()).getAccount().getKeycloakSecurityContext()
                .getToken();
    }

}

Then I am trying to take token but every try is useless.

I tried this way and result is null

@Controller
@RequestMapping
public class AuthController {

    @Autowired
        private AccessToken accessToken;

     @RequestMapping(value = "/login", method = {RequestMethod.POST})
public String verify(Principal principal,Model model) throws Exception {
     //principal field is null
    String token = accessToken.getAccessTokenHash(); // null
}

and this way

@Controller
@RequestMapping
public class AuthController {

    @Autowired
        private AccessToken accessToken;

     @RequestMapping(value = "/login", method = {RequestMethod.POST})
public String verify(Principal principal,Model model) throws Exception {
     Authentication auth =SecurityContextHolder.getContext().getAuthentication();
    KeycloakPrincipal principal = (KeycloakPrincipal) auth.getPrincipal(); // again null 
}

and this way also

@Controller
    @RequestMapping
    public class AuthController {

        @Autowired
            private AccessToken accessToken;

         @RequestMapping(value = "/login", method = {RequestMethod.POST})
    public String verify(Principal principal,Model model) throws Exception {
         HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
                .getRequest();

 KeycloakSecurityContext keycloakSecurityContext = (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
                AuthorizationContext authzContext = keycloakSecurityContext.getAuthorizationContext(); // and still null
}

here is content of my keycloak.json which is placed in WEB-INF

{
  "realm": "demo",
  "bearer-only": true,
  "auth-server-url": "localhost:8080/auth",
  "ssl-required": "external",
  "resource": "justice-service",
  "use-resource-role-mappings": true
}

Maybe I misunderstand flow of this authentication or something.Maybe I have some mistakes in code or in configuration. I just need to take token and properties from this token i.e. user role or username on java side. I am using first time keycloak authentication, anyway do I need to set this Adapters on JavaScript and on Java side too like I have ? Or is it enough to have only in JavaScript?



from Can not get keycloak authorization token in spring

No comments:

Post a Comment