Skip to main content
Мы публикуем частые обновления нашей документации, и перевод этой страницы может все еще выполняться. Актуальные сведения см. в документации на английском языке.

Создание кнопки "Вход с помощью GitHub" с Приложение GitHub

Выполните инструкции из этого руководства, чтобы написать код Ruby, чтобы создать маркер доступа пользователя через поток веб-приложения для GitHub App.

Введение

В этом руководстве показано, как создать кнопку "Вход с помощью GitHub" для веб-сайта. Веб-сайт будет использовать GitHub App для создания маркера доступа пользователя через поток веб-приложения. Затем веб-сайт использует маркер доступа пользователя для выполнения запросов API от имени пользователя, прошедшего проверку подлинности.

В этом руководстве используется Ruby, но вы можете использовать поток веб-приложения с любым языком программирования, используемым для веб-разработки.

Сведения о потоке веб-приложения и маркерах доступа пользователей

Приложение должно использовать маркер доступа пользователя, если вы хотите приказать действия приложения пользователю. Дополнительные сведения см. в разделе Проверка подлинности с помощью Приложение GitHub от имени пользователя.

Существует два способа создания маркера доступа пользователя для GitHub App: поток веб-приложения и поток устройства. Если приложение имеет доступ к веб-интерфейсу, следует использовать поток веб-приложения. Если приложение не имеет доступа к веб-интерфейсу, следует использовать поток устройства. Дополнительные сведения см. в разделах Создание маркера доступа пользователя для Приложение GitHub и Создание интерфейса командной строки с помощью Приложение GitHub.

Предварительные требования

В этом руководстве предполагается, что вы уже создали GitHub App. Дополнительные сведения о создании приложения см. в разделе Создание приложения GitHub.

Перед выполнением этого руководства необходимо задать URL-адрес обратного вызова для приложения. В этом руководстве используется локальный сервер Sinatra с URL-адресом http://localhost:4567по умолчанию . Например, для работы с URL-адресом по умолчанию для локального приложения Sinatra url-адресом обратного вызова может быть http://localhost:4567/github/callback. Когда вы будете готовы к развертыванию приложения, вы можете изменить URL-адрес обратного вызова, чтобы использовать адрес активного сервера. Дополнительные сведения об обновлении URL-адреса обратного вызова для приложения см. в разделах Изменение приложения GitHub и Сведения о URL-адресе обратного вызова авторизации пользователя.

В этом руководстве предполагается, что у вас есть базовое представление о Ruby и системе шаблонов Ruby ( ERB). Дополнительные сведения см. в разделе Ruby и ERB.

Установка зависимостей

В этом руководстве для создания веб-приложения с помощью Ruby используется драгоценный камень Ruby Sinatra. Дополнительные сведения см. в файле сведений О Sinatra.

В этом руководстве для доступа к значениям, хранящимся в файле, используется драгоценный .env камень Ruby dotenv. Дополнительные сведения см. в файле сведений dotenv.

Чтобы выполнить инструкции из этого руководства, необходимо установить драгоценные камни Sinatra и dotenv в проекте Ruby. Например, это можно сделать с помощью bundler:

  1. Если у вас еще не установлено средство bundler, выполните в терминале следующую команду:

    gem install bundler
    
  2. Если у вас еще нет файла Gemfile для приложения, выполните в терминале следующую команду:

    bundle init
    
  3. Если у вас еще нет gemfile.lock для приложения, выполните в терминале следующую команду:

    bundle install
    
  4. Установите gems, выполнив следующие команды в терминале:

    bundle add sinatra
    
    bundle add dotenv
    

Хранение идентификатора и секрета клиента

