Google Drive SDK

Implementing Server-Side Authorization

Requests to the Drive API must be authorized using OAuth 2.0 credentials. You should use server-side flow when your application needs to access Google APIs on behalf of the user such as when the user is offline. This approach requires passing a one-time authorization code from your client to your server that is used to acquire an access and refresh tokens for your server.

If your application does not require offline access to user data, consider using the client-side authorization flow, which can be implemented using only JavaScript and HTML.

Create a client ID and client secret

If you haven't already registered your application with the Google Developers Console, then set up a project and application in the Developers Console. The system guides you through the process of choosing or creating a project and registering a new application, and it automatically activates the API for you.

If you've already registered your application with the Developers Console, then follow this procedure instead:

  1. Go to the Google Developers Console.
  2. Select a project.
  3. In the sidebar on the left, select APIs & auth. In the list of APIs, make sure the status is ON for the Drive API.
  4. In the sidebar on the left, select Credentials.

In either case, you end up on the application's credentials page.

To find your application's client ID and client secret, and set a redirect URI, expand the OAuth 2.0 Client ID section.

Take note of the Client ID as you'll need to add it to your code later.

Handling authorization requests

When a user loads your application for the first time, they are presented with a dialog to grant permission for your application to access their Google Drive account with the requested permission scopes. After this initial authorization, the user is only presented with the permission dialog if your app's client ID changes or the requested scopes have changed.

Authenticate the user

This initial sign-in returns an authorization result object that contains an authorization code if successful.

Exchange the authorization code for an access token

The authorization code is a one-time code that your server can exchange for an access token. This access token is passed to the Google Drive API to grant your application access to user data for a limited time.

If your application requires offline access, the first time your app exchanges the authorization code, it also receives a refresh token that it uses to receive a new access token after a previous token has expired. Your application stores this refresh token (generally in a database on your server) for later use.

The following code samples demonstrate exchanging an authorization code for an access token with offline access and storing the refresh token.

Java

Replace CLIENTSECRETS_LOCATION value with the location of your client_secrets.json file.

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeRequestUrl;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.services.oauth2.Oauth2;
import com.google.api.services.oauth2.model.Userinfo;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

// ...

class MyClass {

  // Path to client_secrets.json which should contain a JSON document such as:
  //   {
  //     "web": {
  //       "client_id": "[[YOUR_CLIENT_ID]]",
  //       "client_secret": "[[YOUR_CLIENT_SECRET]]",
  //       "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  //       "token_uri": "https://accounts.google.com/o/oauth2/token"
  //     }
  //   }
  private static final String CLIENTSECRETS_LOCATION = "client_secrets.json";

  private static final String REDIRECT_URI = "<YOUR_REGISTERED_REDIRECT_URI>";
  private static final List<String> SCOPES = Arrays.asList(
      "https://www.googleapis.com/auth/drive.file",
      "https://www.googleapis.com/auth/userinfo.email",
      "https://www.googleapis.com/auth/userinfo.profile");

  private static GoogleAuthorizationCodeFlow flow = null;

  /**
   * Exception thrown when an error occurred while retrieving credentials.
   */
  public static class GetCredentialsException extends Exception {

    protected String authorizationUrl;

    /**
     * Construct a GetCredentialsException.
     *
     * @param authorizationUrl The authorization URL to redirect the user to.
     */
    public GetCredentialsException(String authorizationUrl) {
      this.authorizationUrl = authorizationUrl;
    }

    /**
     * Set the authorization URL.
     */
    public void setAuthorizationUrl(String authorizationUrl) {
      this.authorizationUrl = authorizationUrl;
    }

    /**
     * @return the authorizationUrl
     */
    public String getAuthorizationUrl() {
      return authorizationUrl;
    }
  }

  /**
   * Exception thrown when a code exchange has failed.
   */
  public static class CodeExchangeException extends GetCredentialsException {

    /**
     * Construct a CodeExchangeException.
     *
     * @param authorizationUrl The authorization URL to redirect the user to.
     */
    public CodeExchangeException(String authorizationUrl) {
      super(authorizationUrl);
    }

  }

  /**
   * Exception thrown when no refresh token has been found.
   */
  public static class NoRefreshTokenException extends GetCredentialsException {

    /**
     * Construct a NoRefreshTokenException.
     *
     * @param authorizationUrl The authorization URL to redirect the user to.
     */
    public NoRefreshTokenException(String authorizationUrl) {
      super(authorizationUrl);
    }

  }

  /**
   * Exception thrown when no user ID could be retrieved.
   */
  private static class NoUserIdException extends Exception {
  }

  /**
   * Retrieved stored credentials for the provided user ID.
   *
   * @param userId User's ID.
   * @return Stored Credential if found, {@code null} otherwise.
   */
  static Credential getStoredCredentials(String userId) {
    // TODO: Implement this method to work with your database. Instantiate a new
    // Credential instance with stored accessToken and refreshToken.
    throw new UnsupportedOperationException();
  }

  /**
   * Store OAuth 2.0 credentials in the application's database.
   *
   * @param userId User's ID.
   * @param credentials The OAuth 2.0 credentials to store.
   */
  static void storeCredentials(String userId, Credential credentials) {
    // TODO: Implement this method to work with your database.
    // Store the credentials.getAccessToken() and credentials.getRefreshToken()
    // string values in your database.
    throw new UnsupportedOperationException();
  }

  /**
   * Build an authorization flow and store it as a static class attribute.
   *
   * @return GoogleAuthorizationCodeFlow instance.
   * @throws IOException Unable to load client_secrets.json.
   */
  static GoogleAuthorizationCodeFlow getFlow() throws IOException {
    if (flow == null) {
      HttpTransport httpTransport = new NetHttpTransport();
      JacksonFactory jsonFactory = new JacksonFactory();
      GoogleClientSecrets clientSecrets =
          GoogleClientSecrets.load(jsonFactory,
              MyClass.class.getResourceAsStream(CLIENTSECRETS_LOCATION));
      flow =
          new GoogleAuthorizationCodeFlow.Builder(httpTransport, jsonFactory, clientSecrets, SCOPES)
              .setAccessType("offline").setApprovalPrompt("force").build();
    }
    return flow;
  }

