osso 0.0.2.8 → 0.0.3.2

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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Gemfile.lock +1 -1
  4. data/db/schema.rb +1 -0
  5. data/lib/osso/graphql/mutation.rb +11 -0
  6. data/lib/osso/graphql/mutations.rb +9 -0
  7. data/lib/osso/graphql/mutations/base_mutation.rb +20 -0
  8. data/lib/osso/graphql/mutations/configure_identity_provider.rb +26 -0
  9. data/lib/osso/graphql/mutations/create_identity_provider.rb +24 -0
  10. data/lib/osso/graphql/mutations/set_saml_provider.rb +23 -0
  11. data/lib/osso/graphql/query.rb +28 -0
  12. data/lib/osso/graphql/resolvers.rb +8 -0
  13. data/lib/osso/graphql/resolvers/enterprise_account.rb +21 -0
  14. data/lib/osso/graphql/resolvers/enterprise_accounts.rb +13 -0
  15. data/lib/osso/graphql/resolvers/oauth_clients.rb +11 -0
  16. data/lib/osso/graphql/schema.rb +38 -0
  17. data/lib/osso/graphql/types.rb +12 -0
  18. data/lib/osso/graphql/types/base_enum.rb +6 -0
  19. data/lib/osso/graphql/types/base_object.rb +8 -0
  20. data/lib/osso/graphql/types/enterprise_account.rb +29 -0
  21. data/lib/osso/graphql/types/identity_provider.rb +36 -0
  22. data/lib/osso/graphql/types/identity_provider_service.rb +8 -0
  23. data/lib/osso/graphql/types/oauth_client.rb +16 -0
  24. data/lib/osso/graphql/types/user.rb +12 -0
  25. data/lib/osso/helpers/auth.rb +51 -49
  26. data/lib/osso/helpers/helpers.rb +3 -1
  27. data/lib/osso/routes/admin.rb +1 -5
  28. data/lib/osso/routes/oauth.rb +2 -1
  29. data/lib/osso/version.rb +1 -1
  30. data/lib/tasks/bootstrap.rake +1 -2
  31. data/spec/routes/admin_spec.rb +1 -0
  32. data/spec/spec_helper.rb +4 -0
  33. metadata +24 -3
  34. data/spec/support/vcr_cassettes/okta_saml_callback.yml +0 -59
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ceef442a19c2833e4209dc505d521efae52f9c16416841929125e6b084075a3c
4
- data.tar.gz: 3be3b7863223c124a41d830c074b92e58c83dc8bee6795152a8f37bf7b6a68b7
3
+ metadata.gz: 5436cc4ffd1836ba000cdea128e83432cc94528d49ab407110fcacf7df05895d
4
+ data.tar.gz: c84623f25ff2893b0d7aeec78d6d9cfc28294c194abfaff2fc7e80862de0a70f
5
5
  SHA512:
6
- metadata.gz: 0ce9317d0d5489baa6d4fb47f0c20f15816d120ea56708959b0fdd4dd580359ddfd46bd929b4028d77d8eef8f4d45b24fb9a95f75fe04100094b814cd6a3b56f
7
- data.tar.gz: ba3ec1f44299d0576a2a3de1fa9e89dc331b063ffadcca5dde2e3bbf9e445d5d826f3e526f07c0870410e3c517ff7cee8af21b2ca39d721fa37a15af7efb4fa2
6
+ metadata.gz: 854fbac14e9d96122b17af1de627bfb21a70a2f055edf7d9bda2179cd246f19e233b34fc468da9ff59b1a62271b7faaa2a5450c853c6c518d9531f62d4218475
7
+ data.tar.gz: e6df4b4874341659bb60704a9bfa1ddadf703b86ff0629c8174ac9bc83ceec019dc07d74e67f5cff71871c7f32dc7ea29a3a1959cb7a07f782ac8cc58fb9f9f5
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /spec/reports/
8
8
  /tmp/
9
9
  *.gem
10
+ .DS_Store
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- osso (0.0.2.8)
4
+ osso (0.0.3.2)
5
5
  activesupport (>= 6.0.3.2)
6
6
  jwt
7
7
  omniauth-multi-provider
