Skip to main content

Criando um botão "Logon com o GitHub" com um Aplicativo GitHub

Siga este tutorial para escrever o código Ruby necessário para gerar um token de acesso do usuário por meio do fluxo do aplicativo Web para o GitHub App.

Introdução

Este tutorial demonstra como criar um botão "Logon com o GitHub" para um site. O site usará um GitHub App para gerar um token de acesso do usuário por meio do fluxo do aplicativo Web. Em seguida, o site usa o token de acesso do usuário para fazer solicitações de API em nome do usuário autenticado.

Este tutorial usa o Ruby, mas você pode usar o fluxo de aplicativo Web com qualquer linguagem de programação usada para o desenvolvimento na Web.

Sobre o fluxo de aplicativos Web e tokens de acesso do usuário

Seu aplicativo deve usar um token de acesso do usuário se você quiser atribuir as ações do aplicativo a um usuário. Para obter mais informações, confira "Autenticação com um aplicativo GitHub em nome de um usuário".

Há duas maneiras de gerar um token de acesso do usuário para um GitHub App: fluxo de aplicativo Web e fluxo de dispositivo. Se o aplicativo tiver acesso a uma interface da Web, você deverá usar o fluxo do aplicativo Web. Se o aplicativo não tiver acesso a uma interface da Web, use o fluxo do dispositivo. Para obter mais informações, confira "Como gerar um token de acesso do usuário para um GitHub App" e "Criando uma CLI com um Aplicativo GitHub."

Pré-requisitos

Este tutorial pressupõe que você já tenha registrado o GitHub App. Para obter mais informações sobre como registrar um GitHub App, confira "Registrar um Aplicativo GitHub".

Antes de seguir este tutorial, você precisa definir uma URL de retorno de chamada para o aplicativo. Este tutorial usa um servidor local do Sinatra com a URL padrão http://localhost:4567. Por exemplo, para trabalhar com a URL padrão de um aplicativo local do Sinatra, a URL de retorno de chamada pode ser http://localhost:4567/github/callback. Quando estiver pronto para implantar seu aplicativo, altere a URL de retorno de chamada para usar o endereço do servidor dinâmico. Para obter mais informações sobre como atualizar a URL de retorno de chamada do seu aplicativo, confira "Modificar um registro do Aplicativo GitHub" e "Sobre a URL de retorno de chamada de autorização do usuário".

Este tutorial pressupõe que você tenha uma compreensão básica do Ruby e do sistema de modelos do Ruby, o ERB. Para obter mais informações, confira Ruby e ERB.

Instalar dependências

Este tutorial usa o Ruby gem Sinatra para criar um aplicativo Web com o Ruby. Para obter mais informações, confira o LEIAME do Sinatra.

Este tutorial usa o Ruby Gem dotenv para acessar valores armazenados em um arquivo .env. Para obter mais informações, confira o LEIAME do dotenv.

Para seguir este tutorial, você precisa instalar os gems Sinatra e dotenv no projeto Ruby. Por exemplo, faça isso com o Bundler:

  1. Caso ainda não tenha o Bundler instalado, execute o seguinte comando no terminal:

    gem install bundler
    
  2. Caso ainda não tenha um Gemfile para seu aplicativo, execute o seguinte comando no terminal:

    bundle init
    
  3. Caso ainda não tenha um Gemfile.lock para seu aplicativo, execute o seguinte comando no terminal:

    bundle install
    
  4. No terminal, instale os gems executando os seguintes comandos:

    bundle add sinatra
    
    bundle add dotenv
    

Armazenar a ID do cliente e o segredo do cliente

