Keycloak - Фактор Multi / 2FA - OTP - QR-код - Пользовательский экран входа в систему - Rest API

У меня есть собственная страница входа, на которой пользователь вводит имя пользователя и пароль. Это имя пользователя и пароль используются для входа через Keycloak Rest API.

http://localhost:8080/auth/realms/Demo/protocol/openid-connect/token

input - {username,password,grant_type,client_secret,client_id}

И в ответ получаю access token.

Теперь я хочу включить аутентификатор (Google Authenticator). Я включил его из бэкэнда. Теперь, если пользователь хочет войти в систему через мое приложение, на моей странице входа мне нужно получить данные ниже.

1.) Каким-то образом мне нужно включить QR-код, который появляется на странице входа в keycloak, после проверки имени пользователя / пароля, чтобы показывать на моем экране входа в первый раз, когда пользователь вводит имя пользователя / пароль. Итак, есть ли у нас какой-либо API, который в ответ возвращает изображение QR-кода Keycloak.

2.) При последующем входе в систему у меня будет поле OTP, поэтому потребуется REST api для передачи OTP вместе с именем пользователя / паролем.

Пожалуйста, помогите с REST API, если есть keycloak. Интеграция через Javascript.

Схема, аналогичная описанной в примере использования 1, здесь

Просто хочу использовать keycloak в качестве базы данных, выполняя все операции за меня, вводом будет мой экран. Я действительно хочу перенаправление URL-адресов при входе в систему, но при этом должен быть развернут автономно.


person Ankur Singhal    schedule 13.05.2018    source источник
comment
Keycloak уже имеет интеграцию OTP. Рассматривали ли вы использование потока кода авторизации (вход в систему с помощью страницы keycloak) вместо предоставления прямого доступа (что не рекомендуется, кстати)? Имейте в виду, что вы можете настроить страницу входа в keycloak. В противном случае вы можете выполнять довольно много дополнительной работы и вводить ошибки / проблемы с безопасностью, просто чтобы проксировать одну функцию, которую KC уже имеет в вашем приложении.   -  person Xtreme Biker    schedule 14.05.2018
comment
@XtremeBiker Привет, я проверил эту страницу, я могу выполнить интеграцию, используя пользовательский интерфейс входа администратора, проверяющий его с помощью Google Authenticator, я все еще хочу создать свой собственный пользовательский интерфейс и должен отображать QR-код на основе ответа keycloak.   -  person Ankur Singhal    schedule 14.05.2018
comment
Я также создал билет здесь   -  person Ankur Singhal    schedule 09.07.2018


Ответы (2)


Я знаю, что это старый вопрос, но я недавно смотрел на нечто подобное, и поэтому подумал, что было бы потенциально полезно поделиться тем, что я нашел, для других, которые, возможно, изучают это и задаются вопросом, каковы возможности.


TL; DR
Для этого можно использовать только существующие действия Keycloak или встроить страницу управления учетной записью пользователя по адресу https: // {URL-адрес сервера keycloak} / auth / realms / { имя области} / аккаунт в iframe. Боюсь, что все. На мой взгляд, в настоящее время лучше всего просто назначать действия непосредственно учетным записям или использовать электронные письма для сброса учетных данных для назначения действий; при желании оба из них могут быть выполнены через Admin API:

Отправить электронное письмо для сброса учетных данных, содержащее назначенные действия:
https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_executeactionsemail

Задайте действия непосредственно в учетной записи (включите действия в часть requiredActions пользовательского JSON, который вы отправляете в теле на конечную точку):
https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_updateuser


Предыстория заключается в том, что в рамках проекта, над которым я работал, мы хотели увидеть, можем ли мы иметь интегрированный способ для пользователей установить их начальный пароль и устройство OTP, когда для них была создана новая учетная запись, поскольку метод по умолчанию отправки им электронного письма из Keycloak с использованием функции сброса учетных данных имеет ограничения: а) он не предоставляет ссылку на само приложение, если вы не переопределите тему, и если у вас есть несколько экземпляров приложения для разных пользователей, у вас нет способ узнать, для какого экземпляра предоставить ссылку, поэтому, возможно, придется включить их список, и б) он часто не кажется действительно естественным для приложения, даже с изменениями в теме. Если вы разумны, я бы посоветовал вам остановиться и просто использовать эту функцию - подробности см. В разделе TL; DR выше.

