Skip to main content

Creación de un botón "Inicio de sesión con GitHub" con una aplicación de GitHub

Sigue este tutorial para escribir código de Ruby para generar un token de acceso de usuario a través del flujo de aplicación web para GitHub App.

Introducción

En este tutorial se muestra cómo crear un botón "Iniciar sesión con GitHub" para un sitio web. El sitio web usará la GitHub App para generar un token de acceso de usuario a través del flujo de la aplicación web. A continuación, el sitio web usa el token de acceso de usuario para realizar solicitudes de API en nombre del usuario autenticado.

En este tutorial se usa Ruby, pero puedes usar el flujo de aplicaciones web con cualquier lenguaje de programación que se use para el desarrollo web.

Acerca del flujo de aplicaciones web y los tokens de acceso de usuario

La aplicación debe usar un token de acceso de usuario si quieres atribuir las acciones de la aplicación a un usuario. Para obtener más información, vea «Autenticación con una aplicación de GitHub en nombre de un usuario».

Hay dos maneras de generar un token de acceso de usuario para la GitHub App: flujo de aplicación web y flujo de dispositivo. Si la aplicación tiene acceso a una interfaz web, debe usar el flujo de aplicación web. Si la aplicación no tiene acceso a una interfaz web, debe usar el flujo de dispositivo en su lugar. Para obtener más información, vea «Generación de un token de acceso de usuario para una aplicación de GitHub» y «Creación de una CLI con una aplicación de GitHub».

Requisitos previos

En este tutorial se supone que ya has registrado una GitHub App. Para obtener más información sobre el registro de una GitHub App, consulta "Registro de una instancia de GitHub App".

Antes de seguir este tutorial, debes establecer una dirección URL de devolución de llamada para la aplicación. En este tutorial se usa un servidor local Sinatra con la dirección URL predeterminada de http://localhost:4567. Por ejemplo, para trabajar con la dirección URL predeterminada de una aplicación local de Sinatra, la dirección URL de devolución de llamada puede ser http://localhost:4567/github/callback. Una vez que estés listo para implementar la aplicación, puedes cambiar la dirección URL de devolución de llamada para usar la dirección del servidor activo. Para más información sobre cómo actualizar la dirección URL de devolución de llamada de la aplicación, consulta "Modificación del registro de una instancia de GitHub App" y "Acerca de la dirección URL de devolución de llamada de autorización de usuario".

En este tutorial se da por supuesto que tienes conocimientos básicos de Ruby y del sistema de plantillas de Ruby, ERB. Para más información, consulta Ruby y ERB.

Instalar dependencias

En este tutorial se usa la gema de Ruby, Sinatra, para crear una aplicación web con Ruby. Para más información, consulta el archivo LÉAME de Sinatra.

En este tutorial se usa la gema de Ruby, dotenv, para acceder a los valores almacenados en un archivo .env. Para más información, consulta el archivo LÉAME de dotenv.

Para seguir este tutorial, debes instalar las gemas Sinatra y dotenv en el proyecto de Ruby. Por ejemplo, puedes hacerlo con Bundler:

  1. Si aún no tienes instalado Bundler, ejecuta el siguiente comando en el terminal:

    gem install bundler
    
  2. Si aún no tienes un archivo Gemfile para la aplicación, ejecuta el siguiente comando en el terminal:

    bundle init
    
  3. Si aún no tienes un archivo Gemfile.lock para la aplicación, ejecuta el siguiente comando en el terminal:

    bundle install
    
  4. En el terminal, ejecuta los comandos siguientes para instalar las gemas:

    bundle add sinatra
    
    bundle add dotenv
    

Copia el identificador de cliente y el secreto de cliente.

