invalid_grant prova a ottenere token oAuth da google

Continuo a ricevere un errore invalid_grant nel tentativo di ottenere un token oAuth da Google per connettersi alla loro api dei contatti. Tutte le informazioni sono corrette e ho triplicato controllato questo in modo un po ‘perplesso.

Qualcuno sa che cosa potrebbe causare questo problema? Ho provato a configurare un ID client diverso, ma ottengo lo stesso risultato, ho provato a colbind molti modi diversi tra cui provare l’autenticazione forzata, ma sempre lo stesso risultato.

Ho riscontrato questo problema quando non ho chiesto esplicitamente l’accesso “offline” quando invio l’utente a OAuth “Vuoi concedere a questa app il permesso di toccare i tuoi contenuti?” pagina.

Assicurati di specificare access_type = offline nella tua richiesta.

Dettagli qui: https://developers.google.com/accounts/docs/OAuth2WebServer#offline

(Inoltre: penso che Google abbia aggiunto questa restrizione alla fine del 2011. Se hai vecchi token di prima, devi inviare i tuoi utenti alla pagina delle autorizzazioni per autorizzare l’uso offline.)

Mi sono imbattuto in questo stesso problema nonostante access_type specificato access_type “offline” nella mia richiesta come da risposta di bonkydog. Per farla breve ho scoperto che la soluzione descritta qui ha funzionato per me:

https://groups.google.com/forum/#!topic/google-analytics-data-export-api/4uNaJtquxCs

In sostanza, quando aggiungi un client OAuth2 nella console della tua API Google, Google ti fornirà un “ID cliente” e un “Indirizzo email” (supponendo che tu selezioni “webapp” come tipo di client). E nonostante le convenzioni di denominazione fuorvianti di Google, si aspettano che tu invii l ‘”indirizzo email” come valore del parametro client_id quando accedi alle loro API OAuth2.

Questo si applica quando si chiamano entrambi questi URL:

Tieni presente che la chiamata al primo URL avrà esito positivo se la chiami con il tuo “ID cliente” anziché con il tuo “Indirizzo email”. Tuttavia, l’utilizzo del codice restituito da tale richiesta non funzionerà quando si tenta di ottenere un token al portatore dal secondo URL. Invece riceverai un messaggio “Errore 400” e un messaggio “invalid_grant”.

Anche se questa è una vecchia domanda, sembra che molti lo incontrino ancora – abbiamo trascorso giorni interi a rintracciarlo da soli.

Nella specifica OAuth2, “invalid_grant” è una sorta di catch-all per tutti gli errori relativi a token non validi / scaduti / revocati (concessione di autenticazione o token di aggiornamento).

Per noi, il problema era duplice:

  1. L’utente ha revocato triggersmente l’accesso alla nostra app
    Ha senso, ma ottieni questo: 12 ore dopo la revoca, Google smette di inviare il messaggio di errore nella loro risposta: “error_description” : “Token has been revoked.”
    È piuttosto fuorviante perché presumerai che il messaggio di errore sia sempre presente, il che non è il caso. Puoi verificare se la tua app ha ancora accesso alla pagina delle autorizzazioni delle app .

  2. L’utente ha ripristinato / recuperato la propria password Google
    A dicembre 2015, Google ha cambiato il comportamento predefinito in modo che la reimpostazione della password per gli utenti non di Google Apps revocherebbe automaticamente tutti i token di aggiornamento delle app dell’utente. In caso di revoca, il messaggio di errore segue la stessa regola del caso precedente, quindi riceverai solo “error_description” nelle prime 12 ore. Non sembra esserci alcun modo per sapere se l’utente ha revocato manualmente l’accesso (intenzionale) o è successo a causa di una reimpostazione della password (effetto collaterale).

Oltre a quelli, c’è una miriade di altre potenziali cause che potrebbero innescare l’errore:

  1. L’ora / ora del server non è sincronizzata
  2. Non autorizzato per l’accesso offline
  3. Limitato da Google
  4. Utilizzo di token di aggiornamento scaduti
  5. L’utente è rimasto inattivo per 6 mesi
  6. Utilizzare l’email dell’operatore di servizio anziché l’ID cliente
  7. Troppi token di accesso in breve tempo
  8. SDK client potrebbe essere obsoleto
  9. Token di aggiornamento errato / incompleto

Ho scritto un breve articolo che riassume ogni elemento con alcune indicazioni di debug per aiutare a trovare il colpevole. Spero che sia d’aiuto.

