Gmail Api 请求的身份验证范围不足

Posted

技术标签:

【中文标题】Gmail Api 请求的身份验证范围不足【英文标题】:Gmail Api Request had insufficient authentication scopes 【发布时间】:2021-10-20 20:40:38 【问题描述】:

我正在尝试使用 Gmail API 阅读电子邮件,但遇到了权限不足的问题。

注意:我已将范围设置为阅读电子邮件。

ManiFestFile.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hatsoff.glogin">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/Theme.GLogin">
    <activity
        android:name=".MainActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

我创建了GoogleSignInOptions 来动态获取电子邮件地址或用户。

  //assign googleAuth
    googleAuth = new GoogleAuth();
    // request for google email
    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestScopes(new Scope(Scopes.DRIVE_APPFOLDER))
            .requestIdToken(getString(R.string.server_client_id))
            .requestServerAuthCode(getString(R.string.server_client_id))
            .requestEmail()
            .build();
    // google_signing object to store gso.
    mGoogleSignInClient = GoogleSignIn.getClient(getApplicationContext(), gso);

当用户从 gsoGoogleSignInOptions 对话框中选择 GoogleAccount 时调用此 someActivityResultLauncher。

        //google Dialog click event
    someActivityResultLauncher = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            new ActivityResultCallback<ActivityResult>() 
                @Override
                public void onActivityResult(ActivityResult result) 
                    if (result.getResultCode() == RESULT_OK) 
                        System.out.println("ActivityResult: " + result.getResultCode());
                        Intent data = result.getData();
                        Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
                        authCode = googleAuth.handleSignInResult(task);
                        if (authCode != null) 
                            // Signed in successfully
                            // save AuthCode to sharedPref
                        
                     else 
                        System.out.println("ActivityResult: " + result.getResultCode());
                    
                
            );

要获取 AccessToken,我使用的是GoogleTokenResponse

ReadEmail 类

    public class ReadMails extends AsyncTask<String, Void, String> 
    @Override
    protected String doInBackground(String... strings) 
        SharedPreferences AuthCodePre = getSharedPreferences("oAuth", MODE_PRIVATE);
        if (!AuthCodePre.getString("Auth", "").equals("")) 
            try 
                String MailBody = "";
                // Load client secrets.
                AssetManager am = getAssets();
                InputStream in = am.open("credentials.json");
                if (in == null) 
                    throw new FileNotFoundException("Resource not found: " + in);
                
                GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
                final NetHttpTransport HTTP_TRANSPORT = new com.google.api.client.http.javanet.NetHttpTransport();
                GoogleTokenResponse tokenResponse =
                        new GoogleAuthorizationCodeTokenRequest(
                                HTTP_TRANSPORT,
                                JSON_FACTORY,
                                "https://oauth2.googleapis.com/token",
                                clientSecrets.getDetails().getClientId(),
                                clientSecrets.getDetails().getClientSecret(),
                                AuthCodePre.getString("Auth", ""),
                                "http://localhost")
                                .setScopes(Arrays.asList(SCOPES))
                                .execute();

                String accessToken = tokenResponse.getAccessToken();
                // Use access token to call API
                Credential credential = new GoogleCredential.Builder().setTransport(new com.google.api.client.http.javanet.NetHttpTransport())
                        .setJsonFactory(JSON_FACTORY)
                        .setClientSecrets(clientSecrets.getDetails().getClientId(), clientSecrets.getDetails().getClientSecret())
                        .build()
                        .setAccessToken(accessToken);

                // Build a new authorized API client service.
                Gmail service = new Gmail.Builder(new NetHttpTransport(), JacksonFactory.getDefaultInstance(), credential)
                        .setApplicationName(APPLICATION_NAME)
                        .build();
                //Access gmail inbox
                Gmail.Users.Messages.List RequestList = service.users().messages().list(user).setQ("from:abcd@gmail.com");
                ListMessagesResponse listMessagesResponse = RequestList.setMaxResults(100L).execute();
                RequestList.setPageToken(listMessagesResponse.getNextPageToken());

                //Get id of search email
                for (int i = 0; i < listMessagesResponse.getMessages().size(); i++) 
                    String SEmailID = listMessagesResponse.getMessages().get(i).getId();
                    com.google.api.services.gmail.model.Message message = service.users().messages().get(user, SEmailID).execute();
                    //read email body
                    MessagePart msgpart = message.getPayload();
                    List<MessagePart> bodyParts = new ArrayList<>();
                    bodyParts.add(msgpart);
                    for (int j = 0; j < bodyParts.size(); j++) 
                        MailBody = StringUtils.newStringUtf8(Base64.decodeBase64(bodyParts.get(j).getBody().getData()));
                    
                    System.out.println("EmailBody:==> " + MailBody);
                
             catch (FileNotFoundException e) 
                e.printStackTrace();
             catch (IOException e) 
                e.printStackTrace();
            
         else 
            //signIn
            someActivityResultLauncher.launch(mGoogleSignInClient.getSignInIntent());
        
        return null;
    

GoogleAuth.java

    public class GoogleAuth 
    public String handleSignInResult(Task<GoogleSignInAccount> completedTask) 
        try 
            GoogleSignInAccount account = completedTask.getResult(ApiException.class);
            System.out.println("ServerAuthCode: " + account.getServerAuthCode());
            return account.getServerAuthCode();
         catch (ApiException e) 
            System.out.println("getStatusCode: " + e);
            return null;
        
    

错误日志

W/System.err: com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden

  "code" : 403,
  "errors" : [ 
    "domain" : "global",
    "message" : "Insufficient Permission",
 W/System.err:     "reason" : "insufficientPermissions"
   ],
  "message" : "Request had insufficient authentication scopes.",
  "status" : "PERMISSION_DENIED"

此行出错:ListMessagesResponse listMessagesResponse = RequestList.setMaxResults(100L).execute();

【问题讨论】:

【参考方案1】:

您已授权您的应用程序

Scope(Scopes.DRIVE_APPFOLDER)

User.message.list 需要以下范围之一

将范围更改为适当的范围并让您的用户重新授权您的应用程序。当用户运行应用程序时,同意屏幕需要显示新的范围。

【讨论】:

以上是关于Gmail Api 请求的身份验证范围不足的主要内容,如果未能解决你的问题,请参考以下文章

gmail api 发送邮件不起作用 C# 控制台应用程序(身份验证范围不足)

错误 403:“请求的身份验证范围不足”,即使相关范围已激活

Youtube 评论 API 抛出“权限不足:请求的身份验证范围不足”错误

请求的身份验证范围不足 youtube api

Google Calendar API 错误请求的身份验证范围不足

请求的身份验证范围不足 javascript