0
votes

I am writing a service which shall write data to different Google Cloud Storage account. The owner's of the accounts shall "sign up" with my service and I will be periodically writing data to their account's bucket.

I want to make the "signup" as easy as possible. I am still trying to wrap my head around google's OAuth2. I want to ideally create my own account to which the owner can give permission to buckets and I can write to their bucket. How do i achieve that ? I want to write data programmatically in JAVA

1

1 Answers

0
votes

The scenario you describe, where a customer has a Google cloud account and you as a third party want to act on the customer's behalf, is a central feature of OAuth 2. Unfortunately, because it involves 3 different parties sharing credential stuff, it's also the most complex way to authenticate with Google Cloud. The way this works is that your app requests the user's consent, the user tells Google about that consent, and Google gives you credentials to act on that user's behalf. Because there are three parties involved, this is called 3-legged OAuth (3LO).

Here's an overview of this OAuth flow: https://developers.google.com/identity/protocols/OAuth2WebServer#overview

And here's an example of building this using the Java library: https://developers.google.com/api-client-library/java/google-api-java-client/oauth2#web_server_applications

Here's the important section of Java code from that example:

public class CalendarServletSample extends AbstractAuthorizationCodeServlet {

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws IOException {
    // do stuff
  }

  @Override
  protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
    GenericUrl url = new GenericUrl(req.getRequestURL().toString());
    url.setRawPath("/oauth2callback");
    return url.build();
  }

  @Override
  protected AuthorizationCodeFlow initializeFlow() throws IOException {
    return new GoogleAuthorizationCodeFlow.Builder(
        new NetHttpTransport(), JacksonFactory.getDefaultInstance(),
        "[[ENTER YOUR CLIENT ID]]", "[[ENTER YOUR CLIENT SECRET]]",
        Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory(
        DATA_STORE_FACTORY).setAccessType("offline").build();
  }

  @Override
  protected String getUserId(HttpServletRequest req) throws ServletException, IOException {
    // return user ID
  }
}

public class CalendarServletCallbackSample extends AbstractAuthorizationCodeCallbackServlet {

  @Override
  protected void onSuccess(HttpServletRequest req, HttpServletResponse resp, Credential credential)
      throws ServletException, IOException {
    resp.sendRedirect("/");
  }

  @Override
  protected void onError(
      HttpServletRequest req, HttpServletResponse resp, AuthorizationCodeResponseUrl errorResponse)
      throws ServletException, IOException {
    // handle error
  }

  @Override
  protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
    GenericUrl url = new GenericUrl(req.getRequestURL().toString());
    url.setRawPath("/oauth2callback");
    return url.build();
  }

  @Override
  protected AuthorizationCodeFlow initializeFlow() throws IOException {
    return new GoogleAuthorizationCodeFlow.Builder(
        new NetHttpTransport(), JacksonFactory.getDefaultInstance()
        "[[ENTER YOUR CLIENT ID]]", "[[ENTER YOUR CLIENT SECRET]]",
        Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory(
        DATA_STORE_FACTORY).setAccessType("offline").build();
  }

  @Override
  protected String getUserId(HttpServletRequest req) throws ServletException, IOException {
    // return user ID
  }
}

You should note that this code is built around the common Java "Servlet" model, and it also assumes you're using some sort of data store to remember the refresh tokens for your users. The end result of the whole OAuth dance is you getting a "refresh token", which you can periodically use to gain a temporary "session token" that can last for up to an hour. You'll need to use some sort of data store to remember all of these tokens.