Class: OmniAuth::Globalid::Vault

Inherits:
Object
  • Object
show all
Defined in:
lib/omniauth/globalid/vault.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(openid_token: nil, token_url: nil, client_id: nil, client_secret: nil, redirect_uri: nil, private_key: nil, private_key_pass: nil, acrc_id: nil) ⇒ Vault

Returns a new instance of Vault.



6
7
8
9
10
11
12
13
14
15
16
17
18
19
# File 'lib/omniauth/globalid/vault.rb', line 6

def initialize(openid_token: nil, token_url: nil, client_id: nil, client_secret: nil,
               redirect_uri: nil, private_key: nil, private_key_pass: nil, acrc_id: nil)
  @openid_token = openid_token
  # TODO: Figure out a cleaner way to implement this!
  @token_url = token_url || "https://api.global.id/v1/auth/token"
  @client_id = client_id || ENV["GLOBALID_CLIENT_ID"]
  @client_secret = client_secret || ENV["GLOBALID_CLIENT_SECRET"]
  @redirect_uri = redirect_uri || ENV["GLOBALID_REDIRECT_URL"]
  @acrc_id = acrc_id || ENV["ACRC_ID"]
  # Clean up the private key in case environmental variables were extra escaped
  private_key ||= ENV["GLOBALID_PRIVATE_KEY"].gsub("\\n", "\n").gsub("\"", "")
  private_key_pass ||= ENV["GLOBALID_PRIVATE_KEY_PASS"]
  @private_key = OpenSSL::PKey::RSA.new(private_key, private_key_pass)
end

Instance Attribute Details

#openid_tokenObject

Returns the value of attribute openid_token.



21
22
23
# File 'lib/omniauth/globalid/vault.rb', line 21

def openid_token
  @openid_token
end

#private_keyObject

Returns the value of attribute private_key.



21
22
23
# File 'lib/omniauth/globalid/vault.rb', line 21

def private_key
  @private_key
end

Instance Method Details

#client_credentials_access_tokenObject



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/omniauth/globalid/vault.rb', line 59

def client_credentials_access_token
  # TODO: figure out how to configure these without having to specify via environmental variables
  client_credentials_token_params = {
    client_id: @client_id,
    client_secret: @client_secret,
    redirect_uri: @redirect_uri,
    grant_type: "client_credentials",
    acrc_id: @acrc_id
  }
  client_credentials_response = Faraday.new(url: @token_url).post do |req|
    req.headers["Content-Type"] = "application/json"
    req.body = client_credentials_token_params.to_json
  end
  JSON.parse(client_credentials_response.body)["access_token"] # this is the only part of the client_credentials_response we use
end

#decrypted_piiObject



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/omniauth/globalid/vault.rb', line 23

def decrypted_pii
  vault_response.map do |vault_data|
    # Decrypt the password for the vault data
    decrypted_data_password = private_key.private_decrypt(Base64.decode64(vault_data["encrypted_data_password"]), OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
    # The Initialization Vector is the first 32 bytes of the encrypted data
    iv = vault_data["encrypted_data"][0, 32]
    # The actual encrypted data is everything after the first 32 bytes
    encrypted_data = vault_data["encrypted_data"][32, vault_data["encrypted_data"].length]
    # Create a cipher that can decrypt the data that was encrypted in the vault
    cipher = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
    cipher.decrypt # Tell the cipher instance that we are going to decrypt with it
    # The password and the IV are hex encoded
    cipher.key = Array(decrypted_data_password).pack("H*") # Encode the password in hex (base16)
    cipher.iv = Array(iv).pack("H*") # the initialization vector (iv) is first 32 chars of the encoded_data, hex encoded
    # Decode the base64 encoded data, and decrypt it!
    decrypted_pii = cipher.update(Base64.decode64(encrypted_data)) + cipher.final
    JSON.parse(decrypted_pii)
  end
end

#decrypted_tokensObject



51
52
53
54
55
56
57
# File 'lib/omniauth/globalid/vault.rb', line 51

def decrypted_tokens
  # Get the tokens to make requests to the vault, which is how you access the PII, by decrypting the encrypted_data_tokens
  encrypted_data_tokens.map do |claim_token|
    # The claim_tokens are base64 encoded
    private_key.private_decrypt(Base64.decode64(claim_token), OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
  end
end

#encrypted_data_tokensObject



43
44
45
46
47
48
49
# File 'lib/omniauth/globalid/vault.rb', line 43

def encrypted_data_tokens
  # Parsing this is a paid because the keys are dynamic
  # And we need the inside of the nested structure :(
  @openid_token.select { |k, v| k.match?("/claims/") }
    .reject { |k, v| k.match?("/claims/null") }
    .values.map(&:values).flatten
end

#vault_responseObject



75
76
77
78
79
80
81
82
# File 'lib/omniauth/globalid/vault.rb', line 75

def vault_response
  result = Faraday.new(url: "https://api.global.id/v1/vault/get-encrypted-data").post do |req|
    req.headers["Authorization"] = "Bearer #{client_credentials_access_token}"
    req.headers["Content-Type"] = "application/json"
    req.body = { private_data_tokens: decrypted_tokens }.to_json
  end
  JSON.parse(result.body)
end