@@ -0,0 +1 @@
1
+ # frozen_string_literal: true
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'mutations'
4
+
5
+ module Types
6
+ class MutationType < BaseObject
7
+ field :configure_identity_provider, mutation: Mutations::ConfigureIdentityProvider
8
+ field :create_identity_provider, mutation: Mutations::CreateIdentityProvider
9
+ field :set_saml_provider, mutation: Mutations::SetSamlProvider
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mutations
4
+ end
5
+
6
+ require_relative 'mutations/base_mutation'
7
+ require_relative 'mutations/configure_identity_provider'
8
+ require_relative 'mutations/create_identity_provider'
9
+ require_relative 'mutations/set_saml_provider'
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mutations
4
+ class BaseMutation < GraphQL::Schema::RelayClassicMutation
5
+ # This is used for generating payload types
6
+ object_class Types::BaseObject
7
+ # # This is used for return fields on the mutation's payload
8
+ # field_class Types::BaseField
9
+ # # This is used for generating the `input: { ... }` object type
10
+ # input_object_class Types::BaseInputObject
11
+
12
+ def return_data(data)
13
+ data.merge(errors: [])
14
+ end
15
+
16
+ def return_error(error)
17
+ error.merge(data: nil)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mutations
4
+ class ConfigureIdentityProvider < BaseMutation
5
+ null false
6
+ argument :id, ID, required: true
7
+ # argument :provider, Types::IdentityProviderService, required: true
8
+ argument :sso_url, String, required: true
9
+ argument :sso_cert, String, required: true
10
+
11
+ field :identity_provider, Types::IdentityProvider, null: true
12
+ field :errors, [String], null: false
13
+
14
+ def resolve(id:, sso_url:, sso_cert:)
15
+ provider = Osso::Models::SamlProvider.find(id)
16
+ provider.update(
17
+ idp_cert: sso_cert,
18
+ idp_sso_target_url: sso_url,
19
+ )
20
+
21
+ return_data(identity_provider: provider)
22
+ # rescue StandardError => e
23
+ # return_error(errors: e.full_message)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mutations
4
+ class CreateIdentityProvider < BaseMutation
5
+ null false
6
+ argument :enterprise_account_id, ID, required: true
7
+ argument :provider_service, Types::IdentityProviderService, required: true
8
+
9
+ field :identity_provider, Types::IdentityProvider, null: false
10
+ field :errors, [String], null: false
11
+
12
+ def resolve(enterprise_account_id:, provider_service:)
13
+ enterprise_account = Osso::Models::EnterpriseAccount.find(enterprise_account_id)
14
+ identity_provider = enterprise_account.saml_providers.create!(
15
+ provider: provider_service || 'OKTA',
16
+ domain: enterprise_account.domain,
17
+ )
18
+
19
+ return_data(identity_provider: identity_provider)
20
+ rescue StandardError => e
21
+ return_error(errors: e.full_message)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mutations
4
+ class SetSamlProvider < BaseMutation
5
+ null false
6
+
7
+ argument :provider, Types::IdentityProviderService, required: true
8
+ argument :id, ID, required: true
9
+
10
+ field :identity_provider, Types::IdentityProvider, null: false
11
+ field :errors, [String], null: false
12
+
13
+ def resolve(provider:, id:)
14
+ saml_provider = Osso::Models::SamlProvider.find(id)
15
+ saml_provider.provider = provider
16
+ saml_provider.save!
17
+ {
18
+ saml_provider: saml_provider,
19
+ errors: [],
20
+ }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Types
4
+ class QueryType < GraphQL::Schema::Object
5
+ # field :node, field: GraphQL::Relay::Node.field
6
+ field :enterprise_account, null: false, resolver: Resolvers::EnterpriseAccount do
7
+ argument :domain, String, required: true
8
+ end
9
+ field :enterprise_accounts, null: true, resolver: Resolvers::EnterpriseAccounts
10
+ field :oauth_clients, null: true, resolver: Resolvers::OAuthClients
11
+
12
+ field(
13
+ :identity_provider,
14
+ Types::IdentityProvider,
15
+ null: true,
16
+ resolve: ->(_obj, args, _context) { Osso::Models::SamlProvider.find(args[:id]) },
17
+ ) do
18
+ argument :id, ID, required: true
19
+ end
20
+
21
+ # field(
22
+ # :viewer,
23
+ # Types::User,
24
+ # null: true,
25
+ # resolve: ->(_obj, _args, context) { context[:current_user] },
26
+ # )
27
+ end
28
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resolvers
4
+ end
5
+
6
+ require_relative 'resolvers/enterprise_account'
7
+ require_relative 'resolvers/enterprise_accounts'
8
+ require_relative 'resolvers/oauth_clients'
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resolvers
4
+ class EnterpriseAccount < GraphQL::Schema::Resolver
5
+ type Types::EnterpriseAccount, null: false
6
+
7
+ def resolve(args)
8
+ return unless admin? || enterprise_authorized?(args[:domain])
9
+
10
+ Osso::Models::EnterpriseAccount.find_by(domain: args[:domain])
11
+ end
12
+
13
+ def admin?
14
+ context[:scope] == :admin
15
+ end
16
+
17
+ def enterprise_authorized?(domain)
18
+ context[:scope] == domain
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resolvers
4
+ class EnterpriseAccounts < GraphQL::Schema::Resolver
5
+ type [Types::EnterpriseAccount], null: true
6
+
7
+ def resolve
8
+ return Osso::Models::EnterpriseAccount.all if context[:scope] == :admin
9
+
10
+ Array(Osso::Models::EnterpriseAccount.find_by(domain: context[:scope]))
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resolvers
4
+ class OAuthClients < GraphQL::Schema::Resolver
5
+ type [Types::OAuthClient], null: true
6
+
7
+ def resolve
8
+ return Osso::Models::OAuthClient.all if context[:scope] == :admin
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'graphql'
4
+ require_relative 'types'
5
+ require_relative 'resolvers'
6
+ require_relative 'mutation'
7
+ require_relative 'query'
8
+
9
+ GraphQL::Relay::BaseConnection.register_connection_implementation(
10
+ ActiveRecord::Relation,
11
+ GraphQL::Relay::RelationConnection,
12
+ )
13
+
14
+ class OssoSchema < GraphQL::Schema
15
+ query Types::QueryType
16
+ mutation Types::MutationType
17
+ use GraphQL::Pagination::Connections
18
+
19
+ def self.id_from_object(object, _type_definition = nil, _query_ctx = nil)
20
+ GraphQL::Schema::UniqueWithinType.encode(object.class.name, object.id)
21
+ end
22
+
23
+ def self.object_from_id(id, _query_ctx = nil)
24
+ class_name, item_id = GraphQL::Schema::UniqueWithinType.decode(id)
25
+ Object.const_get(class_name).find(item_id)
26
+ end
27
+
28
+ def self.resolve_type(_type, obj, _ctx)
29
+ case obj
30
+ when Osso::Models::EnterpriseAccount
31
+ Types::EnterpriseAccount
32
+ when Osso::Models::SamlProvider
33
+ Types::IdentityProvider
34
+ else
35
+ raise("Unexpected object: #{obj}")
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Types
4
+ end
5
+
6
+ require_relative 'types/base_object'
7
+ require_relative 'types/base_enum'
8
+ require_relative 'types/identity_provider_service'
9
+ require_relative 'types/identity_provider'
10
+ require_relative 'types/enterprise_account'
11
+ require_relative 'types/oauth_client'
12
+ require_relative 'types/user'
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Types
4
+ class BaseEnum < GraphQL::Schema::Enum
5
+ end
6
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'graphql'
4
+
5
+ module Types
6
+ class BaseObject < GraphQL::Schema::Object
7
+ end
8
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'graphql'
4
+
5
+ module Types
6
+ class EnterpriseAccount < Types::BaseObject
7
+ description 'An Account for a company that wishes to use SAML via Osso'
8
+ implements GraphQL::Types::Relay::Node
9
+
10
+ global_id_field :gid
11
+ field :id, ID, null: false
12
+ field :name, String, null: false
13
+ field :domain, String, null: false
14
+ field :identity_providers, [Types::IdentityProvider], null: true
15
+ field :status, String, null: false
16
+
17
+ def name
18
+ object.domain.gsub('.com', '')
19
+ end
20
+
21
+ def status
22
+ 'active'
23
+ end
24
+
25
+ def identity_providers
26
+ object.saml_providers
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'graphql'
4
+
5
+ module Types
6
+ class IdentityProvider < Types::BaseObject
7
+ description 'Represents a SAML based IDP instance for an EnterpriseAccount'
8
+ implements GraphQL::Types::Relay::Node
9
+
10
+ global_id_field :gid
11
+ field :id, ID, null: false
12
+ field :enterprise_Account_id, ID, null: false
13
+ field :service, Types::IdentityProviderService, null: true
14
+ field :domain, String, null: false
15
+ field :acs_url, String, null: false
16
+ field :sso_url, String, null: true
17
+ field :sso_cert, String, null: true
18
+ field :configured, Boolean, null: false
19
+
20
+ def service
21
+ @object.provider
22
+ end
23
+
24
+ def configured
25
+ @object.idp_sso_target_url && @object.idp_cert
26
+ end
27
+
28
+ def sso_cert
29
+ @object.idp_cert
30
+ end
31
+
32
+ def sso_url
33
+ @object.idp_sso_target_url
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Types
4
+ class IdentityProviderService < BaseEnum
5
+ value('AZURE', 'Microsoft Azure Identity Provider', value: 'Osso::Models::AzureSamlProvider')
6
+ value('OKTA', 'Okta Identity Provider', value: 'Osso::Models::OktaSamlProvider')
7
+ end
8
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'graphql'
4
+
5
+ module Types
6
+ class OAuthClient < Types::BaseObject
7
+ description 'An OAuth client used to consume Osso SAML users'
8
+ implements GraphQL::Types::Relay::Node
9
+
10
+ global_id_field :gid
11
+ field :id, ID, null: false
12
+ field :name, String, null: false
13
+ field :client_id, String, null: false
14
+ field :client_secret, String, null: false
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'graphql'
4
+ require_relative 'base_object'
5
+ module Types
6
+ class User < Types::BaseObject
7
+ description 'A User of the application'
8
+
9
+ field :id, ID, null: false
10
+ field :name, String, null: true
11
+ end
12
+ end
@@ -1,67 +1,69 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Helpers
4
- module Auth
5
- attr_accessor :current_scope
6
-
7
- def enterprise_protected!(domain = nil)
8
- return if admin_authorized?
9
- return if enterprise_authorized?(domain)
3
+ module Osso
4
+ module Helpers
5
+ module Auth
6
+ attr_accessor :current_scope
7
+
8
+ def enterprise_protected!(domain = nil)
9
+ return if admin_authorized?
10
+ return if enterprise_authorized?(domain)
10
11
 
