Short intro: here you can find an example - how to work with IDCS (receive oauth token, query for users and group) from Java using Jersey lib
Пришлось разобраться с тем, как работать с Identity Cloud Service REST API из Java. Несмотря на то, что IDCS REST API хорошо документирован, а работа с API хорошо описана в соответствующих обучающих материалах и имеется коллекция REST запросов для Postman, мне пришлось немного поработать, чтобы "подружить" IDCS REST API с Java при помощи библиотек Jersey для вызова REST сервисов. Под катом - пример Java программы с комментариями.
Пришлось разобраться с тем, как работать с Identity Cloud Service REST API из Java. Несмотря на то, что IDCS REST API хорошо документирован, а работа с API хорошо описана в соответствующих обучающих материалах и имеется коллекция REST запросов для Postman, мне пришлось немного поработать, чтобы "подружить" IDCS REST API с Java при помощи библиотек Jersey для вызова REST сервисов. Под катом - пример Java программы с комментариями.
Для доступа к IDCS мы зарегистрируем приложение. Как
это сделать, подробно рассказано в IDCS Workshop. Нужно зайти в IDCS Admin Console, перейти в Applications, нажать Add для добавления нового приложения, выбрать Confidential Application. URL можно не
заполнять, а на шаге Client нужно убедиться, что отмечена «галочка» Client Credentials (программа для соединения будет использовать ClientID и Client Secret).
Также укажите
доступные приложению внутри IDCS полномочия (я выделил все, но в-целом можно выделить лишь некоторые).
В итоге вы должны получить значение ClientID и Client Secret, наподобие показанного ниже. Эти значения будут использоваться для аутентификации нашей программы в IDCS.
Таким образом, вы
создали приложение в IDCS, из-под
которого будет выполнять соединение ваша программа. Теперь нам нужно написать Java код, который будет соответствующим
образом вызывать REST сервисы IDCS. Существуют
разные способы вызова REST API из Java, я буду использовать библиотеки Jersey (https://jersey.github.io/). Для начала вам
необходимо скачать библиотеки отсюда (https://jersey.github.io/download.html) и включить их в CLASSPATH.
Дальше разберем Java код. Следующий код используется для получения токена аутентификации.Токен по умолчанию действителен один час. Вам потребуется заменить IDCS URL и ваши значения ClientID и Client Secret, указанные в переменной authcred в формате ClientID:ClientSecret. Это значение потом кодируется в Base64 и подставляется как Basic аутентификация, запрос - HTTP POST.
Encoder encoder = Base64.getEncoder();
String authcred = "5a01c43d6XXXXXXX80bb0cf64d667b3e:3e8eb730-94XXXXXXX39d895b63758";
String authcred64 = encoder.encodeToString(authcred.getBytes());
System.out.println("auth cred: " + authcred64);
// authorization, get bearer
MultivaluedMap formData = new MultivaluedHashMap();
formData.add("grant_type", "client_credentials");
formData.add("scope", "urn:opc:idm:__myscopes__");
Client client = ClientBuilder.newClient();
WebTarget webTarget = client.target("https://idcs-fa04eXXXXXXXe5f5c007167.identity.oraclecloud.com");
Response resp = webTarget.path("oauth2/v1/token").request().header("Content-Type", "application/x-www-form-urlencoded")
.header("X-RESOURCE-IDENTITY-DOMAIN-NAME", "cissandbox")
.header("Authorization", "Basic " + authcred64)
.post(Entity.form(formData));
System.out.println("Resp: " + resp.toString() + "\n");
Отладочный вывод покажет, как именно выглядит токен аутентификации (access_token).
Далее вытащим атрибуты из полученного ответа:
HashMap respData = resp.readEntity(HashMap.class);
String accessToken = (String)respData.get("access_token");
String tokenType = (String)respData.get("token_type");
BigDecimal expiresIn = (BigDecimal)respData.get("expires_in");
System.out.println("access_token = " + accessToken);
System.out.println("token_type = " + tokenType);
System.out.println("expires_in = " + expiresIn);
resp.close();
Теперь полученный токен можно использовать при вызове REST API IDCS. Например, выведем всех зарегистрированных пользователей, указав "Bearer + access_token" в заголовке Authorization.
// USER operations - get ALL users
resp = webTarget.path("admin/v1/Users").
request().
header("Authorization", "Bearer " + accessToken).
get();
System.out.println("Resp: " + resp.toString() + "\n" + resp.readEntity(String.class));
resp.close();
Отладочный вывод:
Просто? Интереснее (пришлось поработать) заставить работать фильтр поиска, синтаксис которого отличается от описанного в документации (в Query нельзя вставлять "+") и необхдимо использовать UriComponent.encode с соответствующими параметрами для корректной кодировки параметра запроса HTTP GET.
// USER operations - search
String filter = "userName eq \"oleg.faynitskiy@oracle.com\"";
System.out.println("filter: " + filter);
resp = webTarget.path("admin/v1/Users").
queryParam("filter", UriComponent.encode(filter, UriComponent.Type.QUERY_PARAM_SPACE_ENCODED)).
request().
header("Authorization", "Bearer " + accessToken).
get();
System.out.println("Resp: " + resp.toString());
respData = resp.readEntity(HashMap.class);
BigDecimal totalResults = (BigDecimal)respData.get("totalResults");
System.out.println("Totalresults: " + totalResults);
if(totalResults.intValue() > 0) {
System.out.println(totalResults + " user(s) found");
} else {
throw new Exception("No users found with filter " + filter);
}
// at least one user found
ArrayList users = (ArrayList)respData.get("Resources");
HashMap user = (HashMap)users.get(0);
System.out.println("Processing user: " + user.get("userName"));
Iterator it = user.keySet().iterator();
while(it.hasNext()) {
String key = (String)it.next();
System.out.println("user." + key + " = " + user.get(key));
}
ArrayList emails = (ArrayList)user.get("emails");
HashMap email = (HashMap)emails.get(0);
System.out.println("\nuser email: " + email.get("value"));
resp.close();
Отладочный вывод:
Целиком исходник Java класса, где помимо чтения и поиска пользователей показано чтение и поиск групп, членства в группах, вы можете получить тут.
Напоследок замечу, что большая часть IDCS REST API реализует стандарт SCIM (http://www.simplecloud.info/), это верно для используемых в данном примере endpoint'ов /Users и /Groups.
No comments:
Post a Comment