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 завершится неудачей.
Мой вопрос:
- Есть ли способ проверить правильность учетных данных, прежде чем пытаться их использовать? Иначе, я могу только догадываться, что сбой при получении объекта клиента - единственный способ заставить мой портал понять, что учетные данные больше не действительны?
- Что мне делать с недействительными / отозванными учетными данными? я должен просто позвонить
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; }