【问题标题】:How to implement OAuth2 authorization on Android如何在 Android 上实现 OAuth2 授权
【发布时间】:2019-04-17 09:35:08
【问题描述】:

我需要在我的应用中添加 OAuth2 授权。我只有客户端 ID、客户端密码和用户名(电子邮件)。我需要得到令牌。你能给我一些建议吗?库或示例代码?

【问题讨论】:

    标签: android oauth-2.0


    【解决方案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);
    }
    

    【讨论】:

    • 这是推荐用于 Android 的方法吗?我曾经认为移动设备可以使用设备的默认 Web 浏览器作为用户代理来处理代码和令牌重定向。最近有变化吗?
    • AppAuth 是 Google 推荐的。它使用 Chrome 自定义选项卡进行授权请求。与设备的默认网络浏览器相比,Chrome 自定义标签有一些优势。例如,自定义选项卡与最后显示的活动重叠。 (请参阅 Google 的以下演讲:youtu.be/DdQTXrk6YTk?t=220
    猜你喜欢
    • 2018-11-04
    • 2017-08-30
    • 1970-01-01
    • 1970-01-01
    • 2018-10-28
    • 1970-01-01
    • 2015-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多