#android #keycloak #aerogear
#Android #скрытый ключ #aerogear
Вопрос:
Я хочу аутентифицировать пользователя (используя его имя пользователя и пароль) в приложении для Android, используя aerogear, с сервером, использующим Keycloak. Я не смог этого сделать, помогите мне, пожалуйста.
В настоящее время я могу аутентифицировать пользователя без aerogear, но я хочу использовать эту библиотеку, поскольку она может помочь мне обновить токен, когда это необходимо. Я аутентифицирую пользователя, выполняющего POST-вызов на сервер следующим образом (но с Android).:
curl -X POST http://127.0.0.1:8080/auth/realms/example/protocol/openid-connect/token
-H "Content-Type: application/x-www-form-urlencoded" -d "username=auser" -d 'password=apassword' -d 'grant_type=password'
-d 'client_id=clientId' -d 'client_secret=secret'
Итак, информация, которой я располагаю, такова:
- URL аутентификации,
ie http://127.0.0.1:8080/auth/realms/example/protocol/openid-connect/token
- имя пользователя, имя пользователя пользователя
- пароль, пароль пользователя
- client_id и client_secret сервера перехвата ключей
То, что я пробовал с Aerogear, это:
private void authz() {
try {
AuthzModule authzModule = AuthorizationManager.config("KeyCloakAuthz", OAuth2AuthorizationConfiguration.class)
.setBaseURL(new URL("http://127.0.0.1:8080/"))
.setAuthzEndpoint("/realms/example/protocol/openid-connect/auth")
.setAccessTokenEndpoint("/realms/example/protocol/openid-connect/token")
.setAccountId("keycloak-token")
.setClientId("clientId")
.setClientSecret("secret")
.setRedirectURL("http://oauth2callback")
.setScopes(Arrays.asList("openid"))
.addAdditionalAuthorizationParam((Pair.create("grant_type", "password")))
.addAdditionalAuthorizationParam((Pair.create("username", "aUserName")))
.addAdditionalAuthorizationParam((Pair.create("password", "aPassword")))
.asModule();
authzModule.requestAccess(this, new Callback<String>() {
@Override
public void onSuccess(String o) {
Log.d("TOKEN ", o);
}
@Override
public void onFailure(Exception e) {
System.err.println("Error!!");
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
}
});
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
Однако это ничего не дает. Чего я не понимаю, так это:
- Как я могу указать, что я делаю, и OpenID подключается к Keycloak в Aerogear?
- Как и куда я могу отправить имя пользователя и пароль?
- Как я могу указать grant_type? (Мой HTTP-ПОСТ на сервер не будет работать, если я не включу это, так что это важно)
Любая помощь была бы очень признательна
Комментарии:
1.Возможно, эти ресурсы могли бы помочь: aerogear.org/docs/guides/aerogear-android/authz github.com/aerogear/aerogear-android-cookbook/tree/master /…
2. Спасибо Вам, я просмотрел оба ресурса. На самом деле, код, который я представил, основан на второй ссылке, которую вы отправили, но я все еще не смог решить свою проблему. В любом случае спасибо 🙂
3. Пожалуйста. Не могли бы вы, пожалуйста, предоставить некоторую информацию о том, вызывается ли обратный вызов сбоя? Правильно ли настроен ваш Android-манифест? Кроме того, я полагаю, что вы не используете базовый URL-адрес 127.0.0.1 в своем клиенте Android, верно?
Ответ №1:
Если вы используете стандартный Authorization Code
поток с типом доступа = public client
(без clientSecret), вы можете взглянуть на мой пример родного приложения для Android.
Короче говоря, вы можете открыть окно браузера в a WebView
, получить authorization code
, проанализировав параметр запроса из возвращаемого URL-адреса, и обменять его (код) на токен с помощью POST-запроса.
Если вы используете Retrofit, то вот интерфейс REST:
interface IKeycloakRest {
@POST("token")
@FormUrlEncoded
fun grantNewAccessToken(
@Field("code") code: String,
@Field("client_id") clientId: String,
@Field("redirect_uri") uri: String,
@Field("grant_type") grantType: String = "authorization_code"
): Observable<KeycloakToken>
@POST("token")
@FormUrlEncoded
fun refreshAccessToken(
@Field("refresh_token") refreshToken: String,
@Field("client_id") clientId: String,
@Field("grant_type") grantType: String = "refresh_token"
): Observable<KeycloakToken>
@POST("logout")
@FormUrlEncoded
fun logout(
@Field("client_id") clientId: String,
@Field("refresh_token") refreshToken: String
): Completable
}
data class KeycloakToken(
@SerializedName("access_token") var accessToken: String? = null,
@SerializedName("expires_in") var expiresIn: Int? = null,
@SerializedName("refresh_expires_in") var refreshExpiresIn: Int? = null,
@SerializedName("refresh_token") var refreshToken: String? = null
)
И его создание:
val rest: IKeycloakRest = Retrofit.Builder()
.baseUrl("https://[KEYCLOAK-URL]/auth/realms/[REALM]/protocol/openid-connect/")
.addConverterFactory(GsonConverterFactory.create(GsonBuilder().setLenient().create()))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
.create(IKeycloakRest::class.java)
Комментарии:
1. как добавить идентификатор устройства в код авторизации для добавления в заявку jwt?
Ответ №2:
Я тоже использую AeroGear, и я заметил, что у меня была та же проблема. Затем я сделал (помимо другой информации о конфигурации, как сказал Толис Эммануилидис) добавление службы аутентификации в ваш манифест.
Попробуйте добавить <service android:name="org.jboss.aerogear.android.authorization.oauth2.OAuth2AuthzService"/>
в свой манифест
Как только вы это сделаете, он заработает должным образом, и вы сможете получить токен на предъявителя.
Ответ №3:
я реализовал это в своем проекте внутри моего класса keycloakHelper.
public class KeycloakHelper {
static
{
try
{
AuthorizationManager
.config("KeyCloakAuthz", OAuth2AuthorizationConfiguration.class)
.setBaseURL(new URL(EndPoints.HTTP.AUTH_BASE_URL))
.setAuthzEndpoint("/auth/realms/***/protocol/openid-connect/auth")
.setAccessTokenEndpoint("/auth/realms/ujuzy/protocol/openid-connect/token")
.setRefreshEndpoint("/auth/realms/***/protocol/openid-connect/token")
.setAccountId("account")
.setClientId("account")
.setRedirectURL("your base url")
.addAdditionalAuthorizationParam((Pair.create("grant_type", "password")))
.asModule();
PipeManager.config("kc-upload", RestfulPipeConfiguration.class)
.module(AuthorizationManager.getModule("KeyCloakAuthz"))
.requestBuilder(new MultipartRequestBuilder());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void connect(final Activity activity, final Callback callback)
{
if (!DetectConnection.checkInternetConnection(activity))
return;
try {
final AuthzModule authzModule = AuthorizationManager.getModule("KeyCloakAuthz");
authzModule.requestAccess(activity, new Callback<String>()
{
@SuppressWarnings("unchecked")
@Override
public void onSuccess(String s)
{
callback.onSuccess(s);
}
@Override
public void onFailure(Exception e)
{
// authzModule.refreshAccess();
authzModule.isAuthorized();
if (!e.getMessage().matches(OAuthWebViewDialog.OAuthReceiver.DISMISS_ERROR))
{
//authzModule.refreshAccess();
authzModule.deleteAccount();
}
callback.onFailure(e);
}
});
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static boolean isConnected()
{
return AuthorizationManager.getModule("KeyCloakAuthz").isAuthorized();
}
}
Когда вы хотите, чтобы пользователь вошел в систему (введите адрес электронной почты и пароль)
public void LoginUser() {
KeycloakHelper.connect(getActivity(), new Callback() {
@Override
public void onSuccess(Object o) {
//YOU WILL GET YOUR TOKEN HERE IF USER IS ALREADY SIGNED IN.
//IF USER IS NOT SIGNED IN, AEROGEAR WILL PROMPT A WEBVIEW DIALOG
//WHERE THE USER WILL INPUT THERE EMAIL AND PASSWORD
}
@Override
public void onFailure(Exception e) {
}
});
}
Счастливого кодирования 🙂