Ho incontrato lo stesso problema. Per me, ho risolto questo problema utilizzando l’indirizzo email (la stringa che termina con … @ developer.gserviceaccount.com) anziché l’ID client per il valore del parametro client_id. Il set di nomi di Google è confuso qui.

Ho avuto lo stesso messaggio di errore ‘invalid_grant’ ed è stato perché il authResult [‘code’] send dal lato client javascript non è stato ricevuto correttamente sul server.

Prova a restituirlo dal server per vedere se è corretto e non una stringa vuota.

Il mio problema era che ho usato questo URL:

 https://accounts.google.com/o/oauth2/token 

Quando avrei dovuto usare questo URL:

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

Questo stava testando un account di servizio che voleva l’accesso offline al motore di Storage .

se usi la libreria scribe, imposta semplicemente la modalità offline, come bonkydog suggerito qui è il codice:

 OAuthService service = new ServiceBuilder().provider(Google2Api.class).apiKey(clientId).apiSecret(apiSecret) .callback(callbackUrl).scope(SCOPE).offline(true) .build(); 

https://github.com/codolutions/scribe-java/

in questo sito console.developers.google.com

questa consolle seleziona il tuo progetto immesso nell’URL del giuramento. l’url di callback di oauth reindirizzerà quando il successo di oauth

Usando un client AndroidId (nessun client_secret) stavo ottenendo la seguente risposta all’errore:

 { "error": "invalid_grant", "error_description": "Missing code verifier." } 

Non riesco a trovare alcuna documentazione per il campo ‘code_verifier’ ma ho scoperto che se lo si imposta a valori uguali in entrambe le richieste di authorization e token rimuoverà questo errore. Non sono sicuro di quale dovrebbe essere il valore previsto o se dovrebbe essere sicuro. Ha una lunghezza minima (16? Caratteri) ma ho trovato che l’impostazione su null funziona anche.

Sto utilizzando AppAuth per la richiesta di authorization nel mio client Android che ha una funzione setCodeVerifier() .

 AuthorizationRequest authRequest = new AuthorizationRequest.Builder( serviceConfiguration, provider.getClientId(), ResponseTypeValues.CODE, provider.getRedirectUri() ) .setScope(provider.getScope()) .setCodeVerifier(null) .build(); 

Ecco una richiesta di token di esempio nel nodo:

 request.post( 'https://www.googleapis.com/oauth2/v4/token', { form: { 'code': '4/xxxxxxxxxxxxxxxxxxxx', 'code_verifier': null, 'client_id': 'xxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com', 'client_secret': null, 'redirect_uri': 'com.domain.app:/oauth2redirect', 'grant_type': 'authorization_code' } }, function (error, response, body) { if (!error && response.statusCode == 200) { console.log('Success!'); } else { console.log(response.statusCode + ' ' + error); } console.log(body); } ); 

Ho provato e funziona con entrambi https://www.googleapis.com/oauth2/v4/token e https://accounts.google.com/o/oauth2/token .

Se invece stai usando GoogleAuthorizationCodeTokenRequest :

 final GoogleAuthorizationCodeTokenRequest req = new GoogleAuthorizationCodeTokenRequest( TRANSPORT, JSON_FACTORY, getClientId(), getClientSecret(), code, redirectUrl ); req.set("code_verifier", null); GoogleTokenResponse response = req.execute(); 

Questa è una risposta sciocca, ma il problema per me è stato che non sono riuscito a capire che avevo già rilasciato un token oAuth attivo per il mio utente google che non ero riuscito a memorizzare. La soluzione in questo caso è andare alla console di api e ripristinare il segreto del client.

Esistono numerose altre risposte su SO a questo effetto, ad esempio Reimposta segreta client OAuth2: i client devono concedere nuovamente l’accesso?

Potrebbe essere necessario rimuovere una risposta OAuth non valida / non valida.

Credito: node.js google oauth2 sample ha smesso di funzionare invalid_grant

Nota : anche una risposta OAuth diventa non valida se la password utilizzata nell’authorization iniziale è stata modificata.

Se in un ambiente bash, è ansible utilizzare quanto segue per rimuovere la risposta obsoleta:

rm /Users//.credentials/

Ci sono due ragioni principali per l’ errore invalid_grant che devi fare attenzione prima della richiesta POST per il token di aggiornamento e il token di accesso.

  1. L’intestazione della richiesta deve contenere “content-type: application / x-www-form-urlencoded”
  2. Il carico utile della richiesta deve essere url codificato Dati modulo, non inviare come object json.