  /**
   * Exchange an authorization code for OAuth 2.0 credentials.
   *
   * @param authorizationCode Authorization code to exchange for OAuth 2.0
   *        credentials.
   * @return OAuth 2.0 credentials.
   * @throws CodeExchangeException An error occurred.
   */
  static Credential exchangeCode(String authorizationCode)
      throws CodeExchangeException {
    try {
      GoogleAuthorizationCodeFlow flow = getFlow();
      GoogleTokenResponse response =
          flow.newTokenRequest(authorizationCode).setRedirectUri(REDIRECT_URI).execute();
      return flow.createAndStoreCredential(response, null);
    } catch (IOException e) {
      System.err.println("An error occurred: " + e);
      throw new CodeExchangeException(null);
    }
  }

  /**
   * Send a request to the UserInfo API to retrieve the user's information.
   *
   * @param credentials OAuth 2.0 credentials to authorize the request.
   * @return User's information.
   * @throws NoUserIdException An error occurred.
   */
  static Userinfo getUserInfo(Credential credentials)
      throws NoUserIdException {
    Oauth2 userInfoService =
        new Oauth2.Builder(new NetHttpTransport(), new JacksonFactory(), credentials).build();
    Userinfo userInfo = null;
    try {
      userInfo = userInfoService.userinfo().get().execute();
    } catch (IOException e) {
      System.err.println("An error occurred: " + e);
    }
    if (userInfo != null && userInfo.getId() != null) {
      return userInfo;
    } else {
      throw new NoUserIdException();
    }
  }

  /**
   * Retrieve the authorization URL.
   *
   * @param emailAddress User's e-mail address.
   * @param state State for the authorization URL.
   * @return Authorization URL to redirect the user to.
   * @throws IOException Unable to load client_secrets.json.
   */
  public static String getAuthorizationUrl(String emailAddress, String state) throws IOException {
    GoogleAuthorizationCodeRequestUrl urlBuilder =
        getFlow().newAuthorizationUrl().setRedirectUri(REDIRECT_URI).setState(state);
    urlBuilder.set("user_id", emailAddress);
    return urlBuilder.build();
  }

  /**
   * Retrieve credentials using the provided authorization code.
   *
   * This function exchanges the authorization code for an access token and
   * queries the UserInfo API to retrieve the user's e-mail address. If a
   * refresh token has been retrieved along with an access token, it is stored
   * in the application database using the user's e-mail address as key. If no
   * refresh token has been retrieved, the function checks in the application
   * database for one and returns it if found or throws a NoRefreshTokenException
   * with the authorization URL to redirect the user to.
   *
   * @param authorizationCode Authorization code to use to retrieve an access
   *        token.
   * @param state State to set to the authorization URL in case of error.
   * @return OAuth 2.0 credentials instance containing an access and refresh
   *         token.
   * @throws NoRefreshTokenException No refresh token could be retrieved from
   *         the available sources.
   * @throws IOException Unable to load client_secrets.json.
   */
  public static Credential getCredentials(String authorizationCode, String state)
      throws CodeExchangeException, NoRefreshTokenException, IOException {
    String emailAddress = "";
    try {
      Credential credentials = exchangeCode(authorizationCode);
      Userinfo userInfo = getUserInfo(credentials);
      String userId = userInfo.getId();
      emailAddress = userInfo.getEmail();
      if (credentials.getRefreshToken() != null) {
        storeCredentials(userId, credentials);
        return credentials;
      } else {
        credentials = getStoredCredentials(userId);
        if (credentials != null && credentials.getRefreshToken() != null) {
          return credentials;
        }
      }
    } catch (CodeExchangeException e) {
      e.printStackTrace();
      // Drive apps should try to retrieve the user and credentials for the current
      // session.
      // If none is available, redirect the user to the authorization URL.
      e.setAuthorizationUrl(getAuthorizationUrl(emailAddress, state));
      throw e;
    } catch (NoUserIdException e) {
      e.printStackTrace();
    }
    // No refresh token has been retrieved.
    String authorizationUrl = getAuthorizationUrl(emailAddress, state);
    throw new NoRefreshTokenException(authorizationUrl);
  }

}

Python

Replace CLIENTSECRETS_LOCATION value with the location of your client_secrets.json file.

import logging
from oauth2client.client import flow_from_clientsecrets
from oauth2client.client import FlowExchangeError
from apiclient.discovery import build
# ...


# Path to client_secrets.json which should contain a JSON document such as:
#   {
#     "web": {
#       "client_id": "[[YOUR_CLIENT_ID]]",
#       "client_secret": "[[YOUR_CLIENT_SECRET]]",
#       "redirect_uris": [],
#       "auth_uri": "https://accounts.google.com/o/oauth2/auth",
#       "token_uri": "https://accounts.google.com/o/oauth2/token"
#     }
#   }
CLIENTSECRETS_LOCATION = '<PATH/TO/CLIENT_SECRETS.JSON>'
REDIRECT_URI = '<YOUR_REGISTERED_REDIRECT_URI>'
SCOPES = [
    'https://www.googleapis.com/auth/drive.file',
    'https://www.googleapis.com/auth/userinfo.email',
    'https://www.googleapis.com/auth/userinfo.profile',
    # Add other requested scopes.
]

class GetCredentialsException(Exception):
  """Error raised when an error occurred while retrieving credentials.

  Attributes:
    authorization_url: Authorization URL to redirect the user to in order to
                       request offline access.
  """

  def __init__(self, authorization_url):
    """Construct a GetCredentialsException."""
    self.authorization_url = authorization_url


