Skip to main content
설명서에 자주 업데이트를 게시하며 이 페이지의 번역이 계속 진행 중일 수 있습니다. 최신 정보는 영어 설명서를 참조하세요.

GitHub 앱 사용하여 CLI 빌드

이 자습서에 따라 디바이스 흐름을 통해 GitHub App에 대한 사용자 액세스 토큰을 생성하는 CLI를 Ruby에 작성합니다.

소개

이 자습서에서는 GitHub App에서 지원되는 CLI(명령줄 인터페이스)를 빌드하는 방법과 디바이스 흐름을 사용하여 앱에 대한 사용자 액세스 토큰을 생성하는 방법을 보여 줍니다.

CLI에는 다음 세 가지 명령이 있습니다.

  • help: 사용 지침을 출력합니다.
  • login: 앱이 사용자를 대신하여 API 요청을 만드는 데 사용할 수 있는 사용자 액세스 토큰을 생성합니다.
  • whoami: 로그인한 사용자에 대한 정보를 반환합니다.

이 자습서에서는 Ruby를 사용하지만 CLI를 작성하고 디바이스 흐름을 사용하여 프로그래밍 언어로 사용자 액세스 토큰을 생성할 수 있습니다.

디바이스 흐름 및 사용자 액세스 토큰 정보

CLI는 디바이스 흐름을 사용하여 사용자를 인증하고 사용자 액세스 토큰을 생성합니다. 그런 다음 CLI는 사용자 액세스 토큰을 사용하여 인증된 사용자를 대신하여 API 요청을 수행할 수 있습니다.

앱의 작업을 사용자에게 특성화하려면 앱에서 사용자 액세스 토큰을 사용해야 합니다. 자세한 내용은 "사용자를 대신하여 GitHub 앱 인증"을 참조하세요.

GitHub App에 대한 사용자 액세스 토큰을 생성하는 방법에는 웹 애플리케이션 흐름 및 디바이스 흐름의 두 가지가 있습니다. 앱이 헤드리스이거나 웹 인터페이스에 대한 액세스 권한이 없는 경우 디바이스 흐름을 사용하여 사용자 액세스 토큰을 생성해야 합니다. 예를 들어 CLI 도구, 간단한 Raspberry Pis 및 데스크톱 애플리케이션은 디바이스 흐름을 사용해야 합니다. 앱이 웹 인터페이스에 액세스할 수 있는 경우 웹 애플리케이션 흐름을 대신 사용해야 합니다. 자세한 내용은 "GitHub 앱 대한 사용자 액세스 토큰 생성" 및 "GitHub 앱 사용하여 "GitHub로 로그인" 단추 빌드.

필수 구성 요소

이 자습서에서는 GitHub App을(를) 이미 등록했다고 가정합니다. GitHub App를 등록하는 방법에 대한 자세한 내용은 "GitHub 앱 등록.

이 자습서를 따르기 전에 앱에 디바이스 흐름을 사용하도록 설정해야 합니다. 앱에 디바이스 흐름을 사용하도록 설정하는 방법에 대한 자세한 내용은 "GitHub 앱 등록 수정"을 참조하세요.

이 자습서에서는 Ruby에 대한 기본적인 이해가 있다고 가정합니다. 자세한 내용은 Ruby를 참조하세요.

클라이언트 ID 가져오기

