La API de Google Sheets devuelve "La persona que llama no tiene permiso" cuando se usa la clave del servidor


89

He generado una clave de servidor en el Administrador de API e intenté ejecutar lo siguiente en mi Mac:

curl 'https://sheets.googleapis.com/v4/spreadsheets/MySheetID?ranges=A1:B5&key=TheServerKeyIGeneratedInAPIManager'

Pero esto es lo que devuelve:

{
 "error": {
    "code": 403,
    "message": "The caller does not have permission",
    "status": "PERMISSION_DENIED"
  }
}

¿Qué estoy haciendo mal aquí?


4
La clave es para acceder a datos públicos, lo que está haciendo requiere acceso autenticado.
DaImTo

En la mayoría de los casos existe algún problema de visores. Compruebe y verifique qué ámbitos requiere el script.
dpkrai96

Respuestas:


119

Para resolver este problema, intente:

  1. Cree una cuenta de servicio: https://console.developers.google.com/iam-admin/serviceaccounts/
  2. En opciones, cree una clave: esta clave es su client_secret.json habitual; úsela de la misma manera
  3. Haga el propietario de la función para la cuenta de servicio (nombre de miembro = ID de cuenta de servicio = correo electrónico de cuenta de servicio, por ejemplo: thomasapp@appname-201813.iam.gserviceaccount.com
  4. Copie la dirección de correo electrónico de su cuenta de servicio = ID de cuenta de servicio
  5. Simplemente vaya en su navegador a la hoja de Google con la que desea interactuar.
  6. Ve a COMPARTIR en la parte superior derecha de tu pantalla
  7. Vaya a la configuración avanzada y compártalo con la dirección de correo electrónico de su cuenta de servicio, por ejemplo: thomasapp@appname-201813.iam.gserviceaccount.com

Funcionó para mí :)


1
esto funcionó para mí. por cierto: en google cloud admin, vaya a ... project> IAM & Admin> Service Accounts .... Si ha configurado cuentas de servicio, verá un correo electrónico especial para cada cuenta de servicio respectiva. Asegúrese de haber habilitado también la API de Google Sheets. Literalmente, solo comparte la dirección de correo electrónico de la cuenta de servicio desde el botón "compartir" de la hoja de Google.
Jason F

1
sí ... la clave es simplemente compartir el documento con el correo electrónico de la cuenta de servicio ....
user1102171

2
La clave json es muy diferente de las credenciales json que obtuve de la guía de inicio rápido de Java (para la API de Sheets). ¿Cómo lo implemento?
Cardinal - Reincorpora a Monica

2
¿Cómo usas el secreto del cliente? ¿Puedes crear una clave API con una cuenta de servicio en su lugar?
Stephen Phillips

42

Sé que es un poco tarde para responder, pero para otras personas que luchan con el mismo problema.
Simplemente cambie el permiso de la hoja a público en su disco para que se pueda acceder sin autenticación a través de llamadas a la API.

Para cambiar el acceso:

  1. Abrir hoja en google drive
  2. En la esquina superior derecha, haz clic en compartir
  3. En la parte inferior de la ventana del mensaje, haga clic en avanzado
  4. Cambiar el permiso a público o personas con enlace (no es necesario iniciar sesión)

Envíe una solicitud de API para obtener datos de hojas sin autenticación.

Nota: si la hoja contiene datos confidenciales, no es seguro hacerla pública y más bien hacerlo con acceso autenticado.


36
Además, puede compartir esta hoja con un correo electrónico específico Ex. el correo electrónico de su cuenta de servicio (proyecto). "client_email": "XXXXX@northern-gasket-XXXX.iam.gserviceaccount.com", esto le permitirá acceder a la hoja mediante su script.
Kishan Patel

4
Gracias hermano. No hay cosas escritas en la documentación como las que ha mencionado.
Maulik Dodia

1
De acuerdo @MaulikDodia. Los documentos de la API de Google lo dicen aquí , pero no está claro para las personas que solo quieren usar la API para mostrar datos en un sitio web público. Estoy en el proceso de escribir un instructivo sobre todo esto. Te enviaré un DM cuando termine.
Edward

Muchas gracias amigo @ user3411192
Maulik Dodia

27

Asegúrese de prestar atención al comentario de @ KishanPatel:

Además, puede compartir esta hoja con un correo electrónico específico Ex. el correo electrónico de su cuenta de servicio (proyecto). "client_email": "XXXXX@northern-gasket-XXXX.iam.gserviceaccount.com", esto le permitirá acceder a la hoja mediante su script.


4

La forma más sencilla es solucionarlo con gcloud cli. Más documentos aquí https://cloud.google.com/pubsub/docs/quickstart-cli#before-you-begin

instalar gcloud

sudo apt-get install google-cloud-sdk

luego llame

gcloud init

luego verifique su proyecto activo y sus credenciales

gcloud config configurations list

Si no está bien, asegúrese de estar autenticado con la cuenta correcta:

gcloud auth list
* account 1
  account 2

Cambie a la cuenta del proyecto si no:

gcloud config set account `ACCOUNT`

Según la cuenta, la lista de proyectos será diferente:

gcloud projects list

- project 1
- project 2...

Cambiar al proyecto previsto:

gcloud config set project `PROJECT NAME`

Luego, cree las credenciales predeterminadas de la aplicación con gcloud auth application-default login, y luego google-cloud detectará automáticamente dichas credenciales.


0

Mis 10 centavos ... Un ejemplo sencillo para leer la hoja usando Java .

    private Credential getCredentials() throws IOException {
            final InputStream accessKey = new ByteArrayInputStream("<credential json>");
            final GoogleCredential credential = GoogleCredential.fromStream(accessKey)
                    .createScoped(Collections.singleton(SheetsScopes.SPREADSHEETS_READONLY));
            return credential;
        }

    private HttpTransport httpTransport() {
            try {
                return GoogleNetHttpTransport.newTrustedTransport();
            } catch (GeneralSecurityException | IOException e) {
                throw new SpreadSheetServiceException(e);
            }
        }


    Sheets service = new Sheets.Builder(httpTransport(), JSON_FACTORY, getCredentials())
                    .setApplicationName("app-name")
                    .build();
            ValueRange response = service.spreadsheets().values()
                    .get("<spread_sheet_id>", "A1:A")
                    .execute();
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.