class CodeExchangeException(GetCredentialsException):
  """Error raised when a code exchange has failed."""


class NoRefreshTokenException(GetCredentialsException):
  """Error raised when no refresh token has been found."""


class NoUserIdException(Exception):
  """Error raised when no user ID could be retrieved."""


def get_stored_credentials(user_id):
  """Retrieved stored credentials for the provided user ID.

  Args:
    user_id: User's ID.
  Returns:
    Stored oauth2client.client.OAuth2Credentials if found, None otherwise.
  Raises:
    NotImplemented: This function has not been implemented.
  """
  # TODO: Implement this function to work with your database.
  #       To instantiate an OAuth2Credentials instance from a Json
  #       representation, use the oauth2client.client.Credentials.new_from_json
  #       class method.
  raise NotImplementedError()


def store_credentials(user_id, credentials):
  """Store OAuth 2.0 credentials in the application's database.

  This function stores the provided OAuth 2.0 credentials using the user ID as
  key.

  Args:
    user_id: User's ID.
    credentials: OAuth 2.0 credentials to store.
  Raises:
    NotImplemented: This function has not been implemented.
  """
  # TODO: Implement this function to work with your database.
  #       To retrieve a Json representation of the credentials instance, call the
  #       credentials.to_json() method.
  raise NotImplementedError()


def exchange_code(authorization_code):
  """Exchange an authorization code for OAuth 2.0 credentials.

  Args:
    authorization_code: Authorization code to exchange for OAuth 2.0
                        credentials.
  Returns:
    oauth2client.client.OAuth2Credentials instance.
  Raises:
    CodeExchangeException: an error occurred.
  """
  flow = flow_from_clientsecrets(CLIENTSECRETS_LOCATION, ' '.join(SCOPES))
  flow.redirect_uri = REDIRECT_URI
  try:
    credentials = flow.step2_exchange(authorization_code)
    return credentials
  except FlowExchangeError, error:
    logging.error('An error occurred: %s', error)
    raise CodeExchangeException(None)


def get_user_info(credentials):
  """Send a request to the UserInfo API to retrieve the user's information.

  Args:
    credentials: oauth2client.client.OAuth2Credentials instance to authorize the
                 request.
  Returns:
    User information as a dict.
  """
  user_info_service = build(
      serviceName='oauth2', version='v2',
      http=credentials.authorize(httplib2.Http()))
  user_info = None
  try:
    user_info = user_info_service.userinfo().get().execute()
  except errors.HttpError, e:
    logging.error('An error occurred: %s', e)
  if user_info and user_info.get('id'):
    return user_info
  else:
    raise NoUserIdException()


def get_authorization_url(email_address, state):
  """Retrieve the authorization URL.

  Args:
    email_address: User's e-mail address.
    state: State for the authorization URL.
  Returns:
    Authorization URL to redirect the user to.
  """
  flow = flow_from_clientsecrets(CLIENTSECRETS_LOCATION, ' '.join(SCOPES))
  flow.params['access_type'] = 'offline'
  flow.params['approval_prompt'] = 'force'
  flow.params['user_id'] = email_address
  flow.params['state'] = state
  return flow.step1_get_authorize_url(REDIRECT_URI)


def get_credentials(authorization_code, state):
  """Retrieve credentials using the provided authorization code.

  This function exchanges the authorization code for an access token and queries
  the UserInfo API to retrieve the user's e-mail address.
  If a refresh token has been retrieved along with an access token, it is stored
  in the application database using the user's e-mail address as key.
  If no refresh token has been retrieved, the function checks in the application
  database for one and returns it if found or raises a NoRefreshTokenException
  with the authorization URL to redirect the user to.

  Args:
    authorization_code: Authorization code to use to retrieve an access token.
    state: State to set to the authorization URL in case of error.
  Returns:
    oauth2client.client.OAuth2Credentials instance containing an access and
    refresh token.
  Raises:
    CodeExchangeError: Could not exchange the authorization code.
    NoRefreshTokenException: No refresh token could be retrieved from the
                             available sources.
  """
  email_address = ''
  try:
    credentials = exchange_code(authorization_code)
    user_info = get_user_info(credentials)
    email_address = user_info.get('email')
    user_id = user_info.get('id')
    if credentials.refresh_token is not None:
      store_credentials(user_id, credentials)
      return credentials
    else:
      credentials = get_stored_credentials(user_id)
      if credentials and credentials.refresh_token is not None:
        return credentials
  except CodeExchangeException, error:
    logging.error('An error occurred during code exchange.')
    # Drive apps should try to retrieve the user and credentials for the current
    # session.
    # If none is available, redirect the user to the authorization URL.
    error.authorization_url = get_authorization_url(email_address, state)
    raise error
  except NoUserIdException:
    logging.error('No user ID could be retrieved.')
  # No refresh token has been retrieved.
  authorization_url = get_authorization_url(email_address, state)
  raise NoRefreshTokenException(authorization_url)

PHP

The getCredentials function retrieves OAuth 2.0 Credentials starting from the provided authorization code. If no refresh token could be retrieved, an exception is raised along with an authorization URL to redirect the user to in order to request offline access.

<?php
require_once 'google-api-php-client/src/Google_Client.php';
require_once "google-api-php-client/src/contrib/Google_Oauth2Service.php";
session_start();
// ...

$CLIENT_ID = '<YOUR_CLIENT_ID>';
$CLIENT_SECRET = '<YOUR_CLIENT_SECRET>';
$REDIRECT_URI = '<YOUR_REGISTERED_REDIRECT_URI>';
$SCOPES = array(
    'https://www.googleapis.com/auth/drive.file',
    'https://www.googleapis.com/auth/userinfo.email',
    'https://www.googleapis.com/auth/userinfo.profile');


/**
 * Exception thrown when an error occurred while retrieving credentials.
 */
class GetCredentialsException extends Exception {
  protected $authorizationUrl;