En este tutorial se muestra cómo almacenar el identificador de cliente y el secreto de cliente en variables de entorno y acceder a ellos con ENV.fetch. Al implementar la aplicación, querrás cambiar cómo almacenar el identificador de cliente y el secreto de cliente. Para más información, consulta Almacenamiento seguro del secreto de cliente.

  1. En la esquina superior derecha de cualquier página en GitHub Enterprise Cloud, haga clic en su fotografía de perfil.

  2. Navega a la configuración de tu cuenta.

    • Para una aplicación propiedad de una cuenta personal, haga clic en Configuración.
    • Para una aplicación propiedad de una organización:
      1. Haga clic en Sus organizaciones.
      2. A la derecha de la organización, haga clic en Configuración.
  3. En la barra lateral izquierda, haz clic en Configuración del desarrollador.

  4. En la barra lateral de la izquierda, haga clic en GitHub Apps .

  5. Junto a la GitHub App que quieres modificar, haz clic en Editar.

  6. En la página de configuración de la aplicación, busca el identificador de cliente de la aplicación. Lo agregarás a un archivo .env en un paso posterior. El identificador de cliente es diferente del identificador de la aplicación.

  7. En la página de configuración de la aplicación, haz clic en Generar un nuevo secreto de cliente. Agregarás el secreto de cliente a un archivo .env en un paso posterior.

  8. Crea un archivo llamado .env en el mismo nivel que tu Gemfile.

  9. Si el proyecto aún no tiene un archivo .gitignore, crea .gitignore uno en el mismo nivel que Gemfile.

  10. Agregue .env al archivo .gitignore. Esto te impedirá confirmar por accidente el secreto de cliente. Para más información sobre los archivos .gitignore, consulta "Ignorar archivos".

  11. Agrega el siguiente contenido al archivo .env: Reemplaza YOUR_CLIENT_ID por el identificador de cliente por de la aplicación. Reemplaza YOUR_CLIENT_SECRET por el secreto de cliente de la aplicación.

    CLIENT_ID="YOUR_CLIENT_ID"
    CLIENT_SECRET="YOUR_CLIENT_SECRET"
    

Adición de código para generar un token de acceso de usuario

Para obtener un token de acceso de usuario, primero debes pedir al usuario que autorice la aplicación. Cuando un usuario autoriza la aplicación, se le redirigirá a la dirección URL de devolución de llamada de la aplicación. La solicitud a la dirección URL de devolución de llamada incluye un parámetro de consulta code. Cuando la aplicación obtiene una solicitud para atender esa dirección URL de devolución de llamada, puedes intercambiar el parámetro code de un token de acceso de usuario.