11
- redirect ENV['JWT_URL']
12
- end
12
+ redirect ENV['JWT_URL']
13
+ end
13
14
 
14
- def enterprise_authorized?(domain)
15
- payload, _args = JWT.decode(
16
- token,
17
- ENV['JWT_HMAC_SECRET'],
18
- true,
19
- { algorithm: 'HS256' },
20
- )
15
+ def enterprise_authorized?(domain)
16
+ payload, _args = JWT.decode(
17
+ token,
18
+ ENV['JWT_HMAC_SECRET'],
19
+ true,
20
+ { algorithm: 'HS256' },
21
+ )
21
22
 
22
- @current_scope = payload['scope']
23
+ @current_scope = payload['scope']
23
24
 
24
- true
25
- rescue JWT::DecodeError
26
- false
27
- end
25
+ true
26
+ rescue JWT::DecodeError
27
+ false
28
+ end
28
29
 
29
- def admin_protected!
30
- return if admin_authorized?
30
+ def admin_protected!
31
+ return if admin_authorized?
31
32
 
32
- redirect ENV['JWT_URL']
33
- end
33
+ redirect ENV['JWT_URL']
34
+ end
34
35
 
35
- def admin_authorized?
36
- payload, _args = JWT.decode(
37
- token,
38
- ENV['JWT_HMAC_SECRET'],
39
- true,
40
- { algorithm: 'HS256' },
41
- )
36
+ def admin_authorized?
37
+ payload, _args = JWT.decode(
38
+ token,
39
+ ENV['JWT_HMAC_SECRET'],
40
+ true,
41
+ { algorithm: 'HS256' },
42
+ )
42
43
 
43
- if payload['scope'] == 'admin'
44
- @current_scope = :admin
45
- return true
46
- end
44
+ if payload['scope'] == 'admin'
45
+ @current_scope = :admin
46
+ return true
47
+ end
47
48
 
48
- false
49
- rescue JWT::DecodeError
50
- false
51
- end
49
+ false
50
+ rescue JWT::DecodeError
51
+ false
52
+ end
52
53
 
53
- def token
54
- request.env['admin_token'] || session['admin_token'] || request['admin_token']
55
- end
54
+ def token
55
+ request.env['admin_token'] || session['admin_token'] || request['admin_token']
56
+ end
56
57
 
57
- def chomp_token
58
- return unless request['admin_token'].present?
58
+ def chomp_token
59
+ return unless request['admin_token'].present?
59
60
 
60
- session['admin_token'] = request['admin_token']
61
+ session['admin_token'] = request['admin_token']
61
62
 