  /**
   * Construct a GetCredentialsException.
   *
   * @param authorizationUrl The authorization URL to redirect the user to.
   */
  public function __construct($authorizationUrl) {
    $this->authorizationUrl = $authorizationUrl;
  }

  /**
   * @return the authorizationUrl.
   */
  public function getAuthorizationUrl() {
    return $this->authorizationUrl;
  }

  /**
   * Set the authorization URL.
   */
  public function setAuthorizationurl($authorizationUrl) {
    $this->authorizationUrl = $authorizationUrl;
  }
}

/**
 * Exception thrown when no refresh token has been found.
 */
class NoRefreshTokenException extends GetCredentialsException {}

/**
 * Exception thrown when a code exchange has failed.
 */
class CodeExchangeException extends GetCredentialsException {}

/**
 * Exception thrown when no user ID could be retrieved.
 */
class NoUserIdException extends Exception {}

/**
 * Retrieved stored credentials for the provided user ID.
 *
 * @param String $userId User's ID.
 * @return String Json representation of the OAuth 2.0 credentials.
 */
function getStoredCredentials($userId) {
  // TODO: Implement this function to work with your database.
  throw new RuntimeException('Not implemented!');
}

/**
 * Store OAuth 2.0 credentials in the application's database.
 *
 * @param String $userId User's ID.
 * @param String $credentials Json representation of the OAuth 2.0 credentials to
                              store.
 */
function storeCredentials($userId, $credentials) {
  // TODO: Implement this function to work with your database.
  throw new RuntimeException('Not implemented!');
}

/**
 * Exchange an authorization code for OAuth 2.0 credentials.
 *
 * @param String $authorizationCode Authorization code to exchange for OAuth 2.0
 *                                  credentials.
 * @return String Json representation of the OAuth 2.0 credentials.
 * @throws CodeExchangeException An error occurred.
 */
function exchangeCode($authorizationCode) {
  try {
    global $CLIENT_ID, $CLIENT_SECRET, $REDIRECT_URI;
    $client = new Google_Client();

    $client->setClientId($CLIENT_ID);
    $client->setClientSecret($CLIENT_SECRET);
    $client->setRedirectUri($REDIRECT_URI);
    $_GET['code'] = $authorizationCode;
    return $client->authenticate();
  } catch (Google_AuthException $e) {
    print 'An error occurred: ' . $e->getMessage();
    throw new CodeExchangeException(null);
  }
}

/**
 * Send a request to the UserInfo API to retrieve the user's information.
 *
 * @param String credentials OAuth 2.0 credentials to authorize the request.
 * @return Userinfo User's information.
 * @throws NoUserIdException An error occurred.
 */
function getUserInfo($credentials) {
  $apiClient = new Google_Client();
  $apiClient->setUseObjects(true);
  $apiClient->setAccessToken($credentials);
  $userInfoService = new Google_Oauth2Service($apiClient);
  $userInfo = null;
  try {
    $userInfo = $userInfoService->userinfo->get();
  } catch (Google_Exception $e) {
    print 'An error occurred: ' . $e->getMessage();
  }
  if ($userInfo != null && $userInfo->getId() != null) {
    return $userInfo;
  } else {
    throw new NoUserIdException();
  }
}

/**
 * Retrieve the authorization URL.
 *
 * @param String $emailAddress User's e-mail address.
 * @param String $state State for the authorization URL.
 * @return String Authorization URL to redirect the user to.
 */
function getAuthorizationUrl($emailAddress, $state) {
  global $CLIENT_ID, $REDIRECT_URI, $SCOPES;
  $client = new Google_Client();

  $client->setClientId($CLIENT_ID);
  $client->setRedirectUri($REDIRECT_URI);
  $client->setAccessType('offline');
  $client->setApprovalPrompt('force');
  $client->setState($state);
  $client->setScopes($SCOPES);
  $tmpUrl = parse_url($client->createAuthUrl());
  $query = explode('&', $tmpUrl['query']);
  $query[] = 'user_id=' . urlencode($emailAddress);
  return
      $tmpUrl['scheme'] . '://' . $tmpUrl['host'] . $tmpUrl['port'] .
      $tmpUrl['path'] . '?' . implode('&', $query);
}

/**
 * Retrieve credentials using the provided authorization code.
 *
 * This function exchanges the authorization code for an access token and
 * queries the UserInfo API to retrieve the user's e-mail address. If a
 * refresh token has been retrieved along with an access token, it is stored
 * in the application database using the user's e-mail address as key. If no
 * refresh token has been retrieved, the function checks in the application
 * database for one and returns it if found or throws a NoRefreshTokenException
 * with the authorization URL to redirect the user to.
 *
 * @param String authorizationCode Authorization code to use to retrieve an access
 *                                 token.
 * @param String state State to set to the authorization URL in case of error.
 * @return String Json representation of the OAuth 2.0 credentials.
 * @throws NoRefreshTokenException No refresh token could be retrieved from
 *         the available sources.
 */
function getCredentials($authorizationCode, $state) {
  $emailAddress = '';
  try {
    $credentials = exchangeCode($authorizationCode);
    $userInfo = getUserInfo($credentials);
    $emailAddress = $userInfo->getEmail();
    $userId = $userInfo->getId();
    $credentialsArray = json_decode($credentials, true);
    if (isset($credentialsArray['refresh_token'])) {
      storeCredentials($userId, $credentials);
      return $credentials;
    } else {
      $credentials = getStoredCredentials($userId);
      $credentialsArray = json_decode($credentials, true);
      if ($credentials != null &&
          isset($credentialsArray['refresh_token'])) {
        return $credentials;
      }
    }
  } catch (CodeExchangeException $e) {
    print 'An error occurred during code exchange.';
    // Drive apps should try to retrieve the user and credentials for the current
    // session.
    // If none is available, redirect the user to the authorization URL.
    $e->setAuthorizationUrl(getAuthorizationUrl($emailAddress, $state));
    throw $e;
  } catch (NoUserIdException $e) {
    print 'No e-mail address could be retrieved.';
  }
  // No refresh token has been retrieved.
  $authorizationUrl = getAuthorizationUrl($emailAddress, $state);
  throw new NoRefreshTokenException($authorizationUrl);
}
?>