Estos pasos te llevan por la escritura de código para generar un token de acceso de usuario. Para ir directamente al código final, consulta "Ejemplo de código completo".

  1. En el mismo directorio que el archivo .env, crea un archivo de Ruby que contenga el código que generará un token de acceso de usuario. En este tutorial se llamará al archivo app.rb.

  2. En la parte superior de app.rb, agrega estas dependencias:

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

    Las dependencias sinatra y dotenv/load usan las gemas que instalaste anteriormente. net/http y json forman parte de la biblioteca estándar de Ruby.

  3. Agrega el código siguiente a app.rb para obtener el identificador de cliente y el secreto de cliente de la aplicación del archivo .env.

    Ruby
    CLIENT_ID = ENV.fetch("CLIENT_ID")
    CLIENT_SECRET = ENV.fetch("CLIENT_SECRET")
    
  4. Agrega el código siguiente a app.rb para mostrar un vínculo que pedirá a los usuarios que autentiquen la aplicación.

    Ruby
    get "/" do
      link = '<a href="https://github.com/login/oauth/authorize?client_id=<%= CLIENT_ID %>">Login with GitHub</a>'
      erb link
    end
    
  5. Agrega el código siguiente a app.rb para controlar las solicitudes a la dirección URL de devolución de llamada de la aplicación y obtener el parámetro code de la solicitud. Reemplaza CALLBACK_URL por la dirección URL de devolución de llamada de la aplicación, menos el dominio. Por ejemplo, si la dirección URL de devolución de llamada es http://localhost:4567/github/callback, reemplaza CALLBACK_URL por /github/callback.

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

    Actualmente, el código solo representa un mensaje junto con el parámetro code. Los pasos siguientes expandirán este bloque de código.

  6. Opcionalmente, comprueba el progreso:

    app.rb ahora tiene este aspecto, donde CALLBACK_URL es la dirección URL de devolución de llamada de la aplicación, menos el dominio:

    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="https://github.com/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. En el terminal, desde el directorio donde se almacena app.rb, ejecuta ruby app.rb. Debe iniciarse un servidor local Sinatra.

    2. Abra el explorador y vaya a http://localhost:4567. Deberías ver un vínculo con el texto "Iniciar sesión con GitHub".

    3. Haz clic en el vínculo "Iniciar sesión con GitHub".

      Si no has autorizado la aplicación, al hacer clic en el vínculo debes ir a https://github.com/login/oauth/authorize?client_id=CLIENT_ID, donde CLIENT_ID es el identificador de cliente de la aplicación. Se trata de una página de GitHub que solicita a los usuarios que autoricen la aplicación. Si haces clic en el botón para autorizar la aplicación, irás a la dirección URL de devolución de llamada de la aplicación.

      Si anteriormente autorizaste la aplicación y la autorización no se ha revocado, pasarás por alto el mensaje de autorización e irás directamente a la dirección URL de devolución de llamada. Puedes revocar la autorización anterior si quieres ver el mensaje de autorización. Para obtener más información, vea «Revisión y revocación de autorización de aplicaciones de GitHub».

    4. La página de dirección URL de devolución de llamada, a la que se accede haciendo clic en el vínculo "Iniciar sesión con GitHub" y autorizando la aplicación si así se solicita, debe mostrar un texto similar a "Autorización correcta. Se obtuvo el código agc622abb6135be5d1f2".

    5. En el terminal donde se ejecuta Sinatra, usa Ctrl+C para detener el servidor.

  7. Reemplaza el contenido de app.rb por el código siguiente, donde CALLBACK_URL es la dirección URL de devolución de llamada de la aplicación, menos el dominio.

    Este código agrega lógica para intercambiar el parámetro code de un token de acceso de usuario:

    • La función parse_response analiza la respuesta de la API de GitHub.
    • La función exchange_code intercambia el parámetro code de un token de acceso de usuario.
    • El controlador de la solicitud de dirección URL de devolución de llamada ahora llama a exchange_code para intercambiar el parámetro de código de un token de acceso de usuario.
    • La página de devolución de llamada ahora muestra texto para indicar que se generó un token. Si la generación del token no se realizó correctamente, la página indicará ese error.
    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("https://github.com/login/oauth/access_token"),
        URI.encode_www_form(params),
        {"Accept" => "application/json"}
      )
    
      parse_response(result)
    end
    
    get "/" do
      link = '<a href="https://github.com/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, comprueba el progreso:

    1. En el terminal, desde el directorio donde se almacena app.rb, ejecuta ruby app.rb. Debe iniciarse un servidor local Sinatra.
    2. Abra el explorador y vaya a http://localhost:4567. Deberías ver un vínculo con el texto "Iniciar sesión con GitHub".
    3. Haz clic en el vínculo "Iniciar sesión con GitHub".
    4. Si se te pide que lo hagas, autoriza la aplicación.
    5. La página de dirección URL de devolución de llamada, a la que se accede haciendo clic en el vínculo "Iniciar sesión con GitHub" y autorizando la aplicación si así se solicita, debe mostrar un texto similar a "Autorización correcta. Se obtuvo el código 4acd44861aeda86dacce y se intercambió por un token de acceso de usuario que termina en 2zU5kQziE".
    6. En el terminal donde se ejecuta Sinatra, usa Ctrl+C para detener el servidor.
  9. Ahora que tienes un token de acceso de usuario, puedes usarlo para realizar solicitudes de API en nombre del usuario. Por ejemplo:

    Agrega esta función a app.rb para obtener información sobre el usuario con el punto de conexión de la API REST /user:

    Ruby
    def user_info(token)
      uri = URI("https://api.github.com/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
    

    Actualiza el controlador de devolución de llamada para llamar a la función user_info y mostrar el nombre del usuario y el inicio de sesión de GitHub. No olvides reemplazar CALLBACK_URL por la dirección URL de devolución de llamada de la aplicación, menos el dominio.

    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. Comprueba el código en el ejemplo de código completo de la sección siguiente. Puedes probar el código siguiendo los pasos descritos en la sección "Pruebas" debajo del ejemplo de código completo.

Ejemplo de código completo

Este es el ejemplo de código completo que se describió en la sección anterior.

Reemplaza CALLBACK_URL por la dirección URL de devolución de llamada de la aplicación, menos el dominio. Por ejemplo, si la dirección URL de devolución de llamada es http://localhost:4567/github/callback, reemplaza 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("https://github.com/login/oauth/access_token"),
    URI.encode_www_form(params),
    {"Accept" => "application/json"}
  )

  parse_response(result)
end