RFC 6749 OAuth 2.0 ha definito invalid_grant come: La concessione di authorization fornita (es. Codice di authorization, credenziali del proprietario della risorsa) o il token di aggiornamento non è valido, scaduto, revocato, non corrisponde all’URI di reindirizzamento utilizzato nella richiesta di authorization o è stato rilasciato a un altro client .

Ho trovato un altro buon articolo, qui troverai molti altri motivi per questo errore.

https://blog.timekit.io/google-oauth-invalid-grant-nightmare-and-how-to-fix-it-9f4efaf1da35

Dopo aver considerato e provato tutti gli altri modi qui, ecco come ho risolto il problema in nodejs con il modulo googleapis in combinazione con il modulo di request , che ho usato per recuperare i token invece del metodo getToken() fornito:

 const request = require('request'); //SETUP GOOGLE AUTH var google = require('googleapis'); const oAuthConfigs = rootRequire('config/oAuthConfig') const googleOAuthConfigs = oAuthConfigs.google //for google OAuth: https://github.com/google/google-api-nodejs-client var OAuth2 = google.auth.OAuth2; var googleOAuth2Client = new OAuth2( process.env.GOOGLE_OAUTH_CLIENT_ID || googleOAuthConfigs.clientId, process.env.GOOGLE_OAUTH_CLIENT_SECRET || googleOAuthConfigs.clientSecret, process.env.GOOGLE_OAUTH_CLIENT_REDIRECT_URL || googleOAuthConfigs.callbackUrl); /* generate a url that asks permissions for Google+ and Google Calendar scopes https://developers.google.com/identity/protocols/googlescopes#monitoringv3*/ var googleOAuth2ClientScopes = [ 'https://www.googleapis.com/auth/plus.me', 'https://www.googleapis.com/auth/userinfo.email' ]; var googleOAuth2ClientRedirectURL = process.env.GOOGLE_OAUTH_CLIENT_REDIRECT_URL || googleOAuthConfigs.callbackUrl; var googleOAuth2ClientAuthUrl = googleOAuth2Client.generateAuthUrl({ access_type: 'offline', // 'online' (default) or 'offline' (gets refresh_token) scope: googleOAuth2ClientScopes // If you only need one scope you can pass it as string }); //AFTER SETUP, THE FOLLOWING IS FOR OBTAINING TOKENS FROM THE AUTHCODE const ci = process.env.GOOGLE_OAUTH_CLIENT_ID || googleOAuthConfigs.clientId const cs = process.env.GOOGLE_OAUTH_CLIENT_SECRET || googleOAuthConfigs.clientSecret const ru = process.env.GOOGLE_OAUTH_CLIENT_REDIRECT_URL || googleOAuthConfigs.callbackUrl var oauth2Client = new OAuth2(ci, cs, ru); var hostUrl = "https://www.googleapis.com"; hostUrl += '/oauth2/v4/token?code=' + authCode + '&client_id=' + ci + '&client_secret=' + cs + '&redirect_uri=' + ru + '&grant_type=authorization_code', request.post({url: hostUrl}, function optionalCallback(err, httpResponse, data) { // Now tokens contains an access_token and an optional refresh_token. Save them. if(!err) { //SUCCESS! We got the tokens const tokens = JSON.parse(data) oauth2Client.setCredentials(tokens); //AUTHENTICATED PROCEED AS DESIRED. googlePlus.people.get({ userId: 'me', auth: oauth2Client }, function(err, response) { // handle err and response if(!err) { res.status(200).json(response); } else { console.error("/google/exchange 1", err.message); handleError(res, err.message, "Failed to retrieve google person"); } }); } else { console.log("/google/exchange 2", err.message); handleError(res, err.message, "Failed to get access tokens", err.code); } }); 

Io uso semplicemente la request per effettuare la richiesta API via HTTP come descritto qui: https://developers.google.com/identity/protocols/OAuth2WebServer#offline

 POST /oauth2/v4/token HTTP/1.1 Host: www.googleapis.com Content-Type: application/x-www-form-urlencoded code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7& client_id=8819981768.apps.googleusercontent.com& client_secret={client_secret}& redirect_uri=https://oauth2.example.com/code& grant_type=authorization_code 

Prova a cambiare l’URL per richiedere

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