.NET

The GetCredentials function retrieves OAuth 2.0 Credentials starting from the provided authorization code. If no refresh token could be retrieved, an exception is raised along with an authorization URL to redirect the user to in order to request offline access.

using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth2;
using Google;
using Google.Apis.Authentication;
using Google.Apis.Authentication.OAuth2;
using Google.Apis.Authentication.OAuth2.DotNetOpenAuth;
using Google.Apis.Oauth2.v2;
using Google.Apis.Oauth2.v2.Data;
using System;
using System.Collections.Specialized;
using System.Web;
// ...

class MyClass {

  static String CLIENT_ID = "<YOUR_CLIENT_ID>";
  static String CLIENT_SECRET = "<YOUR_CLIENT_SECRET>";
  static String REDIRECT_URI = "<YOUR_REGISTERED_REDIRECT_URI>";
  static String[] SCOPES = new String[] {
      "https://www.googleapis.com/auth/drive.file",
      "https://www.googleapis.com/auth/userinfo.email",
      "https://www.googleapis.com/auth/userinfo.profile"
  };

  /// <summary>
  /// Exception thrown when an error occurred while retrieving credentials.
  /// </summary>
  public class GetCredentialsException : Exception {

    public String AuthorizationUrl { get; set; }

    /// <summary>
    /// Construct a GetCredentialsException.
    /// </summary>
    /// @param authorizationUrl The authorization URL to redirect the user to.
    public GetCredentialsException(String authorizationUrl) {
      this.AuthorizationUrl = authorizationUrl;
    }

  }

  /// <summary>
  /// Exception thrown when no refresh token has been found.
  /// </summary>
  public class NoRefreshTokenException : GetCredentialsException {

    /// <summary>
    /// Construct a NoRefreshTokenException.
    /// </summary>
    /// @param authorizationUrl The authorization URL to redirect the user to.
    public NoRefreshTokenException(String authorizationUrl) : base(authorizationUrl) {
    }

  }

  /// <summary>
  /// Exception thrown when a code exchange has failed.
  /// </summary>
  private class CodeExchangeException : GetCredentialsException {

    /// <summary>
    /// Construct a CodeExchangeException.
    /// </summary>
    /// @param authorizationUrl The authorization URL to redirect the user to.
    public CodeExchangeException(String authorizationUrl) : base(authorizationUrl) {
    }

  }

  /// <summary>
  /// Exception thrown when no user ID could be retrieved.
  /// </summary>
  private class NoUserIdException : Exception {
  }

  /// <summary>
  /// Extends the NativeApplicationClient class to allow setting of a custom IAuthorizationState.
  /// </summary>
  public class StoredStateClient : NativeApplicationClient {
    /// <summary>
    /// Initializes a new instance of the <see cref="StoredStateClient"/> class.
    /// </summary>
    /// <param name="authorizationServer">The token issuer.</param>
    /// <param name="clientIdentifier">The client identifier.</param>
    /// <param name="clientSecret">The client secret.</param>
    public StoredStateClient(AuthorizationServerDescription authorizationServer,
        String clientIdentifier,
        String clientSecret,
        IAuthorizationState state)
        : base(authorizationServer, clientIdentifier, clientSecret) {
      this.State = state;
    }

    public IAuthorizationState State { get; private set; }

    /// <summary>
    /// Returns the IAuthorizationState stored in the StoredStateClient instance.
    /// </summary>
    /// <param name="provider">OAuth2 client.</param>
    /// <returns>The stored authorization state.</returns>
    static public IAuthorizationState GetState(StoredStateClient provider) {
      return provider.State;
    }
  }

  /// <summary>
  /// Retrieve an IAuthenticator instance using the provided state.
  /// </summary>
  /// <param name="credentials">OAuth 2.0 credentials to use.</param>
  /// <returns>Authenticator using the provided OAuth 2.0 credentials</returns>
  public static IAuthenticator GetAuthenticatorFromState(IAuthorizationState credentials) {
    var provider = new StoredStateClient(GoogleAuthenticationServer.Description, CLIENT_ID, CLIENT_SECRET, credentials);
    var auth = new OAuth2Authenticator<StoredStateClient>(provider, StoredStateClient.GetState);
    auth.LoadAccessToken();
    return auth;
  }

  /// <summary>
  /// Retrieved stored credentials for the provided user ID.
  /// </summary>
  /// <param name="userId">User's ID.</param>
  /// <returns>Stored GoogleAccessProtectedResource if found, null otherwise.</returns>
  static IAuthorizationState GetStoredCredentials(String userId) {
    // TODO: Implement this method to work with your database.
    throw new NotImplementedException();
  }

  /// <summary>
  /// Store OAuth 2.0 credentials in the application's database.
  /// </summary>
  /// <param name="userId">User's ID.</param>
  /// <param name="credentials">The OAuth 2.0 credentials to store.</param>
  static void StoreCredentials(String userId, IAuthorizationState credentials) {
    // TODO: Implement this method to work with your database.
    throw new NotImplementedException();
  }

