Many thanks to all of you for the help. I'm so close to achieve it, so I need some last tip (and think you can do even about not to have mobile knowledge). That's the steps I've followed to authenticate a user in a public client in the Android app:

1- Launch a browser app pointing to keycloak's authorization site for the client:

Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse("http://192.168.0.230:8080/auth/realms/master/protocol/" +
    "openid-connect/auth?response_type=code&client_id=web_service&redirect_uri=android://app"));
startActivity(i);

2- Retrieve the authorization code when coming back to my app and ask for an access token:

            RestTemplate template = new RestTemplate();
            template.getMessageConverters().add(new FormHttpMessageConverter());
            template.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
            MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
            form.add("grant_type", "authorization_code");
            form.add("client_id", "edge");
            form.add("code", accessCode);
            form.add("redirect_uri", "tcheck://app");
            ResponseEntity rssResponse = template.postForEntity(
                    "http://192.168.0.230:8080/auth/realms/master/protocol/openid-connect/token",
                    form,
                    AccessToken.class);

I'm passing the parameters in the request body as x-www-form-urlencoded and it works. I do get an access token, with this format:

{
    "access_token" : "eyJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI5OTEzYmRjOS1jZmI0LTRlZjAtYTcxYy0yYWUwYmQ3MTkwZDkiLCJleHAiOjE0NTI3NzUwNDQsIm5iZiI6MCwiaWF0IjoxNDUyNzc0OTg0LCJpc3MiOiJodHRwOi8vMTkyLjE2OC4wLjIzMDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsImF1ZCI6ImVkZ2UiLCJzdWIiOiJhNzE0NzAxNS0zNWM2LTRhZWEtYjNjOC1hNTY1ZTQ5YjcyZDkiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJlZGdlIiwic2Vzc2lvbl9zdGF0ZSI6IjdkZDVhZDdiLWQwYWItNGZiYS1iOWNiLWYzNjYxYTk5NGU3OSIsImNsaWVudF9zZXNzaW9uIjoiZDg2MzY1NjctMzg2MS00NjU5LTg0ZjItMDZjYmM5YTI3YTU1IiwiYWxsb3dlZC1vcmlnaW5zIjpbXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIlNVUEVSX0FETUlOIiwiY3JlYXRlLXJlYWxtIiwiVklFV19PUkdBTklaQVRJT04iLCJST0xFX1RDSEVDS19TVVBFUl9BRE1JTiIsIlJPTEVfVENIRUNLX0FETUlOIiwiYWRtaW4iXX0sInJlc291cmNlX2FjY2VzcyI6eyJtYXN0ZXItcmVhbG0iOnsicm9sZXMiOlsibWFuYWdlLWV2ZW50cyIsInZpZXctcmVhbG0iLCJ2aWV3LWlkZW50aXR5LXByb3ZpZGVycyIsIm1hbmFnZS1yZWFsbSIsIm1hbmFnZS1pZGVudGl0eS1wcm92aWRlcnMiLCJpbXBlcnNvbmF0aW9uIiwidmlldy1ldmVudHMiLCJjcmVhdGUtY2xpZW50IiwibWFuYWdlLXVzZXJzIiwidmlldy11c2VycyIsInZpZXctY2xpZW50cyIsIm1hbmFnZS1jbGl lbnRzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50Iiwidmlldy1wcm9maWxlIl19fSwibmFtZSI6IiIsInByZWZlcnJlZF91c2VybmFtZSI6ImFkbWluIn0.GMoAPe9aUQBRign5J0TvOt4tg1SWwyfJkvJjuWDZ_Ayj3GBnFjhgbjb5qLreKsm87NHymPcpvCv7uHkKJRsx44TjC0514O0oBSiVIiKfcJdbE-y7nPplzYAJF6I2JlsQkw9Na67vNSvhsBNg6AfBop4xpAF9HtTU7Ca7gFwOS01bgDRO09WlJYivzOd5t-vQGNwRVlTqaCstIMiBLaUfdkc82DNQwnoP5VO9R7xZn-7O5BE288_CX0C2V96_vooIoTbB3Qoa-gV6f3s6ZSyJnRGBgoe_2QY3mjCBarFQ_mKH_sbF2qMpm-a5igoNoD_3Xlc7iluP206ZJdQn4NZdQg",
    "expires_in" : 60,
    "refresh_expires_in" : 1800,
    "refresh_token" : "eyJhbGciOiJSUzI1NiJ9.eyJqdGkiOiJkOTBmNzY5Ni00NDIwLTQ3NDUtYmQ3NS01Y2Q4MDNlMWY0YjQiLCJleHAiOjE0NTI3NzY3ODQsIm5iZiI6MCwiaWF0IjoxNDUyNzc0OTg0LCJpc3MiOiJodHRwOi8vMTkyLjE2OC4wLjIzMDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsImF1ZCI6bnVsbCwic3ViIjoiYTcxNDcwMTUtMzVjNi00YWVhLWIzYzgtYTU2NWU0OWI3MmQ5IiwidHlwIjoiUmVmcmVzaCIsImF6cCI6ImVkZ2UiLCJzZXNzaW9uX3N0YXRlIjoiN2RkNWFkN2ItZDBhYi00ZmJhLWI5Y2ItZjM2NjFhOTk0ZTc5IiwiY2xpZW50X3Nlc3Npb24iOiJkODYzNjU2Ny0zODYxLTQ2NTktODRmMi0wNmNiYzlhMjdhNTUiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiU1VQRVJfQURNSU4iLCJjcmVhdGUtcmVhbG0iLCJWSUVXX09SR0FOSVpBVElPTiIsIlJPTEVfVENIRUNLX1NVUEVSX0FETUlOIiwiUk9MRV9UQ0hFQ0tfQURNSU4iLCJhZG1pbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7Im1hc3Rlci1yZWFsbSI6eyJyb2xlcyI6WyJtYW5hZ2UtZXZlbnRzIiwidmlldy1yZWFsbSIsInZpZXctaWRlbnRpdHktcHJvdmlkZXJzIiwibWFuYWdlLXJlYWxtIiwibWFuYWdlLWlkZW50aXR5LXByb3ZpZGVycyIsImltcGVyc29uYXRpb24iLCJ2aWV3LWV2ZW50cyIsImNyZWF0ZS1jbGllbnQiLCJtYW5hZ2UtdXNlcnMiLCJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwibWFuYWdlLWNsaWVudHMiXX0sImFjY291bnQiOnsicm9 sZXMiOlsibWFuYWdlLWFjY291bnQiLCJ2aWV3LXByb2ZpbGUiXX19fQ.OZkivKxU1HJecrqKb1KDSabakruHJLUaUpNOy_DY7UW1R-4Qv6kLnPy_3soeRPP0FwYNrjzNMw94S-naE8JNCD91LqTTEyJ6o6q_1LDiDbVbfsKeyRkJDZDAbHUYtY-r35z_21SqdHxzzMcero6DoCpFaGOZZFQ86FZD7NiRE3oVzCIz1VJAFBIsSjH0W5_UQa2CEEIOxDanPnhbtdB8XZ6oQeKPB15AvobCgukvWcDufmCeJpUMcIjaTcnBdXRz6MIOp6VjQ5SyqJzn7jja8ILs3zEd8eeocAIix8Gv1CRs6PWBtWZJDss_fh4A8R2guKRBcFwQIeoncFgQeFeaoA",
    "token_type" : "bearer",
    "id_token" : "eyJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI0OTUyOGQxNS1kZmEyLTQ1YTUtYjJiYy1hNzZhY2E2M2IwYjEiLCJleHAiOjE0NTI3NzUwNDQsIm5iZiI6MCwiaWF0IjoxNDUyNzc0OTg0LCJpc3MiOiJodHRwOi8vMTkyLjE2OC4wLjIzMDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsImF1ZCI6ImVkZ2UiLCJzdWIiOiJhNzE0NzAxNS0zNWM2LTRhZWEtYjNjOC1hNTY1ZTQ5YjcyZDkiLCJ0eXAiOiJJRCIsImF6cCI6ImVkZ2UiLCJzZXNzaW9uX3N0YXRlIjoiN2RkNWFkN2ItZDBhYi00ZmJhLWI5Y2ItZjM2NjFhOTk0ZTc5IiwibmFtZSI6IiIsInByZWZlcnJlZF91c2VybmFtZSI6ImFkbWluIn0.yOs1HGLQyV33ihDIzL4CiKlKj58zlZzNpJizOlWXg59DkdnL1W5RIT4-Jw5VToy267gWv1o0XIwI2oCVHjbaXKgWZzt7NlVdGnNyGL19VQUPlISlMyyoOhaBGufC4JycQ6BrQh0fnMYUVQOvGE6HGnVwUbrLHiVL579AVhUSmVZ052fzN4VySpm03L7eQBt6BTKMo_7fmL39WvdwY2gEhoi6rz2P8cXp8vbidwqb4nNF7C1wfM7GYgbO-1yaMq_c4JiOoga9YswD68XvKpjjwVZs2WvHpvwZrQjfiqa6EtxkTeRYncMW-RutB8P09wJ3WRaBooDreVBMFB2Tw6nWnQ",
    "not-before-policy" : 1452694301,
    "session-state" : "7dd5ad7b-d0ab-4fba-b9cb-f3661a994e79"
}

