Статьи

Учебник. Как реализовать Java OAuth 2.0 для входа в GitHub и Google

Герцог-OAuth-ява-ключи

Руководство по добавлению входа Google и GitHub OAuth в приложение Java

Одна из последних функций, которую мы добавили в Takipi, — это сторонняя регистрация. Если вы ленивы, как и я, то вы, вероятно, предпочитаете пропустить заполнение форм и создание новых паролей . Когда доступно, многие люди предпочитают сторонний вход, если запрашиваемые разрешения не являются навязчивыми — никто не хочет, чтобы случайные записи отображались на их стене Facebook, поэтому такой доступ включает только пользователя Основная информация, как имя и адреса электронной почты. В этом посте вы получите краткий обзор того, как мы реализовали это в Takipi, как вы можете использовать стороннюю регистрацию в своем приложении, а также несколько полезных советов, которые помогут вам сэкономить драгоценное время, если вы решите интегрировать это с вашим собственным приложением.

Новая статья: Как реализовать Java OAuth 2.0 для входа в систему с помощью GitHub и Google http://t.co/20Hn59dCtf pic.twitter.com/3tNNwPKjET

— Такипи (@takipid) 14 мая 2015 г.

Оказалось, что в нашей маленькой вселенной я не одинок в этом, и многие из наших пользователей чувствуют то же самое. Поскольку мы являемся стартапом инструментов разработчика, использование входа в GitHub и Google от сторонних разработчиков имело смысл. Помимо удобства для ваших пользователей, использование сторонних сервисов может повысить их безопасность. Поскольку Google и GitHub используют двухфакторную аутентификацию (2FA), ваше приложение получает этот уровень безопасности «бесплатно». В нашем случае мы уже включили 2FA, поэтому я думаю, что это делает нас… 3FA & # 55357; & # 56859;

Предварительный просмотр макета для нашей новой домашней страницы с помощью сторонних кнопок входа

Предварительный просмотр макета для нашей новой домашней страницы с помощью сторонних кнопок входа

Чтобы увидеть, как это работает на практике, вы можете проверить эту страницу, которую мы использовали для внутреннего тестирования. Это полностью работает, но обновление пока не доступно на сайте. Здесь у вас есть редкая возможность одним из первых использовать его 🙂

Напомни мне, как снова работает OAuth 2.0?

Процесс входа в OAuth выглядит следующим образом: пользователь заходит на ваш сайт, нажимает кнопку «Войти с помощью чего угодно» и перенаправляется на страницу разрешений. Страница разрешений поступает от Whither ™, и когда они одобряют запрашиваемые вами разрешения, Whither ™ отправляет им токен, который его браузер затем отправляет на серверную часть вашего приложения. Как только у вас есть токен, вы отправляете его обратно в Wh Wh ™ для проверки и, если он проверен — вы получаете доступ к данным, для которых вам были предоставлены разрешения.

Библиотека Google OAuth2.0

Для реализации стороннего входа на нашем сайте мы использовали клиентскую библиотеку API Google для Java. В нем также есть Jackson2, ProtoBuf и все другие полезные утилиты, которые появляются в топ-100 библиотек, которые используются в лучших Java-проектах GitHub . Это был довольно простой выбор для нас, так как мы уже использовали эту библиотеку для других целей, и, честно говоря, библиотека Google появилась как первый результат на … Google. Подготовьте свои шляпы из фольги .

Реализация входа с помощью Google

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

Страница разрешений Google - настроенная для Takipi

Страница разрешений Google — настроенная для Takipi

Теперь вернемся к Java. В основе этого, процедура сводится к нескольким простым шагам без сюрпризов. Сначала мы создаем и выполняем запрос для получения GoogleTokenResponse, чтобы мы могли проверить токен, полученный от пользователя. Затем мы используем этот ответ для создания GoogleCredential, который позволяет нам вызывать getAccessToken () и возвращать информацию о пользователе в формате JSON:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
JsonFactory jsonFactory = new JacksonFactory();
HttpTransport httpTransport = new NetHttpTransport();
 
GoogleTokenResponse tokenResponse = new GoogleAuthorizationCodeTokenRequest(
                     httpTransport, jsonFactory,
                     /* Client ID and Secret */,
                     code, "postmessage").execute();
 
GoogleCredential credential = new GoogleCredential.Builder()
                    .setJsonFactory(jsonFactory)
                    .setTransport(httpTransport)
                    .setClientSecrets(/* Client ID and Secret */).build()
                    .setFromTokenResponse(tokenResponse);
 
Oauth2 oauth2 = new Oauth2.Builder(httpTransport, jsonFactory, credential).setApplicationName("YourAppName").build();
Tokeninfo tokenInfo = oauth2.tokeninfo().setAccessToken(credential.getAccessToken()).execute();
 
