char *GOA2GetAuthorizationURL(const char *pszScope) { CPLString osScope; CPLString osURL; osScope.Seize(CPLEscapeString(pszScope, -1, CPLES_URL)); osURL.Printf( "%s/auth?scope=%s&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&client_id=%s", GOOGLE_AUTH_URL, osScope.c_str(), CPLGetConfigOption("GOA2_CLIENT_ID", GDAL_CLIENT_ID)); return CPLStrdup(osURL); }
char CPL_DLL *GOA2GetRefreshToken( const char *pszAuthToken, const char *pszScope ) { /* -------------------------------------------------------------------- */ /* Prepare request. */ /* -------------------------------------------------------------------- */ CPLString osItem; CPLStringList oOptions; oOptions.AddString( "HEADERS=Content-Type: application/x-www-form-urlencoded" ); osItem.Printf( "POSTFIELDS=" "code=%s" "&client_id=%s" "&client_secret=%s" "&redirect_uri=urn:ietf:wg:oauth:2.0:oob" "&grant_type=authorization_code", pszAuthToken, CPLGetConfigOption("GOA2_CLIENT_ID", GDAL_CLIENT_ID), CPLGetConfigOption("GOA2_CLIENT_SECRET", GDAL_CLIENT_SECRET)); oOptions.AddString(osItem); /* -------------------------------------------------------------------- */ /* Submit request by HTTP. */ /* -------------------------------------------------------------------- */ CPLHTTPResult * psResult = CPLHTTPFetch( GOOGLE_AUTH_URL "/token", oOptions); if (psResult == NULL) return NULL; /* -------------------------------------------------------------------- */ /* One common mistake is to try and reuse the auth token. */ /* After the first use it will return invalid_grant. */ /* -------------------------------------------------------------------- */ if( psResult->pabyData != NULL && strstr((const char *) psResult->pabyData,"invalid_grant") != NULL) { CPLString osURL; osURL.Seize( GOA2GetAuthorizationURL(pszScope) ); CPLError( CE_Failure, CPLE_AppDefined, "Attempt to use a OAuth2 authorization code multiple times.\n" "Request a fresh authorization token at\n%s.", osURL.c_str() ); CPLHTTPDestroyResult(psResult); return NULL; } if (psResult->pabyData == NULL || psResult->pszErrBuf != NULL) { if( psResult->pszErrBuf != NULL ) CPLDebug( "GOA2", "%s", psResult->pszErrBuf ); if( psResult->pabyData != NULL ) CPLDebug( "GOA2", "%s", psResult->pabyData ); CPLError( CE_Failure, CPLE_AppDefined, "Fetching OAuth2 access code from auth code failed."); CPLHTTPDestroyResult(psResult); return NULL; } CPLDebug( "GOA2", "Access Token Response:\n%s", (const char *) psResult->pabyData ); /* -------------------------------------------------------------------- */ /* This response is in JSON and will look something like: */ /* -------------------------------------------------------------------- */ /* { "access_token" : "ya29.AHES6ZToqkIJkat5rIqMixR1b8PlWBACNO8OYbqqV-YF1Q13E2Kzjw", "token_type" : "Bearer", "expires_in" : 3600, "refresh_token" : "1/eF88pciwq9Tp_rHEhuiIv9AS44Ufe4GOymGawTVPGYo" } */ CPLStringList oResponse = ParseSimpleJson( (const char *) psResult->pabyData ); CPLHTTPDestroyResult(psResult); CPLString osAccessToken = oResponse.FetchNameValueDef( "access_token", "" ); CPLString osRefreshToken = oResponse.FetchNameValueDef( "refresh_token", "" ); CPLDebug("GOA2", "Access Token : '%s'", osAccessToken.c_str()); CPLDebug("GOA2", "Refresh Token : '%s'", osRefreshToken.c_str()); if( osRefreshToken.size() == 0) { CPLError( CE_Failure, CPLE_AppDefined, "Unable to identify a refresh token in the OAuth2 response."); return NULL; } else { // Currently we discard the access token and just return the refresh token return CPLStrdup(osRefreshToken); } }