I now finally want to access some resource. As docs state, the only thing I want to do is to pass that access token in the Authorization header, starting with the Bearer keyword:

            HttpHeaders headers = new HttpHeaders();
            headers.set("Authorization", "Bearer " + token.getToken());
            HttpEntity<String> entity = new HttpEntity<>("parameters", headers);
            ResponseEntity rssResponse = template.exchange(
                    "http://192.168.0.230:8765/organization/organizations",
                    HttpMethod.GET,
                    entity,
                    OrganizationExchangeSet.class);

But I get 401 Unauthorized from keycloak. If I do the GET request using Postman, I get the Unauthorized code too:

Request:

Url:

http://192.168.0.230:8765/organization/organizations

Headers:

Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI5OTEzYmRjOS1jZmI0LTRlZjAtYTcxYy0yYWUwYmQ3MTkwZDkiLCJleHAiOjE0NTI3NzUwNDQsIm5iZiI6MCwiaWF0IjoxNDUyNzc0OTg0LCJpc3MiOiJodHRwOi8vMTkyLjE2OC4wLjIzMDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsImF1ZCI6ImVkZ2UiLCJzdWIiOiJhNzE0NzAxNS0zNWM2LTRhZWEtYjNjOC1hNTY1ZTQ5YjcyZDkiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJlZGdlIiwic2Vzc2lvbl9zdGF0ZSI6IjdkZDVhZDdiLWQwYWItNGZiYS1iOWNiLWYzNjYxYTk5NGU3OSIsImNsaWVudF9zZXNzaW9uIjoiZDg2MzY1NjctMzg2MS00NjU5LTg0ZjItMDZjYmM5YTI3YTU1IiwiYWxsb3dlZC1vcmlnaW5zIjpbXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIlNVUEVSX0FETUlOIiwiY3JlYXRlLXJlYWxtIiwiVklFV19PUkdBTklaQVRJT04iLCJST0xFX1RDSEVDS19TVVBFUl9BRE1JTiIsIlJPTEVfVENIRUNLX0FETUlOIiwiYWRtaW4iXX0sInJlc291cmNlX2FjY2VzcyI6eyJtYXN0ZXItcmVhbG0iOnsicm9sZXMiOlsibWFuYWdlLWV2ZW50cyIsInZpZXctcmVhbG0iLCJ2aWV3LWlkZW50aXR5LXByb3ZpZGVycyIsIm1hbmFnZS1yZWFsbSIsIm1hbmFnZS1pZGVudGl0eS1wcm92aWRlcnMiLCJpbXBlcnNvbmF0aW9uIiwidmlldy1ldmVudHMiLCJjcmVhdGUtY2xpZW50IiwibWFuYWdlLXVzZXJzIiwidmlldy11c2VycyIsInZpZXctY2xpZW50cyIsIm1hbmFnZS1jbGll bnRzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50Iiwidmlldy1wcm9maWxlIl19fSwibmFtZSI6IiIsInByZWZlcnJlZF91c2VybmFtZSI6ImFkbWluIn0.GMoAPe9aUQBRign5J0TvOt4tg1SWwyfJkvJjuWDZ_Ayj3GBnFjhgbjb5qLreKsm87NHymPcpvCv7uHkKJRsx44TjC0514O0oBSiVIiKfcJdbE-y7nPplzYAJF6I2JlsQkw9Na67vNSvhsBNg6AfBop4xpAF9HtTU7Ca7gFwOS01bgDRO09WlJYivzOd5t-vQGNwRVlTqaCstIMiBLaUfdkc82DNQwnoP5VO9R7xZn-7O5BE288_CX0C2V96_vooIoTbB3Qoa-gV6f3s6ZSyJnRGBgoe_2QY3mjCBarFQ_mKH_sbF2qMpm-a5igoNoD_3Xlc7iluP206ZJdQn4NZdQg

Response:

{
  "timestamp": 1452784544622,
  "status": 401,
  "error": "Unauthorized",
  "message": "Unable to authenticate bearer token",
  "path": "/organization/organizations"
}

How to solve this?


--
Aritz Maeztu Otaño
Departamento Desarrollo de Software

Pol. Ind. Mocholi. C/Rio Elorz, Nave 13E 31110 Noain (Navarra)
Telf.: 948 21 40 40
Fax.: 948 21 40 41

Antes de imprimir este e-mail piense bien si es necesario hacerlo: El medioambiente es cosa de todos.