Короче говоря, НЕТ конечной точки API для получения QR-кода для настройки OTP-устройства. Однако есть два места, где можно получить QR-код: экран настройки устройства OTP, когда вы входите в систему как пользователь, которому назначено действие «Настроить OTP», и экран управления собственной учетной записью пользователя.

Первый вариант экрана действия «Настроить одноразовый пароль» не запускается. Он отображается только при входе в систему, поэтому по определению пользователь должен войти в Keycloak через страницу входа в Keycloak, чтобы вызвать отображение страницы. На данный момент вы уже находитесь на странице Keycloak, а не на одной из страниц вашего приложения, и поэтому, если вы не можете проявить творческий подход к изменениям этих страниц Keycloak с помощью настраиваемой темы, нажатие на эту страницу на самом деле не вариант.

Второй вариант более интересен, но далек от идеала. Каждый вошедший в систему пользователь имеет доступ к странице управления учетной записью, которую можно найти по адресу https: // {URL-адрес сервера keycloak} / auth / realms / {realm name} / account. Эта страница позволяет вам делать такие вещи, как изменение вашего имени, пароля и т. Д., А также позволяет вам добавить устройство OTP, если у вас его еще нет, или удалить любые существующие устройства OTP, связанные с вашей учетной записью. К этой вкладке устройства OTP на странице управления учетной записью можно напрямую перейти по https: // {URL-адрес сервера keycloak} / auth / realms / {realm name} / account / totp.

Как я уже упоминал, не существует API, к которому вы можете получить доступ для просмотра QR-кода, отображаемого на этой странице. Доступ к нему возможен только через GET-запрос к https: // {keycloak URL-адрес сервера} / auth / realms / {realm name} / account / totp, который возвращает HTML-код для уже упомянутой страницы. Итак, можем ли мы программно очистить QR-код, а затем поместить его на нашу собственную страницу в нашем приложении? Эээ, нет, не совсем. Видите ли, хотя многие конечные точки API Keycloak по праву позволяют вам отправлять токен-носитель (например, токен доступа) в заголовке авторизации для доступа и конечной точки, эта страница не будет принимать токен-носитель в качестве средства аутентификации / авторизации. Вместо этого он использует файл cookie сеанса, который привязан к URL-адресу Keycloak. Этот файл cookie устанавливается, когда вы входите в свое приложение через страницу входа в Keycloak, и поэтому он доступен для этой страницы управления учетной записью, когда вы переходите к ней, когда вы уже вошли в систему, и поскольку страница управления учетной записью использует тот же сервер и доменное имя. как исходная страница входа в Keycloak, она имеет доступ к cookie и может позволить вам войти. Этот файл cookie не может быть отправлен вашим приложением, например, ваш собственный REST API, чтобы затем программно вызвать страницу управления учетной записью и очистить QR-код, потому что ваше приложение не имеет доступа к нему по соображениям безопасности. Это может быть что-то, что вы можете где-нибудь изменить в Keycloak, но если есть, я настоятельно рекомендую не менять это.

Итак, если мы не можем очистить страницу с нашего собственного сервера, можем ли мы что-то сделать во внешнем интерфейсе? Как уже упоминалось, ваше приложение не имеет доступа к cookie сеанса, но если вы сделаете запрос (например, используя fetch или axios) в своем интерфейсном JavaScript на странице управления учетной записью, тогда этот запрос отправит cookie вместе с ним. , так что это могло работать правильно? Умм, ну на самом деле вы получите сообщение об ошибке в этом сценарии из-за CORS. CORS - это Cross-Origin-Resource-Sharing, и для того, чтобы разрешить доступ к странице Keycloak, вам нужно будет открыть настройки на сервере, чтобы разрешить доступ к ней с адреса вашего веб-сайта. Я видел несколько статей, в которых рассказывается, как при желании открыть настройки CORS в Keycloak, но я бы очень нервничал по этому поводу. Я недостаточно знаю о внутреннем устройстве Keycloak и о том, как он работает, чтобы прокомментировать, насколько это опасно для безопасности, но я бы определенно не рекомендовал его. Здесь есть некоторая информация (Keycloak angular No 'Access-Control -Allow-Origin 'присутствует) при изменении настройки Web Origins в клиенте Keycloak вашего приложения, но это открывает ваше приложение для серьезных потенциальных злоупотреблений. Существует также ГЛАВНАЯ проблема, заключающаяся в том, что даже если вы соскребли QR-код, устройство фактически не добавляется в учетную запись пользователя (даже если оно отображается в приложении для проверки подлинности), пока вы не введете код на страницу, на которой находится QR-код. и щелкните Сохранить. Поскольку нет конечной точки API, которую можно было бы использовать для выполнения этой операции, я не думаю, что этот вариант также жизнеспособен. Я проверил, можете ли вы использовать конечную точку получения токена по адресу https: // {URL-адрес сервера keycloak} / auth / realms / {realm name} / protocol / openid-connect / token, чтобы узнать, отправляете ли вы запрос с вашим Имя пользователя / пароль / код otp каким-то образом зарегистрируют ваше устройство и завершат процесс, но хотя вы можете получить токен таким образом, и он не жалуется на код otp, он на самом деле не обращает внимания на код, потому что, как Что касается учетной записи пользователя, в ней нет зарегистрированного устройства. Поэтому нам нужно использовать форму на странице управления учетной записью, чтобы завершить этот процесс регистрации.