  /// <summary>
  /// Exchange an authorization code for OAuth 2.0 credentials.
  /// </summary>
  /// <param name="authorizationCode">Authorization code to exchange for OAuth 2.0 credentials.</param>
  /// <returns>OAuth 2.0 credentials.</returns>
  /// <exception cref="CodeExchangeException">An error occurred.</exception>
  static IAuthorizationState ExchangeCode(String authorizationCode) {
    var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description, CLIENT_ID, CLIENT_SECRET);
    IAuthorizationState state = new AuthorizationState();
    state.Callback = new Uri(REDIRECT_URI);
    try {
      state = provider.ProcessUserAuthorization(authorizationCode, state);
      return state;
    } catch (ProtocolException) {
      throw new CodeExchangeException(null);
    }
  }

  /// <summary>
  /// Send a request to the UserInfo API to retrieve the user's information.
  /// </summary>
  /// <param name="credentials">OAuth 2.0 credentials to authorize the request.</param>
  /// <returns>User's information.</returns>
  /// <exception cref="NoUserIdException">An error occurred.</exception>
  static Userinfo GetUserInfo(IAuthorizationState credentials) {
    Oauth2Service userInfoService = new Oauth2Service(GetAuthenticatorFromState(credentials));
    Userinfo userInfo = null;
    try {
      userInfo = userInfoService.Userinfo.Get().Fetch();
    } catch (GoogleApiRequestException e) {
      Console.WriteLine("An error occurred: " + e.Message);
    }
    if (userInfo != null && !String.IsNullOrEmpty(userInfo.Id)) {
      return userInfo;
    } else {
      throw new NoUserIdException();
    }
  }

  /// <summary>
  /// Retrieve the authorization URL.
  /// </summary>
  /// <param name="emailAddress">User's e-mail address.</param>
  /// <param name="state">State for the authorization URL.</param>
  /// <returns>Authorization URL to redirect the user to.</returns>
  public static String GetAuthorizationUrl(String emailAddress, String state) {
    var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description);
    provider.ClientIdentifier = CLIENT_ID;

    IAuthorizationState authorizationState = new AuthorizationState(SCOPES);
    authorizationState.Callback = new Uri(REDIRECT_URI);

    UriBuilder builder = new UriBuilder(provider.RequestUserAuthorization(authorizationState));
    NameValueCollection queryParameters = HttpUtility.ParseQueryString(builder.Query);

    queryParameters.Set("access_type", "offline");
    queryParameters.Set("approval_prompt", "force");
    queryParameters.Set("user_id", emailAddress);
    queryParameters.Set("state", state);

    builder.Query = queryParameters.ToString();
    return builder.Uri.ToString();
  }

  /// <summary>
  /// Retrieve credentials using the provided authorization code.
  ///
  /// This function exchanges the authorization code for an access token and
  /// queries the UserInfo API to retrieve the user's e-mail address. If a
  /// refresh token has been retrieved along with an access token, it is stored
  /// in the application database using the user's e-mail address as key. If no
  /// refresh token has been retrieved, the function checks in the application
  /// database for one and returns it if found or throws a NoRefreshTokenException
  /// with the authorization URL to redirect the user to.
  /// </summary>
  /// <param name="authorizationCode">Authorization code to use to retrieve an access token.</param>
  /// <param name="state">State to set to the authorization URL in case of error.</param>
  /// <returns>OAuth 2.0 credentials instance containing an access and refresh token.</returns>
  /// <exception cref="CodeExchangeException">
  /// An error occurred while exchanging the authorization code.
  /// </exception>
  /// <exception cref="NoRefreshTokenException">
  /// No refresh token could be retrieved from the available sources.
  /// </exception>
  public static IAuthenticator GetCredentials(String authorizationCode, String state) {
    String emailAddress = "";
    try {
      IAuthorizationState credentials = ExchangeCode(authorizationCode);
      Userinfo userInfo = GetUserInfo(credentials);
      String userId = userInfo.Id;
      emailAddress = userInfo.Email;
      if (!String.IsNullOrEmpty(credentials.RefreshToken)) {
        StoreCredentials(userId, credentials);
        return GetAuthenticatorFromState(credentials);
      } else {
        credentials = GetStoredCredentials(userId);
        if (credentials != null && !String.IsNullOrEmpty(credentials.RefreshToken)) {
          return GetAuthenticatorFromState(credentials);
        }
      }
    } catch (CodeExchangeException e) {
      Console.WriteLine("An error occurred during code exchange.");
      // Drive apps should try to retrieve the user and credentials for the current
      // session.
      // If none is available, redirect the user to the authorization URL.
      e.AuthorizationUrl = GetAuthorizationUrl(emailAddress, state);
      throw e;
    } catch (NoUserIdException) {
      Console.WriteLine("No user ID could be retrieved.");
    }
    // No refresh token has been retrieved.
    String authorizationUrl = GetAuthorizationUrl(emailAddress, state);
    throw new NoRefreshTokenException(authorizationUrl);
  }

}

Ruby

The get_credentials function retrieves OAuth 2.0 Credentials starting from the provided authorization code. If no refresh token could be retrieved, an exception is raised along with an authorization URL to redirect the user to in order to request offline access.

require 'google/api_client'

CLIENT_ID = '<YOUR_CLIENT_ID>'
CLIENT_SECRET = '<YOUR_CLIENT_SECRET>'
REDIRECT_URI = '<YOUR_REGISTERED_REDIRECT_URI>'
SCOPES = [
    'https://www.googleapis.com/auth/drive.file',
    'https://www.googleapis.com/auth/userinfo.email',
    'https://www.googleapis.com/auth/userinfo.profile',
    # Add other requested scopes.
]

##
# Error raised when an error occurred while retrieving credentials.
class GetCredentialsError < StandardError
  ##
  # Initialize a NoRefreshTokenError instance.
  #
  # @param [String] authorize_url
  #   Authorization URL to redirect the user to in order to in order to request
  #   offline access.
  def initialize(authorization_url)
    @authorization_url = authorization_url
  end

  def authorization_url=(authorization_url)
    @authorization_url = authorization_url
  end

  def authorization_url
    return @authorization_url
  end
end

##
# Error raised when a code exchange has failed.
class CodeExchangeError < GetCredentialsError
end

##
# Error raised when no refresh token has been found.
class NoRefreshTokenError < GetCredentialsError
end

##
# Error raised when no user ID could be retrieved.
class NoUserIdError < StandardError
end