디바이스 흐름을 통해 사용자 액세스 토큰을 생성하려면 앱의 클라이언트 ID가 필요합니다.

  1. 계정 설정으로 이동합니다.
    • 개인 계정이 소유하는 GitHub App의 경우 페이지 오른쪽 위 모서리에서 프로필 사진을 클릭한 다음, 설정을 클릭합니다.
    • 조직이 소유하는 GitHub App의 경우 페이지 오른쪽 위 모서리에서 프로필 사진을 클릭한 다음, 조직을 클릭합니다. 그런 다음, 조직 오른쪽에서 설정을 클릭합니다.
  2. 왼쪽 사이드바에서 개발자 설정을 클릭합니다.
  3. 왼쪽 사이드바에서 GitHub Apps를 클릭합니다. GitHub의 "개발자 설정" 페이지 스크린샷 "GitHub Apps"라는 레이블이 지정된 옵션은 진한 주황색으로 표시됩니다.
  4. 작업할 GitHub App 옆에 있는 편집을 클릭합니다.
  5. 앱의 설정 페이지에서 앱의 클라이언트 ID를 찾습니다. 이 자습서의 뒷부분에서 사용합니다. 클라이언트 ID는 앱 ID와 다릅니다.

CLI 작성

이러한 단계는 CLI를 빌드하고 디바이스 흐름을 사용하여 사용자 액세스 토큰을 가져오는 방법을 안내합니다. 최종 코드로 건너뛰려면 "전체 코드 예제"를 참조하세요.

설치 프로그램

  1. 사용자 액세스 토큰을 생성하는 코드를 저장할 Ruby 파일을 만듭니다. 이 자습서에서는 파일 app_cli.rb이름을 로 지정합니다.

  2. 터미널의 가 저장된 디렉터리 app_cli.rb 에서 다음 명령을 실행하여 실행 파일을 만듭니 app_cli.rb 다.

    Code
    chmod +x app_cli.rb
  3. 이 줄을 맨 위에 app_cli.rb 추가하여 Ruby 인터프리터를 사용하여 스크립트를 실행해야 함을 나타냅니다.

    Ruby
    #!/usr/bin/env ruby
  4. 다음#!/usr/bin/env rubyapp_cli.rb맨 위에 이러한 종속성을 추가합니다.

    Ruby
    require "net/http"
    require "json"
    require "uri"
    require "fileutils"

    모두 Ruby 표준 라이브러리의 일부이므로 보석을 설치할 필요가 없습니다.

  5. 진입점으로 사용할 다음 main 함수를 추가합니다. 함수에는 지정된 명령에 따라 다른 작업을 수행하는 문이 포함 case 됩니다. 나중에 이 case 문을 확장합니다.

    Ruby
    def main
      case ARGV[0]
      when "help"
        puts "`help` is not yet defined"
      when "login"
        puts "`login` is not yet defined"
      when "whoami"
        puts "`whoami` is not yet defined"
      else
        puts "Unknown command `#{ARGV[0]}`"
      end
    end
  6. 파일 맨 아래에 다음 줄을 추가하여 진입점 함수를 호출합니다. 자습서의 뒷부분에서 이 파일에 함수를 더 추가할 때 이 함수 호출은 파일 맨 아래에 남아 있어야 합니다.

    Ruby
    main
  7. 필요에 따라 진행률을 검사.

    app_cli.rb 이제 다음과 같이 표시됩니다.

    Ruby
    #!/usr/bin/env ruby
    
    require "net/http"
    require "json"
    require "uri"
    require "fileutils"
    
    def main
      case ARGV[0]
      when "help"
        puts "`help` is not yet defined"
      when "login"
        puts "`login` is not yet defined"
      when "whoami"
        puts "`whoami` is not yet defined"
      else
        puts "Unknown command `#{ARGV[0]}`"
      end
    end
    
    main

    터미널의 가 저장된 디렉터리 app_cli.rb 에서 를 실행 ./app_cli.rb help합니다. 다음 출력이 표시됩니다.

    `help` is not yet defined
    

    명령 없이 또는 처리되지 않은 명령을 사용하여 스크립트를 테스트할 수도 있습니다. 예를 들어 는 다음을 ./app_cli.rb create-issue 출력해야 합니다.

    Unknown command `create-issue`
    