В этом руководстве показано, как сохранить идентификатор клиента и секрет клиента в переменных среды и получить к ним доступ с помощью ENV.fetch. При развертывании приложения необходимо изменить способ хранения идентификатора и секрета клиента. Дополнительные сведения см. в разделе Безопасное хранение секрета клиента.

  1. Перейдите к настройкам учетной записи.

    • Для приложения GitHub App, принадлежащего учетной записи пользователя, нажмите на фото своего профиля в правом верхнем углу любой страницы и выберите Настройки. Снимок экрана: раскрывающееся меню "ПрофильGitHub в GitHub.com. Параметр с меткой "Параметры" выделен темно-оранжевым цветом.

    • Для приложения GitHub App, принадлежащего организации, нажмите на фото своего профиля в правом верхнем углу любой страницы и выберите Ваши организации. Затем нажмите Настройки справа от организации.

      Снимок экрана: раскрывающееся меню под @octocatизображением профиля. "Ваши организации" выделены темно-оранжевым цветом.

  2. На левой боковой панели щелкните Параметры разработчика.

  3. На левой боковой панели щелкните GitHub Apps. Снимок экрана: страница "Параметры разработчика" в GitHub. Параметр с меткой "Приложения GitHub" выделен темно-оранжевым цветом.

  4. Рядом с GitHub App, с которым вы хотите работать, нажмите кнопку Изменить.

  5. На странице параметров приложения найдите идентификатор клиента для приложения. Вы добавите его в .env файл на следующем шаге. Обратите внимание, что идентификатор клиента отличается от идентификатора приложения.

  6. На странице параметров приложения щелкните Создать новый секрет клиента. Секрет клиента будет добавлен в .env файл на следующем шаге.

  7. Создайте файл с именем .env на том же уровне, что и .Gemfile

  8. Если в проекте еще .gitignore нет файла, создайте .gitignore файл на том же уровне, что и .Gemfile

  9. Добавьте .env в .gitignore файл. Это предотвратит случайную фиксацию секрета клиента. Дополнительные сведения о .gitignore файлах см. в разделе Пропуск файлов.

  10. Добавьте в файл следующее содержимое .env . Замените YOUR_CLIENT_ID идентификатором клиента приложения. Замените YOUR_CLIENT_SECRET секретом клиента для приложения.

    CLIENT_ID="YOUR_CLIENT_ID"
    CLIENT_SECRET="YOUR_CLIENT_SECRET"
    

Добавление кода для создания маркера доступа пользователя

Чтобы получить маркер доступа пользователя, сначала необходимо предложить пользователю авторизовать приложение. Когда пользователь авторизует приложение, он перенаправляется на URL-адрес обратного вызова приложения. Запрос к URL-адресу обратного вызова включает code параметр запроса. Когда приложение получает запрос на обслуживание этого URL-адреса обратного code вызова, вы можете обменять параметр на маркер доступа пользователя.