Este tutorial mostrará como armazenar a ID do cliente e o segredo do cliente em variáveis de ambiente e acessá-los com ENV.fetch. Quando você implantar seu aplicativo, o ideal será alterar a forma como armazena a ID do cliente e o segredo do cliente. Para obter mais informações, confira "Armazenar o segredo do cliente com segurança".

  1. No canto superior direito de qualquer página do GitHub, clique na foto do seu perfil.

  2. Acesse as configurações da sua conta.

    • Para um aplicativo de propriedade de uma conta pessoal, clique em Configurações.
    • Para um aplicativo de propriedade de uma organização:
      1. Clique em Suas organizações.
      2. À direita da organização, clique em Configurações.
  3. Na barra lateral esquerda, clique em Configurações do desenvolvedor.

  4. Na barra lateral esquerda, clique em GitHub Apps .

  5. Ao lado do GitHub App com o qual deseja trabalhar, clique em Editar.

  6. Na página de configurações do aplicativo, encontre a ID do cliente para seu aplicativo. Você a adicionará a um arquivo .env em uma etapa posterior. Observe que a ID do cliente é diferente da ID do aplicativo.

  7. Na página de configurações do aplicativo, clique em Gerar um novo segredo do cliente. Você adicionará o segredo do cliente a um arquivo .env em uma etapa posterior.

  8. Crie um arquivo chamado .env no mesmo nível do Gemfile.

  9. Se o projeto ainda não tiver um arquivo .gitignore, crie um arquivo .gitignore no mesmo nível do Gemfile.

  10. Adicione .env ao arquivo .gitignore. Isso impedirá você de fazer um commit acidental do segredo do cliente. Para obter mais informações sobre os arquivos .gitignore, confira "Ignorar arquivos".

  11. Adicione o conteúdo a seguir ao arquivo .env. Substitua YOUR_CLIENT_ID pela ID do cliente do aplicativo. Substitua YOUR_CLIENT_SECRET pelo segredo do cliente do seu aplicativo.

    CLIENT_ID="YOUR_CLIENT_ID"
    CLIENT_SECRET="YOUR_CLIENT_SECRET"
    

Adicionar o código para gerar um token de acesso do usuário

Para obter um token de acesso do usuário, primeiro, você precisa solicitar que o usuário autorize seu aplicativo. Quando um usuário autoriza seu aplicativo, ele é redirecionado para a URL de retorno de chamada do aplicativo. A solicitação para a URL de retorno de chamada inclui um parâmetro de consulta code. Quando seu aplicativo recebe uma solicitação para atender a essa URL de retorno de chamada, você pode trocar o parâmetro code por um token de acesso do usuário.