help 명령 추가

  1. 에 다음 함수를 추가합니다 help app_cli.rb. 현재 함수는 help 사용자에게 이 CLI가 하나의 명령 "help"를 사용함을 알리는 줄을 인쇄합니다. 나중에 이 help 함수를 확장합니다.

    Ruby
    def help
      puts "usage: app_cli <help>"
    end
  2. 명령이 main 제공되면 함수를 help 호출하도록 함수를 help 업데이트합니다.

    Ruby
    def main
      case ARGV[0]
      when "help"
        help
      when "login"
        puts "`login` is not yet defined"
      when "whoami"
        puts "`whoami` is not yet defined"
      else
        puts "Unknown command #{ARGV[0]}"
      end
    end
  3. 필요에 따라 진행률을 검사.

    app_cli.rb 이제 다음과 같이 표시됩니다. 함수 호출이 파일 끝에 있는 한 main 함수의 순서는 중요하지 않습니다.

    Ruby
    #!/usr/bin/env ruby
    
    require "net/http"
    require "json"
    require "uri"
    require "fileutils"
    
    def help
      puts "usage: app_cli <help>"
    end
    
    def main
      case ARGV[0]
      when "help"
        help
      when "login"
        puts "`login` is not yet defined"
      when "whoami"
        puts "`whoami` is not yet defined"
      else
        puts "Unknown command #{ARGV[0]}"
      end
    end
    
    main

    터미널의 가 저장된 디렉터리 app_cli.rb 에서 를 실행 ./app_cli.rb help합니다. 다음 출력이 표시됩니다.

    usage: app_cli <help>
    

login 명령 추가

