Skip to content

Instantly share code, notes, and snippets.

@stevenh512
Created May 22, 2012 21:23
Show Gist options
  • Save stevenh512/2771702 to your computer and use it in GitHub Desktop.
Save stevenh512/2771702 to your computer and use it in GitHub Desktop.
GitHub Authorizations API for command line apps using Octokit
Gemfile.lock
source 'https://rubygems.org'
# Use Octokit 1.3.0 or higher for great justice (and Authorizations)
gem 'octokit', '>= 1.3.0'
# Use Octokit 1.3.0 or higher for great justice (and Authorizations)
require 'bundler/setup'
require 'octokit'
require 'yaml'
class GitHubAuth
# Change NOTE, SCOPES and CREDENTIALS to match your app's needs.
NOTE = "Octokit example"
SCOPES = ["user", "repo"]
CREDENTIALS = File.join("#{ENV['HOME']}", ".config", "sample_app.yml")
def self.client
new.client
end
def client
@client ||= lambda do
unless File.exist?(CREDENTIALS)
authenticate
end
Octokit::Client.new(YAML.load_file(CREDENTIALS))
end.call
end
private
def authenticate
login = password = token = ""
login = `git config github.user`.chomp
login = ask_login if login.empty?
password = ask_password
auth_client = Octokit::Client.new(:login => login, :password => password)
auth = auth_client.authorizations.detect { |a| a.note == NOTE }
unless auth
auth = auth_client.create_authorization(:scopes => SCOPES, :note => NOTE)
end
File.open(CREDENTIALS, 'w') do |f|
f.puts({ :login => login, :oauth_token => auth.token }.to_yaml)
end
end
def ask_login
p "Enter your GitHub username"
gets.chomp
end
# No-echo password input, stolen from Defunkt's `hub`
# Won't work in Windows
def ask_password
p "Enter your GitHub password (this will NOT be stored)"
tty_state = `stty -g`
system 'stty raw -echo -icanon isig' if $?.success?
pass = ''
while char = $stdin.getbyte and not (char == 13 or char == 10)
if char == 127 or char == 8
pass[-1,1] = '' unless pass.empty?
else
pass << char.chr
end
end
pass
ensure
system "stty #{tty_state}" unless tty_state.empty?
end
end
# Example
client = GitHubAuth.client
client.follows? "stevenh512"
@stevenh512
Copy link
Author

Warning: This is only an example. In real life, you'll probably want to include some kind of error checking. 😁

@stevenh512
Copy link
Author

Updated to use Octokit 1.3.0 from RubyGems, which includes the Authorizations API 😁

@mroth
Copy link

mroth commented Jun 26, 2012

Hey, I'd been using this pattern but noticed it wasn't working properly for me until I made a change.

Line 9 should be SCOPES = ["user","repo"] otherwise the authorization is generated with a malformed scope, which was causing any requests made with the token that needed scope to fail.

@stevenh512
Copy link
Author

Good catch. When I originally wrote this I think a space separated string was acceptable for scopes, but now it seems (according to the GitHub and Octokit docs) that an array is required. I'll update that now.

Thanks :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment