138 lines
4.5 KiB
Markdown
138 lines
4.5 KiB
Markdown
# Authenticating in Management API v1
|
|
|
|
## Step 1: Generate keypair.
|
|
|
|
`ruby -e "require 'openssl'; require 'base64'; OpenSSL::PKey::RSA.generate(2048).tap { |p| puts '', 'PRIVATE RSA KEY (URL-safe Base64 encoded, PEM):', '', Base64.urlsafe_encode64(p.to_pem), '', 'PUBLIC RSA KEY (URL-safe Base64 encoded, PEM):', '', Base64.urlsafe_encode64(p.public_key.to_pem) }"`
|
|
|
|
## Step 2: Include public key in the `config/management_api_v1.yml` at Peatio.
|
|
|
|
You should give the ID to the key and put it in variable called `keychain`.
|
|
|
|
The variable `keychain` in `config/management_api_v1.yml` should look like:
|
|
|
|
```yml
|
|
keychain:
|
|
backend-1.mycompany.example:
|
|
algorithm: RS256
|
|
value: 'BACKEND_1_PUBLIC_KEY_IN_PEM_FORMAT_BASE64_URLSAFE_ENCODED'
|
|
backend-2.mycompany.example:
|
|
algorithm: RS256
|
|
value: 'BACKEND_2_PUBLIC_KEY_IN_PEM_FORMAT_BASE64_URLSAFE_ENCODED'
|
|
```
|
|
|
|
The `value` is public key from URL-safe Base64 encoded PEM from the first step.
|
|
The `algorithm` is signature algorithm you prefer.
|
|
|
|
## Step 3: Configure JWT claims.
|
|
|
|
You can customize JWT verification options using variable `jwt` in `config/management_api_v1.yml`:
|
|
|
|
```yml
|
|
jwt:
|
|
verify_jti: true
|
|
verify_aud: true
|
|
exp_leeway: 180
|
|
```
|
|
|
|
The documentation is available at [jwt repository](https://github.com/jwt/ruby-jwt#support-for-reserved-claim-names).
|
|
|
|
## Step 4: Configure security scopes.
|
|
|
|
The `config/management_api_v1.yml` already includes good docs for this step. You can find it at the bottom near variable `scopes`.
|
|
|
|
## Step 5: Configure JWT provider and deliver private key.
|
|
|
|
The JWT provider can use Ruby Gem `jwt-multisig` for generating JWT with multiple signatures.
|
|
|
|
You should store private keys (ID, value, algorithm) somewhere in your application.
|
|
|
|
To generate JWS use the `JWT::Multisig.generate_jwt(payload, private_keychain, algorithms)`.
|
|
|
|
In `private_keychain` you need to put private key from URL-safe Base64 encoded PEM from the first step.
|
|
|
|
The output from this example with serialized JWT will be save in data.json.
|
|
|
|
Example:
|
|
|
|
```ruby
|
|
require 'openssl'
|
|
require 'jwt-multisig'
|
|
require 'base64'
|
|
require 'json'
|
|
|
|
payload = {
|
|
exp: 1922830281, # Put here all the JWT claims.
|
|
data: { foo: 'bar', baz: 'qux' } # Put here all the data your API action expects.
|
|
}
|
|
|
|
# You can choose what signatures the JWT should include.
|
|
private_keychain = {
|
|
:'backend-1.mycompany.example' => OpenSSL::PKey.read(Base64.urlsafe_decode64('BACKEND_1_PRIVATE_KEY_IN_PEM_FORMAT_BASE64_URLSAFE_ENCODED')),
|
|
:'backend-2.mycompany.example' => OpenSSL::PKey.read(Base64.urlsafe_decode64('BACKEND_2_PRIVATE_KEY_IN_PEM_FORMAT_BASE64_URLSAFE_ENCODED'))
|
|
}
|
|
|
|
algorithms = {
|
|
:'backend-1.mycompany.example' => 'RS256',
|
|
:'backend-2.mycompany.example' => 'RS256'
|
|
}
|
|
|
|
jwt = JWT::Multisig.generate_jwt(payload, private_keychain, algorithms)
|
|
|
|
Kernel.puts JSON.dump(jwt) # The output will include serialized JWT.
|
|
|
|
# Save your JWT in data.json
|
|
File.open('./data.json','w') do |f|
|
|
f.write(jwt.to_json)
|
|
end
|
|
```
|
|
|
|
The documentation for this method is available at [rubydoc.info](http://www.rubydoc.info/gems/jwt-multisig/JWT/Multisig#generate_jwt-class_method).
|
|
The source code for `jwt-multisig` is available at [GitHub](https://github.com/rubykube/jwt-multisig).
|
|
The example JWT is available at [jwt-multisig source code](https://github.com/rubykube/jwt-multisig/blob/master/lib/jwt-multisig.rb#L25).
|
|
|
|
## Step 6: Make requests to API.
|
|
|
|
With next example you can make request with ruby Faraday client library or make request with curl. This request will return empty array if you don't have any deposits on the platform.
|
|
|
|
Example:
|
|
|
|
```ruby
|
|
require 'json'
|
|
require 'faraday'
|
|
require 'faraday_middleware'
|
|
|
|
# Read and save your JWT from data.json
|
|
data = File.read('./data.json')
|
|
|
|
# Create HTTP request with ruby Faraday client library
|
|
module Faraday
|
|
class Connection
|
|
alias original_run_request run_request
|
|
def run_request(method, url, body, headers, &block)
|
|
original_run_request(method, url, body, headers, &block).tap do |response|
|
|
response.env.instance_variable_set :@request_body, body if body
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def http_client
|
|
Faraday.new(url: @root_api_url) do |conn|
|
|
conn.request :json
|
|
conn.response :json
|
|
conn.adapter Faraday.default_adapter
|
|
end
|
|
end
|
|
|
|
# The output will include request response
|
|
Kernel.puts http_client
|
|
.public_send(:post,'http://localhost:3000/management_api/v1/deposits', data)
|
|
.body
|
|
```
|
|
|
|
Make request with curl.
|
|
|
|
```
|
|
curl -v -H "Accept: application/json" -H "Content-Type: application/json" -d @jwt.json http://localhost:3000/management_api/v1/deposits
|
|
```
|