명령은 login 디바이스 흐름을 실행하여 사용자 액세스 토큰을 가져옵니다. 자세한 내용은 "GitHub 앱 대한 사용자 액세스 토큰 생성"을 참조하세요.

  1. 파일 맨 위에 있는 문 다음에 require GitHub App의 를 에 app_cli.rb상수로 추가 CLIENT_ID 합니다. 앱의 클라이언트 ID를 찾는 방법에 대한 자세한 내용은 "클라이언트 ID 가져오기"를 참조하세요. 을 앱의 클라이언트 ID로 바꿉니다 YOUR_CLIENT_ID .

    Ruby
    CLIENT_ID="YOUR_CLIENT_ID"
  2. 에 다음 함수를 추가합니다 parse_response app_cli.rb. 이 함수는 GitHub REST API의 응답을 구문 분석합니다. 응답 상태 또는 201 Created200 OK 면 함수는 구문 분석된 응답 본문을 반환합니다. 그렇지 않으면 함수는 응답을 인쇄하고 본문은 프로그램을 종료합니다.

    Ruby
    def parse_response(response)
      case response
      when Net::HTTPOK, Net::HTTPCreated
        JSON.parse(response.body)
      else
        puts response
        puts response.body
        exit 1
      end
    end
  3. 에 다음 함수를 추가합니다 request_device_code app_cli.rb. 이 함수는 에 POST http(s)://HOSTNAME/login/device/code 요청을 수행하고 응답을 반환합니다.

    Ruby
    def request_device_code
      uri = URI("http(s)://HOSTNAME/login/device/code")
      parameters = URI.encode_www_form("client_id" => CLIENT_ID)
      headers = {"Accept" => "application/json"}
    
      response = Net::HTTP.post(uri, parameters, headers)
      parse_response(response)
    end
  4. 에 다음 함수를 추가합니다 request_token app_cli.rb. 이 함수는 에 POST http(s)://HOSTNAME/login/oauth/access_token 요청을 수행하고 응답을 반환합니다.

    Ruby
    def request_token(device_code)
      uri = URI("http(s)://HOSTNAME/login/oauth/access_token")
      parameters = URI.encode_www_form({
        "client_id" => CLIENT_ID,
        "device_code" => device_code,
        "grant_type" => "urn:ietf:params:oauth:grant-type:device_code"
      })
      headers = {"Accept" => "application/json"}
      response = Net::HTTP.post(uri, parameters, headers)
      parse_response(response)
    end
  5. 에 다음 함수를 추가합니다 poll_for_token app_cli.rb. 이 함수는 GitHub이 매개 변수 대신 매개 변수로 응답할 때까지 지정된 간격으로 access_token error 폴링 http(s)://HOSTNAME/login/oauth/access_token 합니다. 그런 다음 사용자 액세스 토큰을 파일에 쓰고 파일에 대한 권한을 제한합니다.

    Ruby
    def poll_for_token(device_code, interval)
    
      loop do
        response = request_token(device_code)
        error, access_token = response.values_at("error", "access_token")
    
        if error
          case error
          when "authorization_pending"
            # The user has not yet entered the code.
            # Wait, then poll again.
            sleep interval
            next
          when "slow_down"
            # The app polled too fast.
            # Wait for the interval plus 5 seconds, then poll again.
            sleep interval + 5
            next
          when "expired_token"
            # The `device_code` expired, and the process needs to restart.
            puts "The device code has expired. Please run `login` again."
            exit 1
          when "access_denied"
            # The user cancelled the process. Stop polling.
            puts "Login cancelled by user."
            exit 1
          else
            puts response
            exit 1
          end
        end
    
        File.write("./.token", access_token)
    
        # Set the file permissions so that only the file owner can read or modify the file
        FileUtils.chmod(0600, "./.token")
    
        break
      end
    end
  6. 다음 함수를 추가합니다 login .

    이 함수:

    1. 함수를 request_device_code 호출하고 응답에서 verification_uri, user_code, device_codeinterval 매개 변수를 가져옵니다.
    2. 사용자에게 이전 단계에서 를 입력하라는 user_code 메시지를 표시합니다.
    3. poll_for_token 호출하여 액세스 토큰에 대해 GitHub을 폴링합니다.
    4. 사용자에게 인증이 성공했음을 알 수 있습니다.
    Ruby
    def login
      verification_uri, user_code, device_code, interval = request_device_code.values_at("verification_uri", "user_code", "device_code", "interval")
    
      puts "Please visit: #{verification_uri}"
      puts "and enter code: #{user_code}"
    
      poll_for_token(device_code, interval)
    
      puts "Successfully authenticated!"
    end
  7. 명령이 main 제공되면 함수를 login 호출하도록 함수를 login 업데이트합니다.

    Ruby
    def main
      case ARGV[0]
      when "help"
        help
      when "login"
        login
      when "whoami"
        puts "`whoami` is not yet defined"
      else
        puts "Unknown command #{ARGV[0]}"
      end
    end
  8. help 명령을 포함하도록 함수를 업데이트합니다.login

    Ruby
    def help
      puts "usage: app_cli <login | help>"
    end
  9. 필요에 따라 진행률을 검사.

    app_cli.rb 이제 다음과 같이 표시됩니다. 여기서 YOUR_CLIENT_ID 는 앱의 클라이언트 ID입니다. 함수 호출이 파일 끝에 있는 한 main 함수의 순서는 중요하지 않습니다.

    Ruby
    #!/usr/bin/env ruby
    
    require "net/http"
    require "json"
    require "uri"
    require "fileutils"
    
    CLIENT_ID="YOUR_CLIENT_ID"
    
    def help
      puts "usage: app_cli <login | help>"
    end
    
    def main
      case ARGV[0]
      when "help"
        help
      when "login"
        login
      when "whoami"
        puts "`whoami` is not yet defined"
      else
        puts "Unknown command #{ARGV[0]}"
      end
    end
    
    def parse_response(response)
      case response
      when Net::HTTPOK, Net::HTTPCreated
        JSON.parse(response.body)
      else
        puts response
        puts response.body
        exit 1
      end
    end
    
    def request_device_code
      uri = URI("http(s)://HOSTNAME/login/device/code")
      parameters = URI.encode_www_form("client_id" => CLIENT_ID)
      headers = {"Accept" => "application/json"}
    
      response = Net::HTTP.post(uri, parameters, headers)
      parse_response(response)
    end
    
    def request_token(device_code)
      uri = URI("http(s)://HOSTNAME/login/oauth/access_token")
      parameters = URI.encode_www_form({
        "client_id" => CLIENT_ID,
        "device_code" => device_code,
        "grant_type" => "urn:ietf:params:oauth:grant-type:device_code"
      })
      headers = {"Accept" => "application/json"}
      response = Net::HTTP.post(uri, parameters, headers)
      parse_response(response)
    end
    
    def poll_for_token(device_code, interval)
    
      loop do
        response = request_token(device_code)
        error, access_token = response.values_at("error", "access_token")
    
        if error
          case error
          when "authorization_pending"
            # The user has not yet entered the code.
            # Wait, then poll again.
            sleep interval
            next
          when "slow_down"
            # The app polled too fast.
            # Wait for the interval plus 5 seconds, then poll again.
            sleep interval + 5
            next
          when "expired_token"
            # The `device_code` expired, and the process needs to restart.
            puts "The device code has expired. Please run `login` again."
            exit 1
          when "access_denied"
            # The user cancelled the process. Stop polling.
            puts "Login cancelled by user."
            exit 1
          else
            puts response
            exit 1
          end
        end
    
        File.write("./.token", access_token)
    
        # Set the file permissions so that only the file owner can read or modify the file
        FileUtils.chmod(0600, "./.token")
    
        break
      end
    end
    
    def login
      verification_uri, user_code, device_code, interval = request_device_code.values_at("verification_uri", "user_code", "device_code", "interval")
    
      puts "Please visit: #{verification_uri}"
      puts "and enter code: #{user_code}"
    
      poll_for_token(device_code, interval)
    
      puts "Successfully authenticated!"
    end
    
    main
    1. 터미널의 가 저장된 디렉터리 app_cli.rb 에서 를 실행 ./app_cli.rb login합니다. 다음과 같은 출력이 표시됩니다. 코드는 다음과 같은 경우마다 다릅니다.

      Please visit: http(s)://HOSTNAME/login/device
      and enter code: CA86-8D94
      
    2. 브라우저에서 http(s)://HOSTNAME/login/device로 이동하고 이전 단계의 코드를 입력한 다음 계속을 클릭합니다.

    3. GitHub은(는) 앱에 권한을 부여하라는 메시지를 표시하는 페이지를 표시해야 합니다. "권한 부여" 단추를 클릭합니다.

    4. 이제 터미널에서 "성공적으로 인증되었습니다!"라고 말해야 합니다.

