Google OAuth, обработайте отмененную авторизацию

Я использую Google OAuth, чтобы разрешить пользователям доступ к службе календаря для моего веб-приложения. После успешного трехстороннего процесса аутентификации я сохранял все учетные данные пользователя в общем файле на сервере приложений. В следующий раз, когда приложению понадобится использовать службу, оно проверит, существуют ли учетные данные, и если да, то будет считать, что они действительны.

код работает так

@Override
public void _authorize(String userId) throws IOException {

    // Check if user has already authorised the service.
    Credential credents = flow.loadCredential(userId);

    // Checking if the given user is not authorized
    if (credents == null) {

        //Create credentials now. user will be redirected to authorise 

        try {
            //Creating a LocalServer Receiver
            // Getting the redirect URI
            // Creating a new authorization URL
            // Setting the redirect URI
            // Building the authorization URL
            // Receiving authorization code
            // Exchanging it for an access token

            // Storing the credentials for later access
            credents = flow.createAndStoreCredential(response, id);

        } finally {
            // Releasing resources
        }
    } else {
        // Assume the credentials are valid. so there's nothing left to do here, let's get that client
        //Update: Nooooooot! the user might have revoked the authorization, so credents != null BUT they are invalid
        //TODO: handle an Exception here, and manage the revoked credentials 
    }

    // Setting up the calendar service client
    client = new com.google.api.services.calendar.Calendar.Builder(httpTransport, jsonFactory, credents).setApplicationName(APPLICATION_NAME)
            .build();

}

Это работает нормально, пока пользователь никогда не передумает. Но если пользователь решит отменить авторизацию вручную, используя параметры безопасности аккаунта Google, получение com.google.api.services.calendar.Calendar завершится неудачей.

Мой вопрос:

  1. Есть ли способ проверить правильность учетных данных, прежде чем пытаться их использовать? Иначе, я могу только догадываться, что сбой при получении объекта клиента - единственный способ заставить мой портал понять, что учетные данные больше не действительны?
  2. Что мне делать с недействительными / отозванными учетными данными? я должен просто позвонить flow.createAndStoreCredential и они собираются быть перезаписаны? Или я должен сначала удалить старые? (как?)

4 ответа

Решение

Вы можете использовать конечную точку https://www.googleapis.com/oauth2/v1/tokeninfo чтобы определить, действителен ли токен OAuth2. Более подробная информация доступна в руководстве OAuth2.

Для этого вы можете использовать метод refreshToken(). Смотрите пример:

// Fetch credential using the GoogleAuthorizationCodeFlow
GoogleAuthorizationCodeFlow authorizationCodeFlow;
Credential credential = authorizationCodeFlow.loadCredential(userId);
if (credential != null) {
    try {
        // refresh the credential to see if the refresh token is still valid
        credential.refreshToken();
        System.out.println("Refreshed: expires in: " + credential.getExpiresInSeconds());
    } catch (TokenResponseException e) {
        // process exception here.
        // This will catch the Exception.
        // This Exception contains the HTTP status and reason etc.
        // In case of a revoke, this will throw something like a 401 - "invalid_grant"
        return;
    }
} else {
    // No credential yet known.
    // Flow for creating a new credential here
}

РЕДАКТИРОВАТЬ Если у вас действительно есть недействительный токен обновления, и вы хотите его обновить, то вам нужно повторить шаги, которые вы в первую очередь сделали, чтобы получить учетные данные. Так:

  • создать новый URL авторизации
  • перенаправить пользователя на него
  • пользователь принимает экран согласия
  • поймать код авторизации из перенаправления обратно в ваше приложение
  • запросить новый токен у Google с помощью кода авторизации
  • создать и сохранить новые учетные данные, используя ответ от Google

Нет необходимости удалять старые учетные данные. Но если вы хотите явно сделать это, это возможно. Что-то вроде:

// This userId is obviously the same as you used to create the credential
String userId = "john.doe";
authorizationCodeFlow.getDataStore().delete(userId);

Ответ на первый вопрос:

При использовании объекта Сервис для извлечения элементов календаря из Календаря Google токен автоматически проверяется. Когда они недействительны, они автоматически обновляются и сохраняются в хранилище данных, которое вы предоставили потоку.

это также можно сделать вручную. Токен действителен в течение 3600 секунд (один час). При получении токена вы получаете это значение с отметкой времени, когда он был выпущен. Вы можете вручную определить, является ли токен действительным. Если это не так, вызовите следующий асинхронный метод.

await credents.RefreshtokenAsync(CancellationToken.None);

Эта функция получает свежие токены и сохраняет их в предоставленном вами хранилище данных.

Проверьте токен с помощью tokeninfo и, если токен недействителен: - удалите учетные данные из хранилища данных - вызовите новую аутентификацию

Защищенный void doGet(запрос HttpServletRequest, ответ HttpServletResponse) вызывает IOException, ServletException {UserService userService = UserServiceFactory.getUserService ();

    if (userService.isUserLoggedIn()) {
        User user = userService.getCurrentUser();
        log.info(String.format("LoggedUser: %s %s", user.getEmail(), user.getUserId()));
        Credential credential = this.getCredential();
        Tokeninfo tokenInfo = OAuth2Utils.getTokenInfo(credential, null);
        if (tokenInfo != null)
            log.info(String.format("Token expires in: %d", tokenInfo.getExpiresIn()));
        else {
            OAuth2Utils.deleteCredential(user.getUserId());
            response.sendRedirect(request.getRequestURI()); // recall this servlet to require new user authorization
            return;
        }

}

public static Tokeninfo getTokenInfo (учетные данные, String accessToken) {служба Oauth2 = новый Oauth2.Builder(новый NetHttpTransport(), Constant.JSON_FACTORY, учетные данные).setApplicationName(Constant.APP_NAME).build(); Tokeninfo tokenInfo = null; try { tokenInfo = service.tokeninfo().setAccessToken( accessToken == null? credential.getAccessToken(): accessToken).execute(); } catch (IOException e) { log.warning("Произошла ошибка: " + e); } return tokenInfo; }

Другие вопросы по тегам