Эти действия поведут вас к написанию кода для создания маркера доступа пользователя. Чтобы перейти к окончательному коду, см. раздел Полный пример кода.

  1. В том же каталоге, что и файл .env , создайте файл Ruby для хранения кода, который создаст маркер доступа пользователя. В этом руководстве файлу app.rbбудет присвоено имя .

  2. В верхней части app.rbдобавьте следующие зависимости:

    Ruby
    require "sinatra"
    require "dotenv/load"
    require "net/http"
    require "json"

    Зависимости sinatra и dotenv/load используют ранее установленные драгоценные камни. net/http и json являются частью стандартной библиотеки Ruby.

  3. Добавьте следующий код в app.rb, чтобы получить идентификатор клиента и секрет клиента приложения из файла .env .

    Ruby
    CLIENT_ID = ENV.fetch("CLIENT_ID")
    CLIENT_SECRET = ENV.fetch("CLIENT_SECRET")
  4. Добавьте следующий код в , app.rb чтобы отобразить ссылку, которая предложит пользователям пройти проверку подлинности приложения.

    Ruby
    get "/" do
      link = '<a href="http(s)://HOSTNAME/login/oauth/authorize?client_id=<%= CLIENT_ID %>">Login with GitHub</a>'
      erb link
    end
  5. Добавьте следующий код в для app.rb обработки запросов к URL-адресу обратного code вызова приложения и получения параметра из запроса. Замените CALLBACK_URL URL-адресом обратного вызова для приложения за вычетом домена. Например, если url-адрес обратного вызова — http://localhost:4567/github/callback, замените CALLBACK_URL на /github/callback.

    Ruby
    get "CALLBACK_URL" do
      code = params["code"]
      render = "Successfully authorized! Got code #{code}."
      erb render
    end

    В настоящее время код просто отображает сообщение вместе с параметром code . Следующие шаги раскроют этот блок кода.

  6. При необходимости проверка ход выполнения:

    app.rb теперь выглядит следующим образом, где CALLBACK_URL — ЭТО URL-адрес обратного вызова для приложения за вычетом домена:

    Ruby
    require "sinatra"
    require "dotenv/load"
    require "net/http"
    require "json"
    
    CLIENT_ID = ENV.fetch("CLIENT_ID")
    CLIENT_SECRET = ENV.fetch("CLIENT_SECRET")
    
    get "/" do
      link = '<a href="http(s)://HOSTNAME/login/oauth/authorize?client_id=<%= CLIENT_ID %>">Login with GitHub</a>'
      erb link
    end
    
    get "CALLBACK_URL" do
      code = params["code"]
      render = "Successfully authorized! Got code #{code}."
      erb render
    end
    1. В терминале в каталоге, где app.rb хранится , выполните команду ruby app.rb. Должен запуститься локальный сервер Sinatra.

    2. В браузере перейдите по адресу http://localhost:4567. Вы увидите ссылку с текстом "Вход с помощью GitHub".

    3. Щелкните ссылку "Вход с помощью GitHub".

      Если вы не авторизовать приложение, щелкнув ссылку, вы перейдете к http(s)://HOSTNAME/login/oauth/authorize?client_id=CLIENT_ID, где CLIENT_ID — это идентификатор клиента вашего приложения. Это страница GitHub, на которую пользователям предлагается авторизовать приложение. Если вы нажмете кнопку для авторизации приложения, вы перейдете по URL-адресу обратного вызова приложения.

      Если вы ранее авторизовывали приложение и авторизация не была отозвана, вы пропустите запрос авторизации и перейдете непосредственно к URL-адресу обратного вызова. Вы можете отозвать предыдущую авторизацию, если хотите увидеть запрос на авторизацию. Дополнительные сведения см. в разделе Просмотр и отзыв авторизации приложений GitHub.

    4. На странице URL-адреса обратного вызова, на которую можно перейти, щелкнув ссылку "Войти с помощью GitHub", а затем авторизовать приложение при появлении соответствующего запроса, должен отобразиться текст, похожий на "Успешно авторизовано! Получил код agc622abb6135be5d1f2.

    5. В терминале, где работает Sinatra, остановите сервер, нажав клавиши CTRL+C.

  7. Замените содержимое app.rb следующим кодом, где CALLBACK_URL — ЭТО URL-адрес обратного вызова для вашего приложения за вычетом домена.

    Этот код добавляет логику для обмена параметром code для маркера доступа пользователя:

    • Функция parse_response анализирует ответ из API GitHub.
    • Функция exchange_code обменивает code параметр на маркер доступа пользователя.
    • Обработчик запроса URL-адреса обратного вызова теперь вызывает exchange_code для обмена параметром кода на маркер доступа пользователя.
    • На странице обратного вызова теперь отображается текст, указывающий, что маркер был создан. Если создание маркера не было успешным, на странице будет указано, что сбой.
    Ruby
    require "sinatra"
    require "dotenv/load"
    require "net/http"
    require "json"
    
    CLIENT_ID = ENV.fetch("CLIENT_ID")
    CLIENT_SECRET = ENV.fetch("CLIENT_SECRET")
    
    def parse_response(response)
      case response
      when Net::HTTPOK
        JSON.parse(response.body)
      else
        puts response
        puts response.body
        {}
      end
    end
    
    def exchange_code(code)
      params = {
        "client_id" => CLIENT_ID,
        "client_secret" => CLIENT_SECRET,
        "code" => code
      }
      result = Net::HTTP.post(
        URI("http(s)://HOSTNAME/login/oauth/access_token"),
        URI.encode_www_form(params),
        {"Accept" => "application/json"}
      )
    
      parse_response(result)
    end
    
    get "/" do
      link = '<a href="http(s)://HOSTNAME/login/oauth/authorize?client_id=<%= CLIENT_ID %>">Login with GitHub</a>'
      erb link
    end
    
    get "CALLBACK_URL" do
      code = params["code"]
    
      token_data = exchange_code(code)
    
      if token_data.key?("access_token")
        token = token_data["access_token"]
    
        render = "Successfully authorized! Got code #{code} and exchanged it for a user access token ending in #{token[-9..-1]}."
        erb render
      else
        render = "Authorized, but unable to exchange code #{code} for token."
        erb render
      end
    end
  8. При необходимости проверка ход выполнения:

    1. В терминале в каталоге, где app.rb хранится , выполните команду ruby app.rb. Должен запуститься локальный сервер Sinatra.
    2. В браузере перейдите по адресу http://localhost:4567. Вы увидите ссылку с текстом "Вход с помощью GitHub".
    3. Щелкните ссылку "Вход с помощью GitHub".
    4. Если появится запрос на это, авторизуйте приложение.
    5. На странице URL-адреса обратного вызова, на которую можно перейти, щелкнув ссылку "Войти с помощью GitHub", а затем авторизовать приложение при появлении соответствующего запроса, должен отображаться текст, похожий на "Успешно авторизовано! Получил код 4acd44861aeda86dacce и обменял его на маркер доступа пользователя, заканчивающийся на 2zU5kQziE".
    6. В терминале, где работает Sinatra, остановите сервер, введя клавиши CTRL+C.
  9. Теперь, когда у вас есть маркер доступа пользователя, вы можете использовать его для выполнения запросов API от имени пользователя. Пример:

    Добавьте эту функцию в , app.rb чтобы получить сведения о пользователе с помощью конечной /user точки REST API:

    Ruby
    def user_info(token)
      uri = URI("http(s)://HOSTNAME/api/v3/user")
    
      result = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
        body = {"access_token" => token}.to_json
    
        auth = "Bearer #{token}"
        headers = {"Accept" => "application/json", "Content-Type" => "application/json", "Authorization" => auth}
    
        http.send_request("GET", uri.path, body, headers)
      end
    
      parse_response(result)
    end

    Обновите обработчик обратного вызова, чтобы вызвать функцию user_info и отобразить имя пользователя и имя входа GitHub. Не забудьте заменить CALLBACK_URL URL-адресом обратного вызова для приложения, за исключением домена.

    Ruby
    get "CALLBACK_URL" do
      code = params["code"]
    
      token_data = exchange_code(code)
    
      if token_data.key?("access_token")
        token = token_data["access_token"]
    
        user_info = user_info(token)
        handle = user_info["login"]
        name = user_info["name"]
    
        render = "Successfully authorized! Welcome, #{name} (#{handle})."
        erb render
      else
        render = "Authorized, but unable to exchange code #{code} for token."
        erb render
      end
    end
  10. Проверьте код по полному примеру кода в следующем разделе. Вы можете протестировать код, выполнив действия, описанные в разделе "Тестирование" под полным примером кода.