whoami 명령 추가

이제 앱에서 사용자 액세스 토큰을 생성할 수 있으므로 사용자를 대신하여 API 요청을 수행할 수 있습니다. 인증된 whoami 사용자의 사용자 이름을 가져오는 명령을 추가합니다.

  1. 에 다음 whoami 함수를 추가합니다 app_cli.rb. 이 함수는 REST API 엔드포인트를 사용하는 사용자에 /user 대한 정보를 가져옵니다. 사용자 액세스 토큰에 해당하는 사용자 이름을 출력합니다. .token 파일을 찾을 수 없으면 사용자에게 함수를 실행 login 하라는 메시지가 표시됩니다.

    Ruby
    def whoami
      uri = URI("http(s)://HOSTNAME/api/v3/user")
    
      begin
        token = File.read("./.token").strip
      rescue Errno::ENOENT => e
        puts "You are not authorized. Run the `login` command."
        exit 1
      end
    
      response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
        body = {"access_token" => token}.to_json
        headers = {"Accept" => "application/vnd.github+json", "Authorization" => "Bearer #{token}"}
    
        http.send_request("GET", uri.path, body, headers)
      end
    
      parsed_response = parse_response(response)
      puts "You are #{parsed_response["login"]}"
    end
  2. 토큰이 parse_response 만료되었거나 해지된 경우를 처리하도록 함수를 업데이트합니다. 이제 응답을 받으면 401 Unauthorized CLI는 사용자에게 명령을 실행하라는 메시지를 표시합니다 login .

    Ruby
    def parse_response(response)
      case response
      when Net::HTTPOK, Net::HTTPCreated
        JSON.parse(response.body)
      when Net::HTTPUnauthorized
        puts "You are not authorized. Run the `login` command."
        exit 1
      else
        puts response
        puts response.body
        exit 1
      end
    end
  3. 명령이 main 제공되면 함수를 whoami 호출하도록 함수를 whoami 업데이트합니다.

    Ruby
    def main
      case ARGV[0]
      when "help"
        help
      when "login"
        login
      when "whoami"
        whoami
      else
        puts "Unknown command #{ARGV[0]}"
      end
    end
  4. help 명령을 포함하도록 함수를 업데이트합니다.whoami

    Ruby
    def help
      puts "usage: app_cli <login | whoami | help>"
    end
  5. 다음 섹션의 전체 코드 예제에 대해 코드를 확인합니다. 전체 코드 예제 아래의 "테스트" 섹션에 설명된 단계에 따라 코드를 테스트할 수 있습니다.