return oauth2.userinfo().get().execute();

Boom. Вот и все. Лучший совет здесь — просто следовать официальной документации. В конце GitHub реализация становится немного хитрее.

Реализация входа с помощью GitHub

Теперь мы поражены осознанием того, что Google помог нам сократить некоторые углы в отношении OAuth и использовать абстракцию с GoogleTokenResponse и GoogleCredential. С GitHub мы должны быть ближе к сырому протоколу. Подобно Google, мы можем настроить экран разрешений при регистрации нашего приложения на экране приложений разработчика GitHub.

Страница разрешений GitHub — Настроена для Takipi

Когда мы добрались до реального кода, возникли три основные проблемы, которые немного замедлили нас, и мы не смогли найти их в документации . Вот как мы их решили:

1. Создание собственного потока запросов

То, что в случае с Google было всего 5 строк кода, превращается в 19 строк, поэтому мы можем сгенерировать GitHub tokenResponse. Вот как сделать запрос самостоятельно:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
JsonFactory jsonFactory = new JacksonFactory();
HttpTransport httpTransport = new NetHttpTransport();
 
AuthorizationCodeFlow flow = new AuthorizationCodeFlow.Builder(
                 BearerToken.authorizationHeaderAccessMethod(),
                 httpTransport, jsonFactory,
                 new GenericUrl("https://github.com/login/oauth/access_token"),
                 new ClientParametersAuthentication(/* Client ID and Secret */),
                 /* Client ID */
                 "https://github.com/login/oauth/authorize").build();
 
TokenResponse tokenResponse = flow
                 .newTokenRequest(code)
                 .setScopes(Collections.singletonList("user:email"))
                 .setRequestInitializer(new HttpRequestInitializer() {
                   @Override
                   public void initialize(HttpRequest request) throws IOException {
                        request.getHeaders().setAccept("application/json");
                   }
                 }).execute();

2. Ожидаете ответа JSON? По какой-то причине String является значением по умолчанию

Заметили, что метод инициализации ранее, что делает setAccept? Это было немного удивительно. Оказывается, вам нужно явно попросить GitHub отправить вам ответ обратно в формате JSON, иначе вы получите его в строковом формате. Если бы мы знали, что заранее это могло бы сэкономить нам время, глядя на это так:

Но, к счастью, мы нашли скотч и скрепку, чтобы справиться с вещами

Но, к счастью, мы нашли скотч и скрепку, чтобы справиться с вещами

3. Обработка электронных писем пользователей для входа в GitHub.

Теперь у пользователя GitHub может быть несколько адресов электронной почты, и вам придется выбирать, какой из них вы будете использовать в своих целях. По этой причине мы создали метод getBestEmail, который сортирует массив электронной почты (обратите внимание, что он должен расширять ArrayList для работы). После сортировки массива электронной почты мы выбираем лучший вариант, который мы можем найти:

01
02
03
04
05
06
07
08
09
10
11
public class GithubEmails extends ArrayList<GithubEmail> {
  public GithubEmail getBestEmail() {
    if (isEmpty()) {
      return null;
    }
 
    Collections.sort(this, GithubEmail.bestEmailComparator);
 
    return get(0);
  }
}

Так какой же самый лучший вариант? Каждое поле в этом массиве электронной почты, которое мы получаем в ответе от GitHub, имеет адрес электронной почты, проверенное поле и первичное поле. Вот сортировочный компаратор, который мы реализовали для сортировки:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
public static final Comparator<? super GithubEmail> bestEmailComparator =
    new Comparator<GithubEmail>() {
      @Override
      public int compare(GithubEmail o1, GithubEmail o2) {
        if (o1.verified != o2.verified) {
          return (o1.verified ? -1 : 1);
        }
 
        if (o1.primary != o2.primary) {
          return (o1.primary ? -1 : 1);
        }
 
      return o1.email.compareTo(o2.email);
  }
};

Таким образом, в основном вы можете видеть, что мы предпочитаем проверенные и первичные электронные письма.

Вывод

Мы надеемся, что этот пост помог вам разобраться в подходах к OAuth и Java с помощью входа в Google и GitHub. Хотя мы решили реализовать это именно так, существуют другие способы и библиотеки, которые можно использовать для достижения аналогичных результатов. Мы будем рады узнать, какой подход вы выбрали, какие библиотеки вы предпочитаете, и ответим на любые вопросы об этой реализации. Если у вас есть какие-либо комментарии или предложения относительно того, как мы решили это сделать, сообщите мне об этом в разделе комментариев ниже. И если вы столкнулись с проблемами, пожалуйста, поделитесь, где вы застряли, и мы будем рады помочь и поделиться большим количеством кода.