Полный пример кода

Это полный пример кода, описанный в предыдущем разделе.

Замените CALLBACK_URL URL-адресом обратного вызова для приложения, за исключением домена. Например, если url-адрес обратного вызова — http://localhost:4567/github/callback, замените на CALLBACK_URL /github/callback.

Ruby
require "sinatra"
require "dotenv/load"
require "net/http"
require "json"

CLIENT_ID = ENV.fetch("CLIENT_ID")
CLIENT_SECRET = ENV.fetch("CLIENT_SECRET")

def parse_response(response)
  case response
  when Net::HTTPOK
    JSON.parse(response.body)
  else
    puts response
    puts response.body
    {}
  end
end

def exchange_code(code)
  params = {
    "client_id" => CLIENT_ID,
    "client_secret" => CLIENT_SECRET,
    "code" => code
  }
  result = Net::HTTP.post(
    URI("http(s)://HOSTNAME/login/oauth/access_token"),
    URI.encode_www_form(params),
    {"Accept" => "application/json"}
  )

  parse_response(result)
end

def user_info(token)
  uri = URI("http(s)://HOSTNAME/api/v3/user")

  result = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
    body = {"access_token" => token}.to_json

    auth = "Bearer #{token}"
    headers = {"Accept" => "application/json", "Content-Type" => "application/json", "Authorization" => auth}

    http.send_request("GET", uri.path, body, headers)
  end

  parse_response(result)
end

get "/" do
  link = '<a href="http(s)://HOSTNAME/login/oauth/authorize?client_id=<%= CLIENT_ID %>">Login with GitHub</a>'
  erb link
end

get "CALLBACK_URL" do
  code = params["code"]

  token_data = exchange_code(code)

  if token_data.key?("access_token")
    token = token_data["access_token"]

    user_info = user_info(token)
    handle = user_info["login"]
    name = user_info["name"]

    render = "Successfully authorized! Welcome, #{name} (#{handle})."
    erb render
  else
    render = "Authorized, but unable to exchange code #{code} for token."
    erb render
  end
end

Тестирование

