需要帮助使用 Google Oauth 和 Android 配置 Django Rest API

Posted

技术标签:

【中文标题】需要帮助使用 Google Oauth 和 Android 配置 Django Rest API【英文标题】:Need help configuring Django Rest API with Google Oauth and Android 【发布时间】:2020-09-11 16:21:40 【问题描述】:

我正在尝试配置我的 django rest API 以使用 google 登录 OAuth 和 django-rest-framework-social-oauth2

我已经看到this question,但我似乎无法弄清楚他们是如何检索到 access_token 的

我到目前为止所尝试的遵循this指南:

console.developers.google.com开始了一个新项目

添加到settings.py:

SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = '2377[...].apps.googleusercontent.com'
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = '[...]'
SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE = ['email']

INSTALLED_APPS = [
    ...
    # oauth
    'oauth2_provider',
    'social_django',
    'rest_framework_social_oauth2'
]

AUTHENTICATION_BACKENDS = (
    # Google OAuth2
    'social_core.backends.google.GoogleOAuth2',

    # django-rest-framework-social-oauth2
    'rest_framework_social_oauth2.backends.DjangoOAuth2',

    # Django
    'django.contrib.auth.backends.ModelBackend',
)

但是当我尝试交换我的身份验证码时,我是从 android 上的 Google 登录获得的

gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestServerAuthCode(Values.CLIENT_ID_WEB_APP)
            .requestEmail()
            .build();

在我的 Django Rest API 后端使用访问令牌

OkHttpClient client = new OkHttpClient();
RequestBody requestBody = new FormEncodingBuilder()
    .add("grant_type", "convert_token")
    .add("client_id", Values.CLIENT_ID_REST_APP)
    .add("client_secret", Values.CLIENT_SECRET_REST_APP)
    .add("backend", "google-oauth2")
    .add("token", idToken)
    .build();

我从服务器收到 400 HTTP 响应:

"error":"access_denied","error_description":"您的凭据不被允许"

我错过了什么吗?提前致谢!

【问题讨论】:

【参考方案1】:

一旦从管理员中删除我的应用程序并创建一个新应用程序,我就可以使用它了。另外,我删除了除管理员用户之外的所有用户。

在我的情况下,我在 settings.py 文件中有这些更改:

SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = '1234565432-n9vf123456perna7o1oungbqhp6rcl.apps.googleusercontent.com'
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = '123456trewBNqTL_or38'


SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE = [
    'https://www.googleapis.com/auth/userinfo.email',
    'https://www.googleapis.com/auth/userinfo.profile',
]
INSTALLED_APPS = [
    ...
    # Social auth
    'oauth2_provider',
    'social_django',
    'rest_framework_social_oauth2',
]
AUTHENTICATION_BACKENDS = (
    'social_core.backends.google.GoogleOAuth2',
    'rest_framework_social_oauth2.backends.DjangoOAuth2',
    'django.contrib.auth.backends.ModelBackend',
)

在 Android 方面我有:

override fun onCreate(savedInstanceState: Bundle?) 
    ...
    val serverClientId = getString(R.string.default_web_client_id)
        val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestIdToken(serverClientId)
            .requestServerAuthCode(serverClientId)
            .requestEmail()
            .build()


    googleSignInClient = GoogleSignIn.getClient(this, so)

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) 
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == RC_SIGN_IN) 
            val task = GoogleSignIn.getSignedInAccountFromIntent(data)
            try 
                val account = task.getResult(ApiException::class.java)
                account?.let 
                    firebaseAuthWithGoogle(it)
                
             catch (e: ApiException) 
                Log.w(TAG, "Google sign in failed", e)
            
        
    
private fun firebaseAuthWithGoogle(account: GoogleSignInAccount) 
        val credential = GoogleAuthProvider.getCredential(account.idToken, null)
        mAuth.signInWithCredential(credential)
            .addOnCompleteListener(this)  task ->
                if (task.isSuccessful) 
                    val user = mAuth.currentUser
                    Toast.makeText(this, "Authentication Success.", Toast.LENGTH_SHORT).show()
                    getGoogleAccessToken(account.idToken, account.serverAuthCode)
                 else 
                    Toast.makeText(this, "Authentication Failed.", Toast.LENGTH_SHORT).show()
                
            
    

getGoogleAccessToken 是对 https://www.googleapis.com/oauth2/v4/token/ URL 的 Google 访问令牌的改造 API 调用。

val call = apiInterface?.getAccessToken(
            id_token = tokenId,
            authCode = authCode,
            response_type = "Code",
            redirect_uri = "",
            grant_type = "authorization_code",
            client_id = getString(R.string.default_web_client_id),
            client_secret = getString(R.string.server_client_secret)
        )

API 的响应带有访问令牌。

data class GoogleSignInAccessTokenDataClass(
val access_token: String,
val expires_in: Int,
val id_token: String,
val token_type: String
)

【讨论】:

以上是关于需要帮助使用 Google Oauth 和 Android 配置 Django Rest API的主要内容,如果未能解决你的问题,请参考以下文章

具有多个用户帐户的Google Drive SDK OAuth2

如何 oAuth 和 SOAP?

Apache Oltu Spring Security OAuth2 和 Google 集成

(403) 请求的身份验证范围不足 - OAuth 范围 Google Clas-s-room API

Java 中的 Google 通讯录 v3 API 和 OAuth v2

使用 JavaScript 的服务器到服务器应用程序的 OAuth 2.0