Android oAuth for Uber API - SSO与INVALID_APP_SIGNATURE挂起

时间:2018-01-10 18:17:47

标签: android uber-api

目标:使用Uber API SSO登录,检索授权令牌,在TokenManager中存储身份验证令牌。但首先,我很高兴获得令牌。 假设:我的应用程序将在安装了Uber应用程序的Androids上运行。

考虑到客观和假设 - 我相信我不需要"后端"那是对的吗?一旦我获得了身份验证令牌,我将通过SSO使用它来请求乘坐。

我在下面发布了我的代码。请帮忙。 (我注释掉了onResume代码,因为,现在,我只是想让初始登录工作。)我的代码主要基于Uber提供的样本here

我有一个优步API客户端ID,因为我填充了优步开发者网站here我也将我的AndroidDebug哈希密钥发布到此网站。

我的手机上安装了Uber。

当我在手机上运行下面的应用程序(不是模拟器)并点击按钮时,有时会出现黑色Uber-logo应用程序屏幕,变为白色并无限期挂起。 有时会出现一个白色屏幕,说连接有问题。当我按下UBer-present" Okay"按钮Uber屏幕恢复到我的应用程序。我的应用程序捕获错误(请参阅onLoginError)并将其Toast to" INVALID_APP_SIGNATURE"运行Android Studio我无法使用断点捕获返回值。英国石油公司已经确定但它从未开火。

BTW我知道至少部分Uber API凭证是正确的。我使用Postman来请求令牌并提供scope = request并获得令牌。但是,我认识到通过Postman这样做可能不会打击Uber API SSO。

根据我的阅读,上面的错误字符串以及应用程序的反应方式,这看起来像一个openSSL / hash / key问题,但我的hashkey适用于Facebook登录。

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mGoButton = (Button) findViewById(R.id.goBtn);

    configuration = new SessionConfiguration.Builder()
            .setClientId(CLIENT_ID)
            .setRedirectUri(REDIRECT_URI)
            .setScopes(Arrays.asList(Scope.RIDE_WIDGETS, Scope.REQUEST, Scope.PROFILE))
            .setEnvironment(SessionConfiguration.Environment.PRODUCTION)
            //.setEnvironment(SessionConfiguration.Environment.SANDBOX)
            .build();

    accessTokenStorage = new AccessTokenManager(getApplicationContext());
    accessTokenManager = new AccessTokenManager(getApplicationContext());
    Long expirationTime = 2592000L;
    List<Scope> scopes = Arrays.asList(Scope.RIDE_WIDGETS);
    String token = "obtainedAccessToken";
    String refreshToken = "obtainedRefreshToken";
    String tokenType = "obtainedTokenType";
    accessToken = new AccessToken(expirationTime, scopes, token, refreshToken, tokenType);
    accessTokenStorage.setAccessToken(accessToken);

    //Use a custom button with an onClickListener to call the LoginManager directly
    loginManager = new LoginManager(accessTokenManager,
            new SampleLoginCallback(),
            configuration,
            CUSTOM_BUTTON_REQUEST_CODE);

    loginManager.setRedirectForAuthorizationCode(true);

    mGoButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            loginManager.login(MainActivity.this);
        }
    });
}

@Override
protected void onResume() {
    super.onResume();
    //if (loginManager.isAuthenticated()) {
    //    loadProfileInfo();
    //}
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    Log.i(LOG_TAG, String.format("onActivityResult requestCode:[%s] resultCode [%s]",
            requestCode, resultCode));
    loginManager.onActivityResult(this, requestCode, resultCode, data);
}

private class SampleLoginCallback implements LoginCallback {

    @Override
    public void onLoginCancel() {
        Toast.makeText(MainActivity.this, R.string.user_cancels_message, Toast.LENGTH_LONG).show();
    }
    @Override
    public void onLoginError(@NonNull AuthenticationError error) {
        int a = 1;
        Toast.makeText(MainActivity.this,
                    getString(R.string.login_error_message, error.name()), Toast.LENGTH_LONG)
                    .show();
        }
    @Override
    public void onLoginSuccess(@NonNull AccessToken accessToken) {
        loadProfileInfo();
    }
    @Override
    public void onAuthorizationCodeReceived(@NonNull String authorizationCode) {
        Toast.makeText(MainActivity.this, getString(R.string.authorization_code_message, authorizationCode),
            Toast.LENGTH_LONG)
            .show();
    }
}

当我在我的环境中复制/粘贴代码时的Sasa(Android Studio)我得到下面的红线/错误,因为它将LoginManger调用中的第一个参数更改为tokenStorage vs tokenManager。 IDE将错误称为必需参数和提供的参数之间的不匹配。

enter image description here

这是我的构建gradle

enter image description here

1 个答案:

答案 0 :(得分:1)

我设法重现了你的问题。问题肯定在于生成签名证书的哈希值。

要获取签名证书的哈希值,请运行此命令,其中包含密钥的别名和密钥库的路径:

  

keytool -exportcert -alias androiddebugkey -keystore   〜/ .android / debug.keystore | openssl sha1 -binary | openssl base64

默认情况下,调试密钥库的密码为空。

也不确定为什么你有两个AccessTokenManager实例。您的代码应如下所示:

configuration = new SessionConfiguration.Builder()
            .setClientId(CLIENT_ID)
            .setRedirectUri(REDIRECT_URI)
            .setScopes(Arrays.asList(Scope.RIDE_WIDGETS, Scope.REQUEST, Scope.PROFILE))
            .setEnvironment(SessionConfiguration.Environment.PRODUCTION)
            //.setEnvironment(SessionConfiguration.Environment.SANDBOX)
            .build();

accessTokenStorage = new AccessTokenManager(this);
loginManager = new LoginManager(accessTokenStorage,
            new SampleLoginCallback(),
            configuration,
            CUSTOM_BUTTON_REQUEST_CODE);

    loginManager.setRedirectForAuthorizationCode(true);

    customButton = (Button) findViewById(R.id.custom_uber_button);
    customButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            loginManager.login(LoginSampleActivity.this);
        }
    });

我添加了新按钮&#34;测试登录&#34; - 执行上面的代码 - 然后进入Scope Authorization页面 - 并完成身份验证。

enter image description here

enter image description here

登录示例应用程序的构建gradle文件如下所示:

buildscript {
repositories {
    jcenter()
    google()
}

dependencies {
    classpath deps.build.gradlePlugins.android
}
}

apply plugin: 'com.android.application'

android {
compileSdkVersion deps.build.compileSdkVersion
buildToolsVersion deps.build.buildToolsVersion

defaultConfig {
    minSdkVersion deps.build.minSdkVersion
    targetSdkVersion deps.build.targetSdkVersion
    buildConfigField "String", "CLIENT_ID", "\"${loadSecret("UBER_CLIENT_ID")}\"" //Add your client id to gradle.properties
    buildConfigField "String", "REDIRECT_URI", "\"${loadSecret("UBER_REDIRECT_URI")}\"" //Add your redirect uri to gradle.properties
}
compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_7
    targetCompatibility JavaVersion.VERSION_1_7
}
}

dependencies {
compile project(':rides-android')
compile deps.support.appCompat
}

/**
* Loads property from gradle.properties and ~/.gradle/gradle.properties
* Use to look up confidential information like keys that shoudln't be stored publicly
* @param name to lookup
* @return the value of the property or "MISSING"
*/
def loadSecret(String name) {
return hasProperty(name) ? getProperty(name) : "MISSING"
}