Skip to main content

Эта версия GitHub Enterprise Server была прекращена 2024-07-09. Исправления выпускаться не будут даже при критических проблемах безопасности. Для повышения производительности, повышения безопасности и новых функций выполните обновление до последней версии GitHub Enterprise Server. Чтобы получить справку по обновлению, обратитесь в службу поддержки GitHub Enterprise.

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

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

Введение

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

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

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

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

Существует два способа создания маркера доступа пользователя для GitHub App: поток веб-приложения и поток устройств. Если у вашего приложения есть доступ к веб-интерфейсу, следует использовать поток веб-приложения. Если приложение не имеет доступа к веб-интерфейсу, вместо этого следует использовать поток устройств. Дополнительные сведения см. в разделе "[AUTOTITLE" и "Создание маркера доступа пользователя для приложения GitHub](/apps/creating-github-apps/guides/building-a-cli-with-a-github-app)".

Необходимые компоненты

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

Перед выполнением этого руководства необходимо задать URL-адрес обратного вызова для приложения. В этом руководстве используется локальный сервер Sinatra с URL-адресом http://localhost:4567по умолчанию. Например, для работы с URL-адресом по умолчанию для локального приложения Sinatra может быть http://localhost:4567/github/callbackURL-адрес обратного вызова. Когда вы будете готовы к развертыванию приложения, вы можете изменить URL-адрес обратного вызова, чтобы использовать адрес динамического сервера. Дополнительные сведения об обновлении URL-адреса обратного вызова для приложения см. в разделе "[AUTOTITLE" и "Изменение регистрации приложения GitHub](/apps/creating-github-apps/setting-up-a-github-app/about-the-user-authorization-callback-url)".

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

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

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

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

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

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

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

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

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

    bundle add sinatra
    
    bundle add dotenv
    

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

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

  1. В правом верхнем углу любой страницы на GitHubщелкните фото профиля.

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

    • Для приложения, принадлежащих личная учетная запись, нажмите кнопку "Параметры".
    • Для приложения, принадлежащих организации:
      1. Щелкните Your organizations (Ваши организации).
      2. Справа от организации нажмите кнопку "Параметры".
  3. На левой боковой панели щелкните Параметры разработчика.

  4. На левой боковой панели щелкните GitHub Apps.

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

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

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

  8. Создайте файл, который вызывается .env на том же уровне, что и ваш Gemfile.

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

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

  11. Добавьте в файл следующее содержимое .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"
    

    dotenv/load И sinatra зависимости используют установленные ранее драгоценные камни. 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. Замените содержимое следующим кодом, где CALLBACK_URL находится URL-адрес обратного app.rb вызова приложения, минус домен.

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

    • Функция parse_response анализирует ответ из API GitHub.
    • Функция exchange_code обменивается code параметром маркера доступа пользователя.
    • Обработчик запроса обратного вызова теперь вызывает 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-адреса обратного вызова для приложения см. в разделе "[AUTOTITLE" и "Изменение регистрации приложения GitHub](/apps/creating-github-apps/setting-up-a-github-app/about-the-user-authorization-callback-url)".

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

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

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

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

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

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

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

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

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

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

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

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

Дополнительные сведения см. в разделе Рекомендации по созданию приложения GitHub.

Применение рекомендаций

Вам следует следовать рекомендациям по использованию данных GitHub App. Дополнительные сведения см. в разделе Рекомендации по созданию приложения GitHub.