Как реализовать авторизацию OAuth2 на Android

#android #oauth-2.0

#Android #oauth-2.0

Вопрос:

Мне нужно добавить авторизацию OAuth2 в мое приложение. У меня есть только идентификатор клиента, секрет клиента и имя пользователя (email). Мне нужно получить токен. Можете ли вы дать мне несколько советов о том, как это сделать? Библиотека или пример кода?

Ответ №1:

Вы можете использовать AppAuth для авторизации OAuth2.

Смотрите https://github.com/openid/AppAuth-Android для примера.


Ниже приведена сокращенная версия документации AppAuth.

Обзор

Рекомендуется, чтобы собственные приложения использовали поток кода авторизации.

Этот поток фактически состоит из четырех этапов:

  1. Указание конфигурации службы авторизации.
  2. Авторизация через браузер, чтобы получить код авторизации.
  3. Обмен кодом авторизации для получения токена доступа и обновления.
  4. Использование токена доступа для доступа к службе защищенных ресурсов.

1. Создайте конфигурацию службы авторизации

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

 AuthorizationServiceConfiguration mServiceConfiguration =
    new AuthorizationServiceConfiguration(
        Uri.parse("https://example.com/authorize"), // Authorization endpoint
        Uri.parse("https://example.com/token")); // Token endpoint

ClientAuthentication mClientAuthentication =
    new ClientSecretBasic("my-client-secret"); // Client secret
 

(Статические клиентские секреты не рекомендуются в собственных приложениях.)

2. Запросить авторизацию и получить код авторизации

Чтобы получить обратный вызов авторизации, определите следующее действие в вашем файле манифеста. (Вам не нужно выполнять это действие. Это действие будет действовать как прокси для вашего запроса на авторизацию.)

 <activity
        android:name="net.openid.appauth.RedirectUriReceiverActivity"
        tools:node="replace">
    <intent-filter>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>
        <data android:scheme="com.example"/> <!-- Redirect URI scheme -->
    </intent-filter>
</activity>
 

Создайте и выполните запрос авторизации.

 private void authorize() {
    AuthorizationRequest authRequest = new AuthorizationRequest.Builder(
        mServiceConfiguration,
        "my-client-id", // Client ID
        ResponseTypeValues.CODE,
        Uri.parse("com.example://oauth-callback") // Redirect URI
    ).build();

    AuthorizationService service = new AuthorizationService(this);

    Intent intent = service.getAuthorizationRequestIntent(authRequest);
    startActivityForResult(intent, REQUEST_CODE_AUTH);
}
 

Обработайте ответ авторизации.

 @Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    if (requestCode != REQUEST_CODE_AUTH) {
        return;
    }

    AuthorizationResponse authResponse = AuthorizationResponse.fromIntent(intent);
    AuthorizationException authException = AuthorizationException.fromIntent(intent);

    mAuthState = new AuthState(authResponse, authException);

    // Handle authorization response error here

    retrieveTokens(authResponse);
}
 

3. Обменяйте код авторизации

 private void retrieveTokens(AuthorizationResponse authResponse) {
    TokenRequest tokenRequest = response.createTokenExchangeRequest();

    AuthorizationService service = new AuthorizationService(this);

    service.performTokenRequest(request, mClientAuthentication,
            new AuthorizationService.TokenResponseCallback() {
        @Override
        public void onTokenRequestCompleted(TokenResponse tokenResponse,
                AuthorizationException tokenException) {
            mAuthState.update(tokenResponse, tokenException);

            // Handle token response error here

            persistAuthState(mAuthState);
        }
    });
}
 

После успешного завершения извлечения токена сохраняйте AuthState его, чтобы вы могли повторно использовать его при следующем (повторном) запуске приложения.

4. Доступ к службе защищенных ресурсов

Используется performActionWithFreshTokens для выполнения вызова API с новым токеном доступа. (Это автоматически гарантирует, что токены свежие, и обновляет их при необходимости.)

 private void prepareApiCall() {
    AuthorizationService service = new AuthorizationService(this);

    mAuthState.performActionWithFreshTokens(service, mClientAuthentication,
            new AuthState.AuthStateAction() {
        @Override
        public void execute(String accessToken, String idToken,
                AuthorizationException authException) {
            // Handle token refresh error here

            executeApiCall(accessToken);
        }
    });
}
 

Выполните вызов API. ( AsyncTask Это просто используется для простоты. Возможно, это не лучшее решение для выполнения вызова API.)

 private void executeApiCall(String accessToken) {
    new AsyncTask<String, Void, String>() {
        @Override
        protected String doInBackground(String... params) {
            OkHttpClient client = new OkHttpClient();
            Request request = new Request.Builder()
                    .url("https://example.com/api/...") // API URL
                    .addHeader("Authorization",
                            String.format("Bearer %s", params[0]))
                    .build();

            try {
                Response response = client.newCall(request).execute();
                return response.body().string();
            } catch (Exception e) {
                // Handle API error here
            }
        }

        @Override
        protected void onPostExecute(String response) {
            ...
        }
    }.execute(accessToken);
}
 

Комментарии:

1. Это рекомендуемый подход для Android? Раньше я думал, что мобильные устройства могут использовать веб-браузер устройства по умолчанию в качестве агента пользователя для обработки перенаправления кода и токена. Изменилось ли это в последнее время?

2. AppAuth рекомендован Google. Он использует пользовательские вкладки Chrome для запроса авторизации. Пользовательские вкладки Chrome имеют некоторые преимущества по сравнению с веб-браузером устройства по умолчанию. Например, пользовательская вкладка перекрывает последнюю показанную активность. (Смотрите следующий доклад от Google: youtu.be/DdQTXrk6YTk?t=220 )