В этом руководстве предполагается, что код приложения хранится в файле с именем app.rb и используется URL-адрес по умолчанию для локального приложения Sinatra. http://localhost:4567

  1. В терминале из каталога, в котором app.rb хранится, выполните команду ruby app.rb. Должен запуститься локальный сервер Sinatra.

  2. В браузере перейдите по адресу http://localhost:4567. Вы увидите ссылку с текстом "Вход с помощью GitHub".

  3. Щелкните ссылку "Вход с помощью GitHub".

    Если вы не авторизовать приложение, щелкните ссылку, чтобы перейти к http(s)://HOSTNAME/login/oauth/authorize?client_id=CLIENT_ID, где CLIENT_ID — это идентификатор клиента вашего приложения. Это страница GitHub, на которую пользователям предлагается авторизовать приложение. Если нажать кнопку для авторизации приложения, вы перейдете по URL-адресу обратного вызова приложения.

    Если вы ранее авторизовали приложение и авторизация не была отозвана, вы пропустите запрос авторизации и перейдете непосредственно по URL-адресу обратного вызова. Вы можете отозвать предыдущую авторизацию, если хотите увидеть запрос авторизации. Дополнительные сведения см. в разделе Просмотр и отзыв авторизации приложений GitHub.

  4. На странице URL-адреса обратного вызова, на которую можно перейти, щелкнув ссылку "Войти с помощью GitHub", а затем авторизовать приложение при появлении соответствующего запроса, должен отображаться текст, похожий на "Успешно авторизовано! Добро пожаловать, Мона Лиза (октокат)."

  5. В терминале, где работает Sinatra, остановите сервер, введя клавиши CTRL+C.

Дальнейшие действия

Безопасное хранение секрета клиента

Никогда не следует обнародовать секрет клиента приложения. В этом руководстве секрет клиента хранится в gitignored .env файле и обращается к значению с помощью ENV.fetch. При развертывании приложения следует выбрать безопасный способ хранения секрета клиента и обновить код, чтобы получить соответствующее значение.

Например, секрет можно сохранить в переменной среды на сервере, где развернуто приложение. Вы также можете использовать службу управления секретами, например Azure Key Vault.

Обновление URL-адреса обратного вызова для развертывания

В этом руководстве использовался URL-адрес обратного вызова, начинающийся с http://localhost:4567. http://localhost:4567 Однако он доступен только локально на компьютере при запуске сервера Sinatra. Перед развертыванием приложения необходимо обновить URL-адрес обратного вызова, чтобы использовать URL-адрес обратного вызова, используемый в рабочей среде. Дополнительные сведения об обновлении URL-адреса обратного вызова для приложения см. в разделах Изменение приложения GitHub и Сведения о URL-адресе обратного вызова авторизации пользователя.

Обработка нескольких URL-адресов обратного вызова

В этом руководстве используется один URL-адрес обратного вызова, но в приложении может быть до 10 URL-адресов обратного вызова. Если вы хотите использовать несколько URL-адресов обратного вызова:

  • Добавьте в приложение дополнительные URL-адреса обратного вызова. Дополнительные сведения о добавлении URL-адресов обратного вызова см. в разделе Изменение приложения GitHub.
  • При связывании redirect_uri с http(s)://HOSTNAME/login/oauth/authorizeиспользуйте параметр запроса, чтобы перенаправлять пользователей на нужный URL-адрес обратного вызова. Дополнительные сведения см. в разделе Создание маркера доступа пользователя для Приложение GitHub.
  • В коде приложения обработайте каждый URL-адрес обратного вызова, как и блок кода, начинающийся с get "CALLBACK_URL" do.

Указание дополнительных параметров

При связывании с http(s)://HOSTNAME/login/oauth/authorizeможно передать дополнительные параметры запроса. Дополнительные сведения см. в разделе Создание маркера доступа пользователя для Приложение GitHub.

В отличие от традиционного маркера OAuth, маркер доступа пользователя не использует области, поэтому вы не можете указать области с помощью scope параметра . Вместо этого он использует детализированные разрешения. Маркер доступа пользователя имеет только те разрешения, которые есть как у пользователя, так и у приложения.

Настройка кода в соответствии с потребностями приложения

В этом руководстве показано, как отобразить сведения о пользователе, прошедшем проверку подлинности, но вы можете настроить этот код для выполнения других действий. Не забудьте обновить разрешения приложения, если приложению требуются дополнительные разрешения для запросов API, которые вы хотите выполнить. Дополнительные сведения см. в разделе Выбор разрешений для Приложение GitHub.

В этом руководстве весь код хранится в одном файле, но может потребоваться переместить функции и компоненты в отдельные файлы.

Безопасное хранение маркеров

В этом руководстве создается маркер доступа пользователя. Если вы не отказались от истечения срока действия маркеров доступа пользователей, срок действия маркера доступа пользователя истечет через восемь часов. Вы также получите маркер обновления, который может повторно создать маркер доступа пользователя. Дополнительные сведения см. в разделе Обновление маркеров доступа пользователей.

Если вы планируете дальше взаимодействовать с API GitHub, следует сохранить маркер для использования в будущем. Если вы решили сохранить маркер доступа пользователя или маркер обновления, необходимо сохранить его в безопасном хранилище. Никогда не следует обнародовать маркер.