bitballoon 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +9 -0
- data/lib/bitballoon.rb +1 -0
- data/lib/bitballoon/multipass.rb +70 -0
- data/lib/bitballoon/version.rb +1 -1
- data/test/multipass_test.rb +14 -0
- metadata +5 -2
data/README.md
CHANGED
@@ -46,6 +46,15 @@ If you're not authenticating on behalf of a user you can authorize directly with
|
|
46
46
|
bitballoon.authorize_from_credentials!
|
47
47
|
```
|
48
48
|
|
49
|
+
If you already have an OAuth2 `access_token` you can instantiate the client like this:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
bitballoon = BitBalloon::Client.new(:access_token => access_token)
|
53
|
+
```
|
54
|
+
|
55
|
+
And the client will be ready to do requests. This means that once you've gotten a token via `authorize!` or `authorize_from_credentials!` you can store it and reuse it for later sessions.
|
56
|
+
|
57
|
+
|
49
58
|
Command Line Utility
|
50
59
|
====================
|
51
60
|
|
data/lib/bitballoon.rb
CHANGED
@@ -0,0 +1,70 @@
|
|
1
|
+
# Multipass implementation used for single-sign-on for resellers
|
2
|
+
require "openssl"
|
3
|
+
require "base64"
|
4
|
+
require "time"
|
5
|
+
require "json"
|
6
|
+
|
7
|
+
module BitBalloon
|
8
|
+
class Multipass
|
9
|
+
def initialize(multipass_secret)
|
10
|
+
### Use the Multipass secret to derive two cryptographic keys,
|
11
|
+
### one for encryption, one for signing
|
12
|
+
key_material = OpenSSL::Digest::Digest.new("sha256").digest(multipass_secret)
|
13
|
+
@encryption_key = key_material[ 0,16]
|
14
|
+
@signature_key = key_material[16,16]
|
15
|
+
end
|
16
|
+
|
17
|
+
def generate_token(customer_data_hash)
|
18
|
+
### Store the current time in ISO8601 format.
|
19
|
+
### The token will only be valid for a small timeframe around this timestamp.
|
20
|
+
customer_data_hash["created_at"] = Time.now.iso8601
|
21
|
+
|
22
|
+
### Serialize the customer data to JSON and encrypt it
|
23
|
+
ciphertext = encrypt(customer_data_hash.to_json)
|
24
|
+
|
25
|
+
### Create a signature (message authentication code) of the ciphertext
|
26
|
+
### and encode everything using URL-safe Base64 (RFC 4648)
|
27
|
+
sig = sign(ciphertext)
|
28
|
+
|
29
|
+
Base64.urlsafe_encode64(ciphertext + sign(ciphertext))
|
30
|
+
end
|
31
|
+
|
32
|
+
def decode_token(token)
|
33
|
+
decoded_token = Base64.urlsafe_decode64(token)
|
34
|
+
ciphertext, signature = [decoded_token[0..-33], decoded_token[-32..-1]]
|
35
|
+
|
36
|
+
sig = sign(ciphertext)
|
37
|
+
|
38
|
+
raise "Bad signature" unless sign(ciphertext) == signature
|
39
|
+
|
40
|
+
JSON.parse(decrypt(ciphertext))
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
def encrypt(plaintext)
|
45
|
+
cipher = OpenSSL::Cipher::Cipher.new("aes-128-cbc")
|
46
|
+
cipher.encrypt
|
47
|
+
cipher.key = @encryption_key
|
48
|
+
|
49
|
+
### Use a random IV
|
50
|
+
cipher.iv = iv = cipher.random_iv
|
51
|
+
|
52
|
+
### Use IV as first block of ciphertext
|
53
|
+
iv + cipher.update(plaintext) + cipher.final
|
54
|
+
end
|
55
|
+
|
56
|
+
def decrypt(ciphertext)
|
57
|
+
decipher = OpenSSL::Cipher::Cipher.new("aes-128-cbc")
|
58
|
+
decipher.decrypt
|
59
|
+
decipher.key = @encryption_key
|
60
|
+
|
61
|
+
decipher.iv, encrypted = [ciphertext[0..15], ciphertext[16..-1]]
|
62
|
+
|
63
|
+
decipher.update(encrypted) + decipher.final
|
64
|
+
end
|
65
|
+
|
66
|
+
def sign(data)
|
67
|
+
OpenSSL::HMAC.digest("sha256", @signature_key, data)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/bitballoon/version.rb
CHANGED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'digest/sha1'
|
3
|
+
|
4
|
+
class MultipassTest < MiniTest::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@mp = BitBalloon::Multipass.new("secret")
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_generate_and_decode_token
|
10
|
+
data = {"email" => "test@example.com", "uid" => "1234"}
|
11
|
+
token = @mp.generate_token(data)
|
12
|
+
assert_equal data, @mp.decode_token(token), "Data should be the same after generating and decoding"
|
13
|
+
end
|
14
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bitballoon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-10-
|
12
|
+
date: 2013-10-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: oauth2
|
@@ -116,6 +116,7 @@ files:
|
|
116
116
|
- lib/bitballoon/form.rb
|
117
117
|
- lib/bitballoon/forms.rb
|
118
118
|
- lib/bitballoon/model.rb
|
119
|
+
- lib/bitballoon/multipass.rb
|
119
120
|
- lib/bitballoon/site.rb
|
120
121
|
- lib/bitballoon/sites.rb
|
121
122
|
- lib/bitballoon/snippet.rb
|
@@ -126,6 +127,7 @@ files:
|
|
126
127
|
- test/client_test.rb
|
127
128
|
- test/files/site-dir.zip
|
128
129
|
- test/files/site-dir/index.html
|
130
|
+
- test/multipass_test.rb
|
129
131
|
- test/sites_test.rb
|
130
132
|
- test/test_helper.rb
|
131
133
|
homepage: https://www.bitballoon.com
|
@@ -156,6 +158,7 @@ test_files:
|
|
156
158
|
- test/client_test.rb
|
157
159
|
- test/files/site-dir.zip
|
158
160
|
- test/files/site-dir/index.html
|
161
|
+
- test/multipass_test.rb
|
159
162
|
- test/sites_test.rb
|
160
163
|
- test/test_helper.rb
|
161
164
|
has_rdoc:
|