전체 코드 예제

이전 섹션에서 설명한 전체 코드 예제입니다. 을 앱의 클라이언트 ID로 바꿉니다 YOUR_CLIENT_ID .

Ruby
#!/usr/bin/env ruby

require "net/http"
require "json"
require "uri"
require "fileutils"

CLIENT_ID="YOUR_CLIENT_ID"

def help
  puts "usage: app_cli <login | whoami | help>"
end

def main
  case ARGV[0]
  when "help"
    help
  when "login"
    login
  when "whoami"
    whoami
  else
    puts "Unknown command #{ARGV[0]}"
  end
end

def parse_response(response)
  case response
  when Net::HTTPOK, Net::HTTPCreated
    JSON.parse(response.body)
  when Net::HTTPUnauthorized
    puts "You are not authorized. Run the `login` command."
    exit 1
  else
    puts response
    puts response.body
    exit 1
  end
end

def request_device_code
  uri = URI("http(s)://HOSTNAME/login/device/code")
  parameters = URI.encode_www_form("client_id" => CLIENT_ID)
  headers = {"Accept" => "application/json"}

  response = Net::HTTP.post(uri, parameters, headers)
  parse_response(response)
end

def request_token(device_code)
  uri = URI("http(s)://HOSTNAME/login/oauth/access_token")
  parameters = URI.encode_www_form({
    "client_id" => CLIENT_ID,
    "device_code" => device_code,
    "grant_type" => "urn:ietf:params:oauth:grant-type:device_code"
  })
  headers = {"Accept" => "application/json"}
  response = Net::HTTP.post(uri, parameters, headers)
  parse_response(response)
end

def poll_for_token(device_code, interval)

  loop do
    response = request_token(device_code)
    error, access_token = response.values_at("error", "access_token")

    if error
      case error
      when "authorization_pending"
        # The user has not yet entered the code.
        # Wait, then poll again.
        sleep interval
        next
      when "slow_down"
        # The app polled too fast.
        # Wait for the interval plus 5 seconds, then poll again.
        sleep interval + 5
        next
      when "expired_token"
        # The `device_code` expired, and the process needs to restart.
        puts "The device code has expired. Please run `login` again."
        exit 1
      when "access_denied"
        # The user cancelled the process. Stop polling.
        puts "Login cancelled by user."
        exit 1
      else
        puts response
        exit 1
      end
    end

    File.write("./.token", access_token)

    # Set the file permissions so that only the file owner can read or modify the file
    FileUtils.chmod(0600, "./.token")

    break
  end
end

def login
  verification_uri, user_code, device_code, interval = request_device_code.values_at("verification_uri", "user_code", "device_code", "interval")

  puts "Please visit: #{verification_uri}"
  puts "and enter code: #{user_code}"

  poll_for_token(device_code, interval)

  puts "Successfully authenticated!"