62
- return if request.post?
63
+ return if request.post?
63
64
 
64
- redirect request.path
65
+ redirect request.path
66
+ end
65
67
  end
66
68
  end
67
- end
69
+ end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Helpers
3
+ module Osso
4
+ module Helpers
5
+ end
4
6
  end
5
7
 
6
8
  require_relative 'auth'
@@ -14,7 +14,7 @@ module Osso
14
14
  get '/' do
15
15
  admin_protected!
16
16
 
17
- erb :'public/index'
17
+ erb :admin
18
18
  end
19
19
 
20
20
  get '/enterprise' do
@@ -26,10 +26,6 @@ module Osso
26
26
  get '/enterprise/:domain' do
27
27
  enterprise_protected!(params[:domain])
28
28
 
29
- @enterprise = Models::EnterpriseAccount.where(
30
- domain: params[:domain],
31
- ).first_or_create
32
-
33
29
  erb :admin
34
30
  end
35
31
 
@@ -24,7 +24,8 @@ module Osso
24
24
  redirect "/auth/saml/#{@enterprise.provider.id}"
25
25
  end
26
26
 
27
- erb :multiple_providers
27
+ # TODO: multiple provider support
28
+ # erb :multiple_providers
28
29
 
29
30
  rescue Rack::OAuth2::Server::Authorize::BadRequest => e
30
31
  @error = e
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Osso
4
- VERSION = '0.0.2.8'
4
+ VERSION = '0.0.3.2'
5
5
  end
@@ -3,11 +3,10 @@
3
3
  require 'sinatra/activerecord'
4
4
  require 'sinatra/activerecord/rake'
5
5
  require 'osso'
6
- require 'dotenv/tasks'
7
6
 
8
7
  namespace :osso do
9
8
  desc 'Bootstrap Osso data for a deployment'
10
- task bootstrap: :dotenv do
9
+ task :bootstrap do
11
10
  %w[Production Staging Development].each do |environement|