##
# Retrieved stored credentials for the provided user ID.
#
# @param [String] user_id
#   User's ID.
# @return [Signet::OAuth2::Client]
#  Stored OAuth 2.0 credentials if found, nil otherwise.
def get_stored_credentials(user_id)
  raise NotImplementedError, 'get_stored_credentials is not implemented.'
end

##
# Store OAuth 2.0 credentials in the application's database.
#
# @param [String] user_id
#   User's ID.
# @param [Signet::OAuth2::Client] credentials
#   OAuth 2.0 credentials to store.
def store_credentials(user_id, credentials)
  raise NotImplementedError, 'store_credentials is not implemented.'
end

##
# Exchange an authorization code for OAuth 2.0 credentials.
#
# @param [String] auth_code
#   Authorization code to exchange for OAuth 2.0 credentials.
# @return [Signet::OAuth2::Client]
#  OAuth 2.0 credentials.
def exchange_code(authorization_code)
  client = Google::APIClient.new
  client.authorization.client_id = CLIENT_ID
  client.authorization.client_secret = CLIENT_SECRET
  client.authorization.code = authorization_code
  client.authorization.redirect_uri = REDIRECT_URI

  begin
    client.authorization.fetch_access_token!
    return client.authorization
  rescue Signet::AuthorizationError
    raise CodeExchangeError.new(nil)
  end
end

##
# Send a request to the UserInfo API to retrieve the user's information.
#
# @param [Signet::OAuth2::Client] credentials
#   OAuth 2.0 credentials to authorize the request.
# @return [Google::APIClient::Schema::Oauth2::V2::Userinfo]
#   User's information.
def get_user_info(credentials)
  client = Google::APIClient.new
  client.authorization = credentials
  oauth2 = client.discovered_api('oauth2', 'v2')
  result = client.execute!(:api_method => oauth2.userinfo.get)
  user_info = nil
  if result.status == 200
    user_info = result.data
  else
    puts "An error occurred: #{result.data['error']['message']}"
  end
  if user_info != nil && user_info.id != nil
    return user_info
  end
  raise NoUserIdError, 'Unable to retrieve the e-mail address.'
end

##
# Retrieve authorization URL.
#
# @param [String] email_address
#   User's e-mail address.
# @param [String] state
#   State for the authorization URL.
# @return [String]
#  Authorization URL to redirect the user to.
def get_authorization_url(email_address, state)
  client = Google::APIClient.new
  client.authorization.client_id = CLIENT_ID
  client.authorization.redirect_uri = REDIRECT_URI
  client.authorization.scope = SCOPES

  return client.authorization.authorization_uri(
    :options => {
       :approval_prompt => :force,
       :access_type => :offline,
       :user_id => email_address,
       :state => state
    }).to_s
end

##
# Retrieve credentials using the provided authorization code.
#
#  This function exchanges the authorization code for an access token and queries
#  the UserInfo API to retrieve the user's e-mail address.
#  If a refresh token has been retrieved along with an access token, it is stored
#  in the application database using the user's e-mail address as key.
#  If no refresh token has been retrieved, the function checks in the application
#  database for one and returns it if found or raises a NoRefreshTokenError
#  with an authorization URL to redirect the user to.
#
# @param [String] auth_code
#   Authorization code to use to retrieve an access token.
# @param [String] state
#   State to set to the authorization URL in case of error.
# @return [Signet::OAuth2::Client]
#  OAuth 2.0 credentials containing an access and refresh token.
def get_credentials(authorization_code, state)
  email_address = ''
  begin
    credentials = exchange_code(authorization_code)
    user_info = get_user_info(credentials)
    email_address = user_info.email
    user_id = user_info.id
    if credentials.refresh_token != nil
      store_credentials(user_id, credentials)
      return credentials
    else
      credentials = get_stored_credentials(user_id)
      if credentials != nil && credentials.refresh_token != nil
        return credentials
      end
    end
  rescue CodeExchangeError => error
    print 'An error occurred during code exchange.'
    # Drive apps should try to retrieve the user and credentials for the current
    # session.
    # If none is available, redirect the user to the authorization URL.
    error.authorization_url = get_authorization_url(email_address, state)
    raise error
  rescue NoUserIdError
    print 'No user ID could be retrieved.'
  end
  authorization_url = get_authorization_url(email_address, state)
  raise NoRefreshTokenError.new(authorization_url)
end

Authorizing with stored credentials

When users visit your app after a successful first-time authorization flow, your application can use a stored refresh token to authorize requests without prompting the end user.

If you have already authenticated the user, your application can retrive the refresh token from its database and store the token in a server-side session. If the refresh token is revoked or is otherwise invalid, you'll need to catch this and take appropriate action as described in Handling revoked or invalid refresh tokens.

Using OAuth 2.0 credentials

Once OAuth 2.0 credentials have been retrieved as shown in the previous section, they can be used to authorize a Drive service object and send requests to the API.

The following code snippets show how to instantiate and authorize a Drive service object and send a request to the Drive API to retrieve a File's metadata.

Instantiate a service object

This code sample shows how to instantiate a service object and then authorize it to make API requests.

Java

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;

import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson.JacksonFactory;

import com.google.api.services.drive.Drive;
// ...

public class MyClass {
  // ...

  /**
    * Build a Drive service object.
    *
    * @param credentials OAuth 2.0 credentials.
    * @return Drive service object.
    */
  static Drive buildService(GoogleCredential credentials) {
    HttpTransport httpTransport = new NetHttpTransport();
    JacksonFactory jsonFactory = new JacksonFactory();

    return new Drive.Builder(httpTransport, jsonFactory, credentials)
        .build();
  }

  // ...
}

Python

from apiclient.discovery import build
# ...

def build_service(credentials):
  """Build a Drive service object.

  Args:
    credentials: OAuth 2.0 credentials.

  Returns:
    Drive service object.
  """
  http = httplib2.Http()
  http = credentials.authorize(http)
  return build('drive', 'v2', http=http)