Итак, последний способ, возможно, сделать это ... iframe. Извините, да, это чушь, но это все, что у вас осталось. У вас может быть точка iframe на странице управления вашей учетной записью, и поскольку пользователь вошел в систему, он сможет видеть содержимое со страницы вашего приложения. Вы можете использовать относительное позиционирование, фиксированную ширину и высоту и удалить полосы прокрутки, чтобы отображать ТОЛЬКО QR-код и поля для одноразового кода, имени устройства и кнопок Сохранить / Отменить. К сожалению, это единственный вариант на данный момент, и из-за того, насколько неприятными и ненадежными могут быть в целом iframe - они определенно не кажутся родными для вашего приложения, и вам нужно переопределить тему Keycloak, чтобы получить страница, о которой идет речь, чтобы больше походить на ваше приложение - я бы рекомендовал избегать этого и использовать вместо этого стандартный подход с использованием действий Keycloak и Admin API.

Если вы зашли так далеко, поздравляем, вы выиграли в Stack Overflow :-)

person codeandchips    schedule 14.01.2021
comment
Мне удалось решить проблему, см. Ответ ниже =) - person Thomas Stubbe; 28.04.2021
comment
Спасибо, Томас. К сожалению, это не помогает в моей конкретной ситуации, поскольку я работаю с управляемым экземпляром, который я не контролирую - поэтому я избегал маршрута SPI - но надеюсь, что ваш ответ поможет кому-то другому :-) - person codeandchips; 23.07.2021

Мне удалось реализовать это через остальной API Keycloak. Чтобы реализовать это, вам нужно самостоятельно расширить Keycloak с помощью SPI. Для этого создайте свой собственный проект Java и расширьте org.keycloak.services.resource.RealmResourceProvider и org.keycloak.services.resource.RealmResourceProviderFactory. Дополнительную информацию можно найти в официальных документах (https://www.keycloak.org/docs/latest/server_development/#_extensions), примеры github и другие сообщения о переполнении стека, как это сделать.

После того, как вы это запустите, вы можете реализовать это следующим образом:

@GET
@Path("your-end-point-to-fetch-the-qr")
@Produces({MediaType.APPLICATION_JSON})
public YourDtoWithSecretAndQr get2FASetup(@PathParam("username") final String username) {
    final RealmModel realm = this.session.getContext().getRealm();
    final UserModel user = this.session.users().getUserByUsername(username, realm);
    final String totpSecret = HmacOTP.generateSecret(20);
    final String totpSecretQrCode = TotpUtils.qrCode(totpSecret, realm, user);
    return new YourDtoWithSecretAndQr(totpSecret, totpSecretQrCode);
}

@POST
@Path("your-end-point-to-setup-2fa")
@Consumes("application/json")
public void setup2FA(@PathParam("username") final String username, final YourDtoWithData dto) {
    final RealmModel realm = this.session.getContext().getRealm();
    final UserModel user = this.session.users().getUserByUsername(username, realm);
    final OTPCredentialModel otpCredentialModel = OTPCredentialModel.createFromPolicy(realm, dto.getSecret(), dto.getDeviceName());
    CredentialHelper.createOTPCredential(this.session, realm, user, dto.getInitialCode(), otpCredentialModel);
}

Секрет, полученный с помощью GET, должен быть отправлен обратно с помощью POST. Исходный код - это код вашего приложения 2FA (например, Google Authenticator). QR-код - это строка, которая может отображаться в img с помощью src 'data:image/png;base64,' + qrCodeString;

person Thomas Stubbe    schedule 28.04.2021