12
11
  Osso::Models::OauthClient.create!(
13
12
  name: environement,
@@ -9,6 +9,7 @@ describe Osso::Admin do
9
9
  before do
10
10
  ENV['JWT_URL'] = jwt_url
11
11
  ENV['JWT_HMAC_SECRET'] = jwt_hmac_secret
12
+ described_class.set(:views, spec_views)
12
13
  end
13
14
 
14
15
  describe 'get /admin' do
@@ -40,6 +40,10 @@ module RSpecMixin
40
40
  def last_json_response
41
41
  JSON.parse(last_response.body, symbolize_names: true)
42
42
  end
43
+
44
+ def spec_views
45
+ File.dirname(__FILE__) + '/support/views'
46
+ end
43
47
  end
44
48
 
45
49
  RSpec.configure do |config|
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: osso
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2.8
4
+ version: 0.0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Bauch
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-03 00:00:00.000000000 Z
11
+ date: 2020-07-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -218,6 +218,7 @@ files:
218
218
  - bin/console
219
219
  - bin/setup
220
220
  - config/database.yml
221
+ - db/schema.rb
221
222
  - lib/.DS_Store
222
223
  - lib/osso.rb
223
224
  - lib/osso/Rakefile
@@ -237,6 +238,27 @@ files:
237
238
  - lib/osso/db/migrate/20200502135008_add_oauth_client_id_to_enterprise_account.rb
238
239
  - lib/osso/db/migrate/20200601131227_drop_null_constraint_from_saml_providers_provider.rb
239
240
  - lib/osso/db/schema.rb
241
+ - lib/osso/graphql/.DS_Store
242
+ - lib/osso/graphql/mutation.rb
243
+ - lib/osso/graphql/mutations.rb
244
+ - lib/osso/graphql/mutations/base_mutation.rb
245
+ - lib/osso/graphql/mutations/configure_identity_provider.rb
246
+ - lib/osso/graphql/mutations/create_identity_provider.rb
247
+ - lib/osso/graphql/mutations/set_saml_provider.rb
248
+ - lib/osso/graphql/query.rb
249
+ - lib/osso/graphql/resolvers.rb
250
+ - lib/osso/graphql/resolvers/enterprise_account.rb
251
+ - lib/osso/graphql/resolvers/enterprise_accounts.rb
252
+ - lib/osso/graphql/resolvers/oauth_clients.rb
253
+ - lib/osso/graphql/schema.rb
254
+ - lib/osso/graphql/types.rb
255
+ - lib/osso/graphql/types/base_enum.rb
256
+ - lib/osso/graphql/types/base_object.rb
257
+ - lib/osso/graphql/types/enterprise_account.rb
258
+ - lib/osso/graphql/types/identity_provider.rb
259
+ - lib/osso/graphql/types/identity_provider_service.rb
260
+ - lib/osso/graphql/types/oauth_client.rb
261
+ - lib/osso/graphql/types/user.rb
240
262
  - lib/osso/helpers/auth.rb
241
263
  - lib/osso/helpers/helpers.rb
242
264
  - lib/osso/lib/app_config.rb
@@ -275,7 +297,6 @@ files:
275
297
  - spec/routes/auth_spec.rb
276
298
  - spec/routes/oauth_spec.rb
277
299
  - spec/spec_helper.rb
278
- - spec/support/vcr_cassettes/okta_saml_callback.yml
279
300
  homepage: https://github.com/enterprise-oss/osso-rb
280
301
  licenses:
281
302
  - MIT
@@ -1,59 +0,0 @@
1
- ---
2
- http_interactions:
3
- - request:
4
- method: post
5
- uri: http://localhost:9292/auth/saml/:uuid/callback
6
- body:
7
- encoding: ASCII-8BIT
8
- string: SAMLResponse=PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDJwOlJlc3BvbnNlIERlc3RpbmF0aW9uPSJodHRwOi8vbG9jYWxob3N0OjkyOTIvYXV0aC9zYW1sLzY4ZTkwNTdjLTQ2MmYtNDM3Zi04NDRkLTk4NzI0ZmVmOWQ0My9jYWxsYmFjayIgSUQ9ImlkMTgyOTI5NzEwODgzMjU2OTIyMDE3Nzc0NDUyIiBJblJlc3BvbnNlVG89Il81NGM0ZjE5MS0xYmY3LTRiMDItOTZlYS0zNGQ4NTU1YWVjYWEiIElzc3VlSW5zdGFudD0iMjAyMC0wNC0xMVQxNjozMjoxOC40MjRaIiBWZXJzaW9uPSIyLjAiIHhtbG5zOnNhbWwycD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIiB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiPjxzYW1sMjpJc3N1ZXIgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6bmFtZWlkLWZvcm1hdDplbnRpdHkiIHhtbG5zOnNhbWwyPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIj5odHRwOi8vd3d3Lm9rdGEuY29tL2V4azUxMzI2YjNVMTk0MUhmNHg2PC9zYW1sMjpJc3N1ZXI%2BPGRzOlNpZ25hdHVyZSB4bWxuczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI%2BPGRzOlNpZ25lZEluZm8%2BPGRzOkNhbm9uaWNhbGl6YXRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48ZHM6U2lnbmF0dXJlTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxkc2lnLW1vcmUjcnNhLXNoYTI1NiIvPjxkczpSZWZlcmVuY2UgVVJJPSIjaWQxODI5Mjk3MTA4ODMyNTY5MjIwMTc3NzQ0NTIiPjxkczpUcmFuc2Zvcm1zPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjZW52ZWxvcGVkLXNpZ25hdHVyZSIvPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiPjxlYzpJbmNsdXNpdmVOYW1lc3BhY2VzIFByZWZpeExpc3Q9InhzIiB4bWxuczplYz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8%2BPC9kczpUcmFuc2Zvcm0%2BPC9kczpUcmFuc2Zvcm1zPjxkczpEaWdlc3RNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyNzaGEyNTYiLz48ZHM6RGlnZXN0VmFsdWU%2BZEpWb0Z6Y01zTjV3TmNJRWtJWkxqb1JjWDRpMzVYekI3RGg4ZE0wU1pMZz08L2RzOkRpZ2VzdFZhbHVlPjwvZHM6UmVmZXJlbmNlPjwvZHM6U2lnbmVkSW5mbz48ZHM6U2lnbmF0dXJlVmFsdWU%2BdnFES0RhVk8vYlRkRW5hNlMwNHdQV0hicXdNQ1JHdStjRVRxOE9FR2pzK1drTUVBQVYzeEFnNitUZTB2Z0haSjlTWnhwSW9iWEdadVQvVFFnbnAyczNMM1FvaUx5UVFwOExXQnl0b1A0UWhSV1dNY1N3UHlUYWI5TmRUT1RWeXJBckJxZHFFVXN0M0Z5cVpLSVFlbUpocWU4ckk4cmJwQTI2YUFqc2xNZkRIZHNMTFlFMjUwTXpPdG9wdVppNHpvdDZDSTl1NFVRK2dsOWdqSUJyai9sZ3BQME5mZ3RXM01QNVRQOGxsaEpmVXJ4MjhLWGZjSHpOa1RDU1BxVTRwLzZCRTV5dm5QcmJVTE1EWWZQWG5aV0t5d0JpRkNyaTgydmNOdElXVHUvcmkrejNRT0p6dFRiTkdKU0ZjWHdkWHpheG8xdS9SN3ZUQlJPOCtuZEFsL1VBPT08L2RzOlNpZ25hdHVyZVZhbHVlPjxkczpLZXlJbmZvPjxkczpYNTA5RGF0YT48ZHM6WDUwOUNlcnRpZmljYXRlPk1JSURwRENDQW95Z0F3SUJBZ0lHQVhFaUQ0TGxNQTBHQ1NxR1NJYjNEUUVCQ3dVQU1JR1NNUXN3Q1FZRFZRUUdFd0pWVXpFVE1CRUcKQTFVRUNBd0tRMkZzYVdadmNtNXBZVEVXTUJRR0ExVUVCd3dOVTJGdUlFWnlZVzVqYVhOamJ6RU5NQXNHQTFVRUNnd0VUMnQwWVRFVQpNQklHQTFVRUN3d0xVMU5QVUhKdmRtbGtaWEl4RXpBUkJnTlZCQU1NQ21SbGRpMHhOakl3TWpReEhEQWFCZ2txaGtpRzl3MEJDUUVXCkRXbHVabTlBYjJ0MFlTNWpiMjB3SGhjTk1qQXdNekk0TVRZMU1UVTBXaGNOTXpBd016STRNVFkxTWpVMFdqQ0JrakVMTUFrR0ExVUUKQmhNQ1ZWTXhFekFSQmdOVkJBZ01Da05oYkdsbWIzSnVhV0V4RmpBVUJnTlZCQWNNRFZOaGJpQkdjbUZ1WTJselkyOHhEVEFMQmdOVgpCQW9NQkU5cmRHRXhGREFTQmdOVkJBc01DMU5UVDFCeWIzWnBaR1Z5TVJNd0VRWURWUVFEREFwa1pYWXRNVFl5TURJME1Sd3dHZ1lKCktvWklodmNOQVFrQkZnMXBibVp2UUc5cmRHRXVZMjl0TUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUEKd3NuUDRVVGZ2M2J4UjVKaDBhdDUxRHFqaitmS3hGem56RlczWEE1TmJGMlNsUkxqZVljdmozKzQ3VEMwZVA2eE9zTFdmbnZkbng0dgpkZDlVZm43akRDbzVwTDNKeWtNVkVoMkkwc3pGM1JMQythNTMyQXJjd2dVOVB4NDgrcldWd1BrQVNTN2w0TkhBTTQrZ09CSEpNUXQyCkFNb2hQVDBrVTQxUDhCRVB6ZndoTnlpRVhSNjZKTlpJSlVFOGZNM1ZwZ254bS9WU3dZekpmME5mT3lmeHY4SmN6RjB6a0RicEU3VGsKM1d3L1BGRkxvTXhXemFuV0dKUStibG5odjZVVjZINGZjZkFiY3dBcGxPZElWSGpTMmdoWUJ2WU5HYWh1RnhqaWEwKzZjc3laR3J0OApINFhtUjVEcitqWFk1SzFiMVZPQTBrMTkvRkNuSEhOL3NtbjI1d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQmdEOU5FCjRPQ3VSMSt2dWNWOFMxVDZYWElMMmhCN2JYQkFaRVZIWjFhRXJSemt0Z1hBTWdWd0cyNjd2SWtENVZPWEJpVHk5eU5VNUxLNkczazIKemV3VTE5MHNMMWRNZnlQbm9WWnluOTRudndlOUErb24wdG1aZG1rMDB4aXJLazNGSmRhY25aTkU5RGwvYWZJcmNOZjZ4QW0wV3NVOQprYk1pUnd3dmpPNFRBaXlnRFF6YnJSQzhaZm1UM2hwQmEzYVRVekFjY3J2RVFjZ2FyTGs0cjdValhQN2EybUNOM1VJSWgrc25OMk1zCnZYSEwwcjZmTTN4Ym5peis1bGxlV3RQRnc3M3l5U0JjOHpua1daNFRuOExoMHI2bzVuQ1JZYnIyUkVVQjdaSWZpSXlCYlp4SXA0a3YKYStoYWJiblFERmlOVnpFZDhPUFhIaDRFcUx4T1BEUlc8L2RzOlg1MDlDZXJ0aWZpY2F0ZT48L2RzOlg1MDlEYXRhPjwvZHM6S2V5SW5mbz48L2RzOlNpZ25hdHVyZT48c2FtbDJwOlN0YXR1cyB4bWxuczpzYW1sMnA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCI%2BPHNhbWwycDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6c3RhdHVzOlN1Y2Nlc3MiLz48L3NhbWwycDpTdGF0dXM%2BPHNhbWwyOkFzc2VydGlvbiBJRD0iaWQxODI5Mjk3MTA4ODQyMDg3MzY4MzU5Njg1MiIgSXNzdWVJbnN0YW50PSIyMDIwLTA0LTExVDE2OjMyOjE4LjQyNFoiIFZlcnNpb249IjIuMCIgeG1sbnM6c2FtbDI9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iIHhtbG5zOnhzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSI%2BPHNhbWwyOklzc3VlciBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpuYW1laWQtZm9ybWF0OmVudGl0eSIgeG1sbnM6c2FtbDI9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iPmh0dHA6Ly93d3cub2t0YS5jb20vZXhrNTEzMjZiM1UxOTQxSGY0eDY8L3NhbWwyOklzc3Vlcj48ZHM6U2lnbmF0dXJlIHhtbG5zOmRzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjIj48ZHM6U2lnbmVkSW5mbz48ZHM6Q2Fub25pY2FsaXphdGlvbk1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjxkczpTaWduYXR1cmVNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNyc2Etc2hhMjU2Ii8%2BPGRzOlJlZmVyZW5jZSBVUkk9IiNpZDE4MjkyOTcxMDg4NDIwODczNjgzNTk2ODUyIj48ZHM6VHJhbnNmb3Jtcz48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI2VudmVsb3BlZC1zaWduYXR1cmUiLz48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIj48ZWM6SW5jbHVzaXZlTmFtZXNwYWNlcyBQcmVmaXhMaXN0PSJ4cyIgeG1sbnM6ZWM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjwvZHM6VHJhbnNmb3JtPjwvZHM6VHJhbnNmb3Jtcz48ZHM6RGlnZXN0TWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjc2hhMjU2Ii8%2BPGRzOkRpZ2VzdFZhbHVlPjJ0ekZZTktpNTRBVTV0L3R1UUZJS0Q2aHdlWlRqc1FYSTFzWmFreUE3Y0k9PC9kczpEaWdlc3RWYWx1ZT48L2RzOlJlZmVyZW5jZT48L2RzOlNpZ25lZEluZm8%2BPGRzOlNpZ25hdHVyZVZhbHVlPkxJakdOK0RRRExldUE4clF4Q0Yvblp2c3ZCM0VLWjFaUHA3cUU4ZXZZVGY3R01lWGlVa3hXaTkvbGQ1d2p2YWFjaG5ZOXBMV0FObStFRGo4aUhGcnI1a1dINWJZZUI3b0JybVY1NDlTMmpJWW5pbmJBT055T2d3TVRpWXJUQkZ3czg1dHVYb2h0N3JBcVRrWVBjY2FnanJyQW5sYnNyK3BVb3FZYzZMOHZUczR3d2x0MzJiVXF0TThCOG5XS1NmWFBMTEo3VlVGeFhFQm1iV1JsbjJBcjgyN2dhT1dGemoyQXcxWGw2bUZFTllscDVib3hoSlVkRHJDMHNkaW01YXZmQU5jSXFrMjJFQkc5aFRZNUdnbzlrTjBSYkgvYm15MTc5K0lDaWo5R2hlZ2xmWGVpV3pVaWlLUkF1WS8zbEVLZnBYQ2lpaVRVbGdUcHFxdzhnNjNvZz09PC9kczpTaWduYXR1cmVWYWx1ZT48ZHM6S2V5SW5mbz48ZHM6WDUwOURhdGE%2BPGRzOlg1MDlDZXJ0aWZpY2F0ZT5NSUlEcERDQ0FveWdBd0lCQWdJR0FYRWlENExsTUEwR0NTcUdTSWIzRFFFQkN3VUFNSUdTTVFzd0NRWURWUVFHRXdKVlV6RVRNQkVHCkExVUVDQXdLUTJGc2FXWnZjbTVwWVRFV01CUUdBMVVFQnd3TlUyRnVJRVp5WVc1amFYTmpiekVOTUFzR0ExVUVDZ3dFVDJ0MFlURVUKTUJJR0ExVUVDd3dMVTFOUFVISnZkbWxrWlhJeEV6QVJCZ05WQkFNTUNtUmxkaTB4TmpJd01qUXhIREFhQmdrcWhraUc5dzBCQ1FFVwpEV2x1Wm05QWIydDBZUzVqYjIwd0hoY05NakF3TXpJNE1UWTFNVFUwV2hjTk16QXdNekk0TVRZMU1qVTBXakNCa2pFTE1Ba0dBMVVFCkJoTUNWVk14RXpBUkJnTlZCQWdNQ2tOaGJHbG1iM0p1YVdFeEZqQVVCZ05WQkFjTURWTmhiaUJHY21GdVkybHpZMjh4RFRBTEJnTlYKQkFvTUJFOXJkR0V4RkRBU0JnTlZCQXNNQzFOVFQxQnliM1pwWkdWeU1STXdFUVlEVlFRRERBcGtaWFl0TVRZeU1ESTBNUnd3R2dZSgpLb1pJaHZjTkFRa0JGZzFwYm1adlFHOXJkR0V1WTI5dE1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBCndzblA0VVRmdjNieFI1SmgwYXQ1MURxamorZkt4RnpuekZXM1hBNU5iRjJTbFJMamVZY3ZqMys0N1RDMGVQNnhPc0xXZm52ZG54NHYKZGQ5VWZuN2pEQ281cEwzSnlrTVZFaDJJMHN6RjNSTEMrYTUzMkFyY3dnVTlQeDQ4K3JXVndQa0FTUzdsNE5IQU00K2dPQkhKTVF0MgpBTW9oUFQwa1U0MVA4QkVQemZ3aE55aUVYUjY2Sk5aSUpVRThmTTNWcGdueG0vVlN3WXpKZjBOZk95Znh2OEpjekYwemtEYnBFN1RrCjNXdy9QRkZMb014V3phbldHSlErYmxuaHY2VVY2SDRmY2ZBYmN3QXBsT2RJVkhqUzJnaFlCdllOR2FodUZ4amlhMCs2Y3N5WkdydDgKSDRYbVI1RHIralhZNUsxYjFWT0EwazE5L0ZDbkhITi9zbW4yNXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUJnRDlORQo0T0N1UjErdnVjVjhTMVQ2WFhJTDJoQjdiWEJBWkVWSFoxYUVyUnprdGdYQU1nVndHMjY3dklrRDVWT1hCaVR5OXlOVTVMSzZHM2syCnpld1UxOTBzTDFkTWZ5UG5vVlp5bjk0bnZ3ZTlBK29uMHRtWmRtazAweGlyS2szRkpkYWNuWk5FOURsL2FmSXJjTmY2eEFtMFdzVTkKa2JNaVJ3d3ZqTzRUQWl5Z0RRemJyUkM4WmZtVDNocEJhM2FUVXpBY2NydkVRY2dhckxrNHI3VWpYUDdhMm1DTjNVSUloK3NuTjJNcwp2WEhMMHI2Zk0zeGJuaXorNWxsZVd0UEZ3NzN5eVNCYzh6bmtXWjRUbjhMaDByNm81bkNSWWJyMlJFVUI3WklmaUl5QmJaeElwNGt2CmEraGFiYm5RREZpTlZ6RWQ4T1BYSGg0RXFMeE9QRFJXPC9kczpYNTA5Q2VydGlmaWNhdGU%2BPC9kczpYNTA5RGF0YT48L2RzOktleUluZm8%2BPC9kczpTaWduYXR1cmU%2BPHNhbWwyOlN1YmplY3QgeG1sbnM6c2FtbDI9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iPjxzYW1sMjpOYW1lSUQgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoxLjE6bmFtZWlkLWZvcm1hdDp1bnNwZWNpZmllZCI%2Bc2FtQHZjYXJkbWUuY29tPC9zYW1sMjpOYW1lSUQ%2BPHNhbWwyOlN1YmplY3RDb25maXJtYXRpb24gTWV0aG9kPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6Y206YmVhcmVyIj48c2FtbDI6U3ViamVjdENvbmZpcm1hdGlvbkRhdGEgSW5SZXNwb25zZVRvPSJfNTRjNGYxOTEtMWJmNy00YjAyLTk2ZWEtMzRkODU1NWFlY2FhIiBOb3RPbk9yQWZ0ZXI9IjIwMjAtMDQtMTFUMTY6Mzc6MTguNDI0WiIgUmVjaXBpZW50PSJodHRwOi8vbG9jYWxob3N0OjkyOTIvYXV0aC9zYW1sLzY4ZTkwNTdjLTQ2MmYtNDM3Zi04NDRkLTk4NzI0ZmVmOWQ0My9jYWxsYmFjayIvPjwvc2FtbDI6U3ViamVjdENvbmZpcm1hdGlvbj48L3NhbWwyOlN1YmplY3Q%2BPHNhbWwyOkNvbmRpdGlvbnMgTm90QmVmb3JlPSIyMDIwLTA0LTExVDE2OjI3OjE4LjQyNFoiIE5vdE9uT3JBZnRlcj0iMjAyMC0wNC0xMVQxNjozNzoxOC40MjRaIiB4bWxuczpzYW1sMj0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiI%2BPHNhbWwyOkF1ZGllbmNlUmVzdHJpY3Rpb24%2BPHNhbWwyOkF1ZGllbmNlPjY4ZTkwNTdjLTQ2MmYtNDM3Zi04NDRkLTk4NzI0ZmVmOWQ0Mzwvc2FtbDI6QXVkaWVuY2U%2BPC9zYW1sMjpBdWRpZW5jZVJlc3RyaWN0aW9uPjwvc2FtbDI6Q29uZGl0aW9ucz48c2FtbDI6QXV0aG5TdGF0ZW1lbnQgQXV0aG5JbnN0YW50PSIyMDIwLTA0LTExVDE2OjMyOjE4LjQyNFoiIFNlc3Npb25JbmRleD0iXzU0YzRmMTkxLTFiZjctNGIwMi05NmVhLTM0ZDg1NTVhZWNhYSIgeG1sbnM6c2FtbDI9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iPjxzYW1sMjpBdXRobkNvbnRleHQ%2BPHNhbWwyOkF1dGhuQ29udGV4dENsYXNzUmVmPnVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphYzpjbGFzc2VzOlBhc3N3b3JkUHJvdGVjdGVkVHJhbnNwb3J0PC9zYW1sMjpBdXRobkNvbnRleHRDbGFzc1JlZj48L3NhbWwyOkF1dGhuQ29udGV4dD48L3NhbWwyOkF1dGhuU3RhdGVtZW50PjxzYW1sMjpBdHRyaWJ1dGVTdGF0ZW1lbnQgeG1sbnM6c2FtbDI9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iPjxzYW1sMjpBdHRyaWJ1dGUgTmFtZT0iZW1haWwiIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6dW5zcGVjaWZpZWQiPjxzYW1sMjpBdHRyaWJ1dGVWYWx1ZSB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhzaTp0eXBlPSJ4czpzdHJpbmciPnNhbUB2Y2FyZG1lLmNvbTwvc2FtbDI6QXR0cmlidXRlVmFsdWU%2BPC9zYW1sMjpBdHRyaWJ1dGU%2BPHNhbWwyOkF0dHJpYnV0ZSBOYW1lPSJpZCIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDp1bnNwZWNpZmllZCI%2BPHNhbWwyOkF0dHJpYnV0ZVZhbHVlIHhtbG5zOnhzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeHNpOnR5cGU9InhzOnN0cmluZyI%2BMDB1NTEwd2pwNDRmdDNEUm80eDY8L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjwvc2FtbDI6QXR0cmlidXRlU3RhdGVtZW50Pjwvc2FtbDI6QXNzZXJ0aW9uPjwvc2FtbDJwOlJlc3BvbnNlPg%3D%3D&RelayState=
9
- headers:
10
- Host:
11
- - localhost:9292
12
- Connection:
13
- - keep-alive
14
- Cache-Control:
15
- - max-age=0
16
- Upgrade-Insecure-Requests:
17
- - '1'
18
- Origin:
19
- - 'null'
20
- User-Agent:
21
- - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML,
22
- like Gecko) Chrome/80.0.3987.163 Safari/537.36
23
- Sec-Fetch-Dest:
24
- - document
25
- Accept:
26
- - text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
27
- Sec-Fetch-Site:
28
- - cross-site
29
- Sec-Fetch-Mode:
30
- - navigate
31
- Accept-Encoding:
32
- - gzip, deflate, br
33
- Accept-Language:
34
- - en-US,en;q=0.9,fr;q=0.8
35
- Cookie:
36
- - _vcardme-api_session=YmdCdkxYdTlLWkhhWWNnZTQ5Yjdxc0gweWJjKys4TUtSWWVBd3c1U2tUT2E1b2t0MFQxd3lZQTJwSVcyZVFCOHZxaHRtTVZjVGYyay9ReVc0WElxR0hlVGM0MW5qQUxVZE8zYytTaXBlcDZraWRLSllkYjlvYUNMVkx6S3Aremh4ODB5eVBzMmFwS3dHOHNZaFFBYnJnPT0tLVRKUEdSMFV1SGRCZSt1LzNiYjRSZnc9PQ%3D%3D--4e212108b448172e97b0e205f75976780e843bd7;
37
- mp_321622acf650be9cac3978565e73be1a_mixpanel=%7B%22distinct_id%22%3A%20%2217122c6e1421dd-0fd311181d4582-396f7f07-384000-17122c6e14935d%22%2C%22%24device_id%22%3A%20%2217122c6e1421dd-0fd311181d4582-396f7f07-384000-17122c6e14935d%22%2C%22%24initial_referrer%22%3A%20%22%24direct%22%2C%22%24initial_referring_domain%22%3A%20%22%24direct%22%7D;
38
- rack.session=BAh7CUkiD3Nlc3Npb25faWQGOgZFVEkiRTdkYWNhMWRhNjc3MTY4OTY0ZWVj%0AZjg2YmIyOTM1M2EzOTcxZWIzN2ZjMzAxZGUxNmIyZGNiNDdhMGU0ZDdiMmQG%0AOwBGSSINc2FtbF91aWQGOwBUSSIUc2FtQHZjYXJkbWUuY29tBjsAVEkiF3Nh%0AbWxfc2Vzc2lvbl9pbmRleAY7AFRJIipfOTBjYjc4NjItYTc5My00M2ZjLWFh%0AOWItZDdiMjY0ZWE4NmM2BjsAVEkiFG9tbmlhdXRoLnBhcmFtcwY7AFR7AA%3D%3D%0A--429d063c69188264011d1384cbf24a4b486d2d3a
39
- Version:
40
- - HTTP/1.1
41
- Content-Type:
42
- - application/x-www-form-urlencoded
43
- Content-Length:
44
- - '10749'
45
- response:
46
- status:
47
- code: 200
48
- message: null
49
- headers:
50
- Content-Type:
51
- - application/json
52
- Content-Length:
53
- - '112'
54
- body:
55
- encoding: UTF-8
56
- string: '{"user":{"id":"2077ee4f-9e7d-46c2-bbf3-98c49c312281","email":"sam@vcardme.com","idp_id":"00u510wjp44ft3DRo4x6"}}'
57
- http_version: null
58
- recorded_at: Sat, 11 Apr 2020 16:32:18 GMT
59
- recorded_with: VCR 5.1.0