end

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

  begin
    token = File.read("./.token").strip
  rescue Errno::ENOENT => e
    puts "You are not authorized. Run the `login` command."
    exit 1
  end

  response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
    body = {"access_token" => token}.to_json
    headers = {"Accept" => "application/vnd.github+json", "Authorization" => "Bearer #{token}"}

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

  parsed_response = parse_response(response)
  puts "You are #{parsed_response["login"]}"
end

main

테스트

이 자습서에서는 앱 코드가 라는 app_cli.rb파일에 저장되어 있다고 가정합니다.

  1. 터미널의 가 저장된 디렉터리 app_cli.rb 에서 를 실행합니다 ./app_cli.rb help. 다음과 같은 출력이 표시됩니다.

    usage: app_cli <login | whoami | help>
    
  2. 터미널의 가 저장된 디렉터리 app_cli.rb 에서 를 실행합니다 ./app_cli.rb login. 다음과 같은 출력이 표시됩니다. 코드는 다음과 같은 경우마다 다릅니다.

    Please visit: http(s)://HOSTNAME/login/device
    and enter code: CA86-8D94
    
  3. 브라우저에서 http(s)://HOSTNAME/login/device로 이동하고 이전 단계의 코드를 입력한 다음 계속을 클릭합니다.

  4. GitHub은(는) 앱에 권한을 부여하라는 메시지를 표시하는 페이지를 표시해야 합니다. "권한 부여" 단추를 클릭합니다.

  5. 이제 터미널에서 "성공적으로 인증되었습니다!"라고 말해야 합니다.

  6. 터미널의 가 저장된 디렉터리 app_cli.rb 에서 를 실행합니다 ./app_cli.rb whoami. 다음과 같은 출력이 표시되어야 합니다. 여기서 octocat 은 사용자 이름입니다.

    You are octocat
    
  7. 편집기 .token 에서 파일을 열고 토큰을 수정합니다. 이제 토큰이 잘못되었습니다.

  8. 터미널의 가 저장된 디렉터리 app_cli.rb 에서 를 실행합니다 ./app_cli.rb whoami. 다음과 비슷한 출력이 표시됩니다.

    You are not authorized. Run the `login` command.
    
  9. .token 파일을 삭제합니다.

  10. 터미널의 가 저장된 디렉터리 app_cli.rb 에서 를 실행합니다 ./app_cli.rb whoami. 결과는 다음과 같습니다.

    You are not authorized. Run the `login` command.
    

다음 단계

앱의 요구 사항에 맞게 코드 조정

이 자습서에서는 디바이스 흐름을 사용하여 사용자 액세스 토큰을 생성하는 CLI를 작성하는 방법을 설명했습니다. 이 CLI를 확장하여 추가 명령을 수락할 수 있습니다. 예를 들어 문제를 여는 create-issue 명령을 추가할 수 있습니다. 앱에 만들려는 API 요청에 대한 추가 권한이 필요한 경우 앱의 권한을 업데이트해야 합니다. 자세한 내용은 "GitHub 앱 대한 권한 선택"을 참조하세요.

토큰을 안전하게 저장

이 자습서에서는 사용자 액세스 토큰을 생성하고 로컬 파일에 저장합니다. 이 파일을 커밋하거나 토큰을 공개해서는 안 됩니다.

디바이스에 따라 토큰을 저장하는 다른 방법을 선택할 수 있습니다. 디바이스에 토큰을 저장하기 위한 모범 사례를 검사 합니다.

자세한 내용은 "GitHub 앱 만들기 위한 모범 사례"을 참조하세요.

모범 사례 준수

GitHub App을(를) 사용하여 모범 사례를 따르는 것을 목표로 해야 합니다. 자세한 내용은 "GitHub 앱 만들기 위한 모범 사례"을 참조하세요.