Estas etapas orientam você na escrita do código usado para gerar um token de acesso do usuário. Para ir para o código final, confira "Exemplo de código completo".

  1. No mesmo diretório do arquivo .env, crie um arquivo Ruby para manter o código que vai gerar um token de acesso do usuário. Este tutorial dará ao arquivo o nome app.rb.

  2. No início do app.rb, adicione estas dependências:

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

    As dependências sinatra e dotenv/load usam os gems que você instalou anteriormente. net/http e json fazem parte da biblioteca padrão do Ruby.

  3. Adicione o código a seguir a app.rb para obter a ID do cliente do aplicativo e o segredo do cliente do arquivo .env.

    Ruby
    CLIENT_ID = ENV.fetch("CLIENT_ID")
    CLIENT_SECRET = ENV.fetch("CLIENT_SECRET")
    
  4. Adicione o código a seguir a app.rb para exibir um link que solicitará aos usuários que autentiquem seu aplicativo.

    Ruby
    get "/" do
      link = '<a href="http(s)://HOSTNAME/login/oauth/authorize?client_id=<%= CLIENT_ID %>">Login with GitHub</a>'
      erb link
    end
    
  5. Adicione o código a seguir a app.rb para processar as solicitações à URL de retorno de chamada do aplicativo e obter o parâmetro code da solicitação. Substitua CALLBACK_URL pela URL de retorno de chamada do seu aplicativo, menos o domínio. Por exemplo, se a URL de retorno de chamada for http://localhost:4567/github/callback, substitua CALLBACK_URL por /github/callback.

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

    Atualmente, o código só renderiza uma mensagem com o parâmetro code. As etapas a seguir expandirão esse bloco de código.

  6. Opcionalmente, verifique seu progresso:

    app.rb agora tem esta aparência, sendo que CALLBACK_URL é a URL de retorno de chamada do seu aplicativo, menos o domínio:

    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. No terminal, no diretório em que app.rb está armazenado, execute ruby app.rb. Um servidor local do Sinatra deve ser iniciado.

    2. No navegador, navegue até http://localhost:4567. Você verá um link com o texto "Faça logon com o GitHub".

    3. Clique no link "Fazer logon com o GitHub".

      Caso não tenha autorizado o aplicativo, se você clicar no link, será levado para http(s)://HOSTNAME/login/oauth/authorize?client_id=CLIENT_ID, sendo que CLIENT_ID é a ID do cliente do aplicativo. Essa é uma página do GitHub que solicita aos usuários a autorizar seu aplicativo. Se você clicar no botão para autorizar seu aplicativo, acessará a URL de retorno de chamada do aplicativo.

      Se você autorizou seu aplicativo anteriormente e a autorização não foi revogada, o prompt de autorização é ignorado e leva você diretamente para a URL de retorno de chamada. Você poderá revogar sua autorização anterior se quiser ver a solicitação de autorização. Para obter mais informações, confira "Revisar e revogar a autorização dos Aplicativos GitHub".

    4. A página da URL de retorno de chamada, acessada com um clique no link "Fazer logon com o GitHub" e com a autorização do aplicativo, se solicitado, exibirá um texto semelhante a "Autorizado com sucesso! Código agc622abb6135be5d1f2 recebido".

    5. No terminal em que o Sinatra está em execução, interrompa o servidor inserindo CTRL+C.

  7. Substitua o conteúdo de app.rb pelo código a seguir, sendo que CALLBACK_URL é a URL de retorno de chamada do seu aplicativo, menos o domínio.

    Esse código adiciona a lógica para trocar o parâmetro code por um token de acesso do usuário:

    • A função parse_response analisa a resposta da API do GitHub.
    • A função exchange_code troca o parâmetro code por um token de acesso do usuário.
    • O manipulador para a solicitação de URL de retorno de chamada agora chama exchange_code para trocar o parâmetro de código por um token de acesso do usuário.
    • A página de retorno de chamada agora mostra o texto para indicar que um token foi gerado. Se a geração do token não tiver sido bem-sucedida, a página indicará essa falha.
    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. Opcionalmente, verifique seu progresso:

    1. No terminal, no diretório em que app.rb está armazenado, execute ruby app.rb. Um servidor local do Sinatra deve ser iniciado.
    2. No navegador, navegue até http://localhost:4567. Você verá um link com o texto "Faça logon com o GitHub".
    3. Clique no link "Fazer logon com o GitHub".
    4. Se precisar fazer isso, autorize seu aplicativo.
    5. A página da URL de retorno de chamada, acessada com um clique no link "Fazer logon com o GitHub" e com a autorização do aplicativo, se solicitado, exibirá um texto semelhante a "Autorizado com sucesso! Código 4acd44861aeda86dacce recebido e trocado por um token de acesso do usuário que termina em 2zU5kQziE".
    6. No terminal em que o Sinatra está em execução, interrompa o servidor inserindo CTRL+C.
  9. Agora que você tem um token de acesso do usuário, use o token para fazer solicitações de API em nome do usuário. Por exemplo:

    Adicione esta função a app.rb para obter informações sobre o usuário com o ponto de extremidade /user da API REST:

    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
    

    Atualize o manipulador de retorno de chamada para chamar a função user_info e exibir o nome do usuário e o logon do GitHub. Lembre-se de substituir CALLBACK_URL pela URL de retorno de chamada do seu aplicativo, menos o domínio.

    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. Verifique o código em relação ao exemplo de código completo na próxima seção. Teste o código seguindo as etapas descritas na seção "Teste" abaixo do exemplo de código completo.

Exemplo de código completo

Este é o exemplo de código completo descrito na seção anterior.

Substitua CALLBACK_URL pela URL de retorno de chamada do seu aplicativo, menos o domínio. Por exemplo, se a URL de retorno de chamada for http://localhost:4567/github/callback, substitua CALLBACK_URL por /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

Testando

Este tutorial pressupõe que o código do aplicativo esteja armazenado em um arquivo chamado app.rb e que você esteja usando a URL padrão para um aplicativo local do Sinatra, http://localhost:4567.

  1. No terminal, no diretório em que app.rb está armazenado, execute ruby app.rb. Um servidor local do Sinatra deve ser iniciado.

  2. No navegador, navegue até http://localhost:4567. Você verá um link com o texto "Faça logon com o GitHub".

  3. Clique no link "Fazer logon com o GitHub".

    Caso não tenha autorizado o aplicativo, se você clicar no link, será levado para http(s)://HOSTNAME/login/oauth/authorize?client_id=CLIENT_ID, sendo que CLIENT_ID é a ID do cliente do aplicativo. Essa é uma página do GitHub que solicita aos usuários a autorizar seu aplicativo. Se você clicar no botão para autorizar seu aplicativo, acessará a URL de retorno de chamada do aplicativo.

    Se você autorizou seu aplicativo anteriormente e a autorização não foi revogada, o prompt de autorização é ignorado e leva você diretamente para a URL de retorno de chamada. Você poderá revogar sua autorização anterior se quiser ver a solicitação de autorização. Para obter mais informações, confira "Revisar e revogar a autorização dos Aplicativos GitHub".

  4. A página da URL de retorno de chamada, acessada com um clique no link "Fazer logon com o GitHub" e com a autorização do aplicativo, se solicitado, exibirá um texto semelhante a "Autorizado com sucesso! Bem-vinda, Mona Lisa (octocat)".

  5. No terminal em que o Sinatra está em execução, interrompa o servidor inserindo CTRL+C.