PHP

<?php
session_start();

require_once "google-api-php-client/src/Google_Client.php";
require_once "google-api-php-client/src/contrib/Google_DriveService.php";

// ...

/**
 * Build a Drive service object.
 *
 * @param String credentials Json representation of the OAuth 2.0 credentials.
 * @return Google_DriveService service object.
 */
function buildService($credentials) {
  $apiClient = new Google_Client();
  $apiClient->setUseObjects(true);
  $apiClient->setAccessToken($credentials);
  return new Google_DriveService($apiClient);
}

// ...
?>

.NET

using Google.Apis.Authentication;

using Google.Apis.Drive.v2;
// ...

public class MyClass {
  // ...

  /// <summary>
  /// Build a Drive service object.
  /// </summary>
  /// <param name="credentials">OAuth 2.0 credentials.</param>
  /// <returns>Drive service object.</returns>
  static DriveService BuildService(IAuthenticator credentials) {
    return new DriveService(credentials);
  }
}

Ruby

require 'google/api_client'

##
# Build a Drive client instance.
#
# @param [Signet::OAuth2::Client] credentials
#   OAuth 2.0 credentials.
# @return [Google::APIClient]
#   Client instance
def build_client(credentials)
  client = Google::APIClient.new
  client.authorization = credentials
  client = client.discovered_api('drive', 'v2')
  client
end

Send authorized requests and check for revoked credentials

The following code snippet uses an authorized Drive service instance and sends an authorized GET request to the Drive API to retrieve a File's metadata.

If an error occurs, the code checks for an HTTP 401 status code, which should be handled by redirecting the user to the authorization URL.

More Drive API operations are documented in the API Reference.

Java

import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.HttpResponseException;

import com.google.api.services.drive.Drive;
import com.google.api.services.drive.model.File;

import java.io.IOException;
// ...

public class MyClass {
  // ...

  /**
    * Print a file's metadata.
    *
    * @param service Drive API service instance.
    * @param fileId ID of the file to print metadata for.
    */
  static void printFile(Drive service, String fileId) {
    try {
      File file = service.files().get(fileId).execute();

      System.out.println("Title: " + file.getTitle());
      System.out.println("Description: " + file.getDescription());
      System.out.println("MIME type: " + file.getMimeType());
    } catch (HttpResponseException e) {
      if (e.getStatusCode() == 401) {
        // Credentials have been revoked.
        // TODO: Redirect the user to the authorization URL.
        throw new UnsupportedOperationException();
      }
    } catch (IOException e) {
      System.out.println("An error occurred: " + e);
    }
  }

  // ...
}

Python

from apiclient import errors
# ...

def print_file(service, file_id):
  """Print a file's metadata.

  Args:
    service: Drive API service instance.
    file_id: ID of the file to print metadata for.
  """
  try:
    file = service.files().get(fileId=file_id).execute()

    print 'Title: %s' % file['title']
    print 'Description: %s' % file['description']
    print 'MIME type: %s' % file['mimeType']
  except errors.HttpError, error:
    if error.resp.status == 401:
      # Credentials have been revoked.
      # TODO: Redirect the user to the authorization URL.
      raise NotImplementedError()

PHP

/**
 * Print a file's metadata.
 *
 * @param apiDriveService $service Drive API service instance.
 * @param string $fileId ID of the file to print metadata for.
 */
function printFile($service, $fileId) {
  try {
    $file = $service->files->get($fileId);

    print "Title: " . $file->getTitle();
    print "Description: " . $file->getDescription();
    print "MIME type: " . $file->getMimeType();
  } catch (apiAuthException) {
    // Credentials have been revoked.
    // TODO: Redirect the user to the authorization URL.
    throw new RuntimeException('Not implemented!');
  } catch (apiException $e) {
    print "An error occurred: " . $e->getMessage();
  }
}

.NET

using Google;
using Google.Apis.Drive.v2;
using Google.Apis.Drive.v2.Data;

using System;
using System.Net;
// ...

public class MyClass {

  // ...

  /// <summary>
  /// Print a file's metadata.
  /// </summary>
  /// <param name="service">Drive API service instance.</param>
  /// <param name="fileId">ID of the file to print metadata for.</param>
  private static void printFile(DriveService service, String fileId) {
    try {
      File file = service.Files.Get(fileId).Fetch();

      Console.WriteLine("Title: " + file.Title);
      Console.WriteLine("Description: " + file.Description);
      Console.WriteLine("MIME type: " + file.MimeType);
    } catch (GoogleApiRequestException e) {
      if (e.HttpStatusCode == HttpStatusCode.Unauthorized) {
        // Credentials have been revoked.
        // TODO: Redirect the user to the authorization URL.
        throw new NotImplementedException();
      }
    }
  }

  //...

}

Ruby

require 'google/api_client'

##
# Print a file's metadata.
#
# @param [Google::APIClient] client
#   Authorized client instance
# @param [String] file_id
#   ID of file to print
# @return nil
def print_file(client, file_id)
  result = client.execute(
    :api_method => client.files.get,
    :parameters => { 'id' => file_id })
  if result.status == 200
    file = result.data
    puts "Title: #{file.data}"
    puts "Description: #{file.description}"
    puts "MIME type: #{file.mime_type}"
  elseif result.status == 401
      # Credentials have been revoked.
      # TODO: Redirect the user to the authorization URL.
      raise NotImplementedError, 'Redirect the user.'
    end
  else
    puts "An error occurred: #{result.data['error']['message']}"
  end
end

Next steps

Once you are comfortable authorizing Drive API requests, you're ready to upload files and perform any of the other operations described in "Manage Drive Files." You can learn more about available API methods in the API Reference, and you can review our end-to-end Example Apps to examine some working code.

Authentication required

You need to be signed in with Google+ to do that.

Signing you in...

Google Developers needs your permission to do that.