Search code examples
google-oauthhangouts-api

Hangout OAuth - Invalid Scope : Some requested scopes cannot be shown


I am facing the below error while generating token for service account for the Hangout Scope - https://www.googleapis.com/auth/chat.bot.

Where i receive 400 response code after making a post request to this url -

https://www.googleapis.com/oauth2/v4/token

the params are Content-Type:application/x-www-form-urlencoded httpMode:POST body:grant_type=jwt-bearer&assertion=assertion-token

Note:This was completely working fine. Suddenly am facing this issue.

cross verified: jwt generation,service_account_id and etc...

Error Response : { "error": "invalid_scope", "error_description": "Some requested scopes cannot be shown": [https://www.googleapis.com/auth/chat.bot]}

code for generating assertion:

 //FORMING THE JWT HEADER
            JSONObject header = new JSONObject();
            header.put("alg", "RS256");
            header.put("typ", "JWT");
            //ENCODING THE HEADER
           String encodedHeader = new String(encodeUrlSafe(header.toString().getBytes("UTF-8")));


            //FORMING THE JWT CLAIM SET
            JSONObject claimSet = new JSONObject();
            claimSet.put("iss","[email protected]");
            claimSet.put("sub","[email protected]");
            claimSet.put("scope","https://www.googleapis.com/auth/chat.bot");
            claimSet.put("aud","https://oauth2.googleapis.com/token");
            long time = System.currentTimeMillis() / 1000;
            claimSet.put("exp",time+3600);
            claimSet.put("iat",time);
            //ENCODING THE CLAIM SET
            String encodedClaim = new String(encodeUrlSafe(claimSet.toString().getBytes("UTF-8")));

            //GENERATING THE SIGNATURE
            String password = "secretofkey", alias = "privatekey";
            String signInput = encodedHeader + "." + encodedClaim;
            Signature signature = Signature.getInstance("SHA256withRSA");
           
            String filepath =   "/check/PrivateKeys/hangoutPKEY.p12";
            KeyStore kstore = KeyStore.getInstance("PKCS12");
            fis = new FileInputStream(filepath);
            kstore.load(fis, password.toCharArray());
            KeyStore.PrivateKeyEntry pke = (KeyStore.PrivateKeyEntry) kstore.getEntry(alias, new KeyStore.PasswordProtection(password.toCharArray()));
            PrivateKey pKey = pke.getPrivateKey();
            signature.initSign(pKey);
            signature.update(signInput.getBytes("UTF-8"));
            String encodedSign = new String(encodeUrlSafe(signature.sign()), "UTF-8");

            //JWT GENERATION
            String JWT = signInput + "." + encodedSign;
  String grant_type = URLEncoder.encode("urn:ietf:params:oauth:grant-type:jwt-bearer");
            reqBody = "grant_type=" + grant_type + "&assertion=" + JWT;  

 public static byte[] encodeUrlSafe(byte[] data) {
        Base64 encoder = new Base64();
        byte[] encode = encoder.encodeBase64(data);
        for (int i = 0; i < encode.length; i++) {
            if (encode[i] == '+') {
                encode[i] = '-';
            } else if (encode[i] == '/') {
                encode[i] = '_';
            }
        }
        return encode;
    }  

Does anyone have any idea, where am going wrong?


Solution

  • Short answer:

    You are trying to use domain-wide authority to impersonate a regular account. This is not supported in Chat API.

    Issue detail:

    You are using the sub parameter when building your JWT claim:

    claimSet.put("sub","[email protected]");
    

    Where sub refers to:

    sub: The email address of the user for which the application is requesting delegated access.

    I noticed that, if I add the sub parameter to my test code, I get the same error as you.

    Solution:

    Remove this line from your code in order to authorize with the service account (without impersonation) and handle bot data:

    claimSet.put("sub","[email protected]");
    

    Background explanation:

    Chat API can be used for bots to manage their own data, not to manage end-user data. Therefore, you can only use a service account to act as the bot, without impersonating an end-user.

    From this Issue Tracker comment:

    At the present moment, Chat API can only be used to manage bot-related data (listing the spaces in which the bot is included, etc.). Using domain-wide delegation to manage regular users' data is not currently possible.

    Feature request:

    If you'd like to be able to access regular users' data with your service account and domain-wide delegation via Chat API, you are not alone. This feature has been requested before in Issue Tracker:

    I'd suggest you to star the referenced issue in order to keep track of it and to help prioritizing it.

    Reference: