Сценарий, который вы описываете, где клиент имеет облачную учетную запись Google и вы, как третья сторона, хочет действовать от имени клиента, является центральной особенностью OAuth 2. К сожалению, потому что он включает в себя 3 разных участника, разделяющих учетные данные, это также самый сложный способ аутентификации с помощью Google Cloud. Как это работает, ваше приложение запрашивает согласие пользователя, пользователь сообщает Google об этом согласии, а Google дает вам полномочия действовать от имени этого пользователя. Поскольку задействованы три стороны, это называется 3-legged OAuth (3LO).
Вот краткий обзор этого OAuth потока: https://developers.google.com/identity/protocols/OAuth2WebServer#overview
А вот пример построения этого с использованием библиотеки Java: https://developers.google.com/api-client-library/java/google-api-java-client/oauth2#web_server_applications
Вот важный раздел Java кода из этого примера:
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
}
}
Следует отметить, что этот код построен вокруг общей модели Java «Servlet», а также предполагает, что вы используете какое-то хранилище данных, чтобы запоминать токены обновления для своих пользователей. Конечным результатом всего танца OAuth является получение «токена обновления», который вы можете периодически использовать для получения временного «токена сеанса», который может длиться до часа. Для запоминания всех этих токенов вам нужно использовать хранилище данных.