Próximas etapas

Armazenar o segredo do cliente com segurança

Você nunca deve divulgar o segredo do cliente do aplicativo. Este tutorial armazenou o segredo do cliente em um arquivo .env ignorado pelo Git e acessou o valor com ENV.fetch. Ao implantar seu aplicativo, você deve escolher uma forma segura de armazenar o segredo do cliente e atualizar o código para obter o valor de acordo.

Por exemplo, você pode armazenar o segredo em uma variável de ambiente no servidor em que o aplicativo foi implantado. Use também um serviço de gerenciamento de segredos como o Azure Key Vault.

Atualizar a URL de retorno de chamada para implantação

Este tutorial usou uma URL de retorno de chamada que começa com http://localhost:4567. No entanto, http://localhost:4567 só estará disponível localmente para o computador quando você iniciar o servidor do Sinatra. Antes de implantar seu aplicativo, você deve atualizar a URL de retorno de chamada para usar a URL de retorno de chamada que você usa em produção. Para obter mais informações sobre como atualizar a URL de retorno de chamada do seu aplicativo, confira "Modificar um registro do Aplicativo GitHub" e "Sobre a URL de retorno de chamada de autorização do usuário".

Processar várias URLs de retorno de chamada

Este tutorial usou uma só URL de retorno de chamada, mas seu aplicativo pode ter até dez URLs de retorno de chamada. Caso você deseje usar várias URLs de retorno de chamada:

  • Adicione as outras URLs de retorno de chamada ao aplicativo. Para obter mais informações sobre como adicionar URLs de retorno de chamada, confira "Modificar um registro do Aplicativo GitHub".
  • Ao vinculá-la ao http(s)://HOSTNAME/login/oauth/authorize, use o parâmetro de consulta redirect_uri para redirecionar os usuários para a URL de retorno de chamada desejada. Para obter mais informações, confira "Como gerar um token de acesso do usuário para um GitHub App".
  • No código do aplicativo, processe cada URL de retorno de chamada, semelhante ao bloco de código que começa com get "CALLBACK_URL" do.

Especificar parâmetros adicionais

Ao vinculá-la ao http(s)://HOSTNAME/login/oauth/authorize, você pode transmitir parâmetros de consulta adicionais. Para obter mais informações, confira "Como gerar um token de acesso do usuário para um GitHub App".

Ao contrário de um token OAuth tradicional, o token de acesso do usuário não usa escopos, ou seja, não é possível especificar escopos por meio do parâmetro scope. Em vez disso, ele usa permissões refinadas. Um token de acesso do usuário só tem permissões que o usuário e o aplicativo têm.

Ajustar o código de acordo com as necessidades do aplicativo

Este tutorial demonstrou como exibir informações sobre o usuário autenticado, mas você pode ajustar esse código para executar outras ações. Lembre-se de atualizar as permissões do aplicativo se o aplicativo precisar de permissões adicionais para as solicitações de API que você deseja fazer. Para obter mais informações, confira "Escolhendo permissões para um Aplicativo GitHub".

Este tutorial armazenou todo o código em um só arquivo, mas o ideal é mover funções e componentes para arquivos separados.

Armazenar tokens com segurança

Este tutorial gera um token de acesso do usuário. A menos que você tenha recusado o vencimento de tokens de acesso do usuário, o token de acesso do usuário vence após oito horas. Você também receberá um token de atualização que pode regenerar um token de acesso do usuário. Para obter mais informações, confira "Atualizar tokens de acesso do usuário".

Se você pretende interagir ainda mais com as APIs do GitHub, armazene o token para uso futuro. Se optar por armazenar o token de acesso do usuário ou atualizar o token, armazene-o com segurança. Você nunca deve divulgar o token.

Para obter mais informações, confira "Práticas recomendadas para criar um aplicativo do GitHub".

Seguir as práticas recomendadas

Você deve ter como objetivo seguir as melhores práticas com seu GitHub App. Para obter mais informações, confira "Práticas recomendadas para criar um aplicativo do GitHub".