def user_info(token)
  uri = URI("https://api.github.com/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="https://github.com/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

Prueba

En este tutorial se supone que el código de la aplicación se almacena en un archivo denominado app.rb y que se usa la dirección URL predeterminada para una aplicación de Sinatra local, http://localhost:4567.

  1. En el terminal, desde el directorio donde se almacena app.rb, ejecuta ruby app.rb. Debe iniciarse un servidor local Sinatra.

  2. Abra el explorador y vaya a http://localhost:4567. Deberías ver un vínculo con el texto "Iniciar sesión con GitHub".

  3. Haz clic en el vínculo "Iniciar sesión con GitHub".

    Si no has autorizado la aplicación, al hacer clic en el vínculo debes ir a https://github.com/login/oauth/authorize?client_id=CLIENT_ID, donde CLIENT_ID es el identificador de cliente de la aplicación. Se trata de una página de GitHub que solicita a los usuarios que autoricen la aplicación. Si haces clic en el botón para autorizar la aplicación, irás a la dirección URL de devolución de llamada de la aplicación.

    Si anteriormente autorizaste la aplicación y la autorización no se ha revocado, pasarás por alto el mensaje de autorización e irás directamente a la dirección URL de devolución de llamada. Puedes revocar la autorización anterior si quieres ver el mensaje de autorización. Para obtener más información, vea «Revisión y revocación de autorización de aplicaciones de GitHub».

  4. La página de dirección URL de devolución de llamada, a la que se accede haciendo clic en el vínculo "Iniciar sesión con GitHub" y autorizando la aplicación si así se solicita, debe mostrar un texto similar a "Autorización correcta. Bienvenido, Mona Lisa (octocat)".

  5. En el terminal donde se ejecuta Sinatra, usa Ctrl+C para detener el servidor.

Pasos siguientes

Almacenamiento seguro del secreto de cliente

Nunca debes divulgar el secreto de cliente de la aplicación. En este tutorial se almacenó el secreto de cliente en un archivo gitignored .env y se obtuvo acceso al valor con ENV.fetch. Al implementar la aplicación, debes elegir una manera segura de almacenar el secreto de cliente y actualizar el código para obtener el valor en consecuencia.

Por ejemplo, puedes almacenar el secreto en una variable de entorno en el servidor donde está implementada la aplicación. También puedes usar un servicio de administración de secretos como Azure Key Vault.

Actualización de la dirección URL de devolución de llamada para la implementación

En este tutorial se usa una dirección URL de devolución de llamada que empieza con http://localhost:4567. Sin embargo, http://localhost:4567 solo está disponible localmente en el equipo al iniciar el servidor Sinatra. Antes de implementar la aplicación, debes actualizar la dirección URL de devolución de llamada para usar aquella que se usa en producción. Para más información sobre cómo actualizar la dirección URL de devolución de llamada de la aplicación, consulta "Modificación del registro de una instancia de GitHub App" y "Acerca de la dirección URL de devolución de llamada de autorización de usuario".

Control de varias direcciones URL de devolución de llamada

En este tutorial se usa una única dirección URL de devolución de llamada, pero la aplicación puede tener hasta 10. Si quieres usar varias direcciones URL de devolución de llamada, sigue estos pasos:

  • Agrega las direcciones URL de devolución de llamada adicionales a la aplicación. Para más información sobre las direcciones URL de devolución de llamada, consulta "Modificación del registro de una instancia de GitHub App".
  • Cuando crees un vínculo a https://github.com/login/oauth/authorize, usa el parámetro de consulta redirect_uri para redirigir a los usuarios a la dirección URL de devolución de llamada deseada. Para obtener más información, vea «Generación de un token de acceso de usuario para una aplicación de GitHub».
  • En el código de la aplicación, controla cada dirección URL de devolución de llamada de forma similar al bloque de código que comienza con get "CALLBACK_URL" do.

Especificar parámetros adicionales

Al crear un vínculo a https://github.com/login/oauth/authorize, puedes pasar parámetros de consulta adicionales. Para obtener más información, vea «Generación de un token de acceso de usuario para una aplicación de GitHub».

A diferencia de los tokens de OAuth tradicionales, el token de acceso de usuario no usa ámbitos, por lo que no puedes especificar ámbitos a través del parámetro scope. En su lugar, usa permisos específicos. Un token de acceso de usuario solo tiene los permisos que el usuario y la aplicación tienen.

Ajuste del código para satisfacer las necesidades de la aplicación

En este tutorial se ilustra cómo mostrar información sobre el usuario autenticado, pero puedes ajustar este código para realizar otras acciones. Recuerda actualizar los permisos de la aplicación si esta necesita permisos adicionales para las solicitudes de API que quieres realizar. Para obtener más información, vea «Elección de permisos para una aplicación de GitHub».

En este tutorial se almacenó todo el código en un único archivo, pero es posible que quieras mover funciones y componentes a archivos independientes.

Almacenamiento seguro de tokens

En este tutorial se genera un token de acceso de usuario. A menos que elijas que los tokens de acceso de usuario no expiren, lo harán al cabo de ocho horas. También recibirás un token de actualización que puede regenerar un token de acceso de usuario. Para obtener más información, vea «Actualización de tokens de acceso de usuario».

Si planeas interactuar más con las API de GitHub, debes almacenar el token para su uso futuro. Si decides almacenar el token de acceso de usuario o el token de actualización, debes hacerlo de forma segura. Nunca debes divulgar el token.

Para obtener más información, vea «Procedimientos recomendados para crear una aplicación de GitHub».

Seguimiento de los procedimientos recomendados

Debes intentar seguir los procedimientos recomendados con tu instancia de GitHub App. Para obtener más información, vea «Procedimientos recomendados para crear una aplicación de GitHub».