Skip to content

Commit

Permalink
feat: oauth ruby (#733)
Browse files Browse the repository at this point in the history
* feat: add oauth support for ruby
  • Loading branch information
manisha1997 authored Nov 26, 2024
1 parent 47c5f4b commit e4e5199
Show file tree
Hide file tree
Showing 24 changed files with 2,183 additions and 9 deletions.
19 changes: 19 additions & 0 deletions lib/twilio-ruby/auth_strategy/auth_strategy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module Twilio
module REST
class AuthStrategy
attr_accessor :auth_type

def initialize(auth_type)
@auth_type = auth_type
end

def auth_string
raise NotImplementedError, 'Subclasses must implement this method'
end

def requires_authentication
raise NotImplementedError, 'Subclasses must implement this method'
end
end
end
end
17 changes: 17 additions & 0 deletions lib/twilio-ruby/auth_strategy/no_auth_strategy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module Twilio
module REST
class NoAuthStrategy < AuthStrategy
def initialize
super(AuthType::NONE)
end

def auth_string
''
end

def requires_authentication
false
end
end
end
end
38 changes: 38 additions & 0 deletions lib/twilio-ruby/auth_strategy/token_auth_strategy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
require_relative 'auth_strategy'
require_relative './../credential/auth_type'
module Twilio
module REST
class TokenAuthStrategy < AuthStrategy
attr_accessor :token_manager, :token, :lock

def initialize(token_manager)
super(AuthType::ORGS_TOKEN)
@token = nil
@token_manager = token_manager
@lock = Mutex.new
end

def auth_string
token = fetch_token
"Bearer #{token}"
end

def fetch_token
@lock.synchronize do
@token = @token_manager.fetch_access_token if @token.nil? || token_expired? || @token == ''
return @token
end
end

def token_expired?
decoded_token = JWT.decode(@token, nil, false)
exp = decoded_token[0]['exp']
Time.at(exp) < Time.now
end

def requires_authentication
true
end
end
end
end
9 changes: 8 additions & 1 deletion lib/twilio-ruby/base/client_base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class ClientBase
# rubocop:enable Style/ClassVars

attr_accessor :http_client, :username, :password, :account_sid, :auth_token, :region, :edge, :logger,
:user_agent_extensions
:user_agent_extensions, :credentials

# rubocop:disable Metrics/ParameterLists
def initialize(username = nil, password = nil, account_sid = nil, region = nil, http_client = nil, logger = nil,
Expand All @@ -22,6 +22,11 @@ def initialize(username = nil, password = nil, account_sid = nil, region = nil,
@logger = logger || Twilio.logger
@user_agent_extensions = user_agent_extensions || []
end

def credential_provider(credential_provider = nil)
@credentials = credential_provider
self
end
# rubocop:enable Metrics/ParameterLists

##
Expand All @@ -47,6 +52,8 @@ def request(host, port, method, uri, params = {}, data = {}, headers = {}, auth
@logger.debug("Request Params:#{params}")
end

auth = @credentials.to_auth_strategy.auth_string unless @credentials.nil?

response = @http_client.request(
host,
port,
Expand Down
17 changes: 17 additions & 0 deletions lib/twilio-ruby/credential/auth_type.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

module Twilio
module REST
class AuthType
BASIC = 'basic'
ORGS_TOKEN = 'orgs_token'
API_KEY = 'api_key'
NOAUTH = 'noauth'
CLIENT_CREDENTIALS = 'client_credentials'

def to_s
name
end
end
end
end
28 changes: 28 additions & 0 deletions lib/twilio-ruby/credential/client_credential_provider.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
require_relative 'credential_provider'
require_relative 'auth_type'
require_relative './../http/client_token_manager'
require_relative './../auth_strategy/token_auth_strategy'
module Twilio
module REST
class ClientCredentialProvider < CredentialProvider
attr_accessor :grant_type, :client_id, :client_secret, :orgs_token, :auth_strategy

def initialize(client_id, client_secret, orgs_token = nil)
super(AuthType::ORGS_TOKEN)
raise ArgumentError, 'client_id and client_secret are required' if client_id.nil? || client_secret.nil?

@grant_type = 'client_credentials'
@client_id = client_id
@client_secret = client_secret
@orgs_token = orgs_token
@auth_strategy = nil
end

def to_auth_strategy
@orgs_token = ClientTokenManager.new(@grant_type, @client_id, @client_secret) if @orgs_token.nil?
@auth_strategy = TokenAuthStrategy.new(@orgs_token) if @auth_strategy.nil?
@auth_strategy
end
end
end
end
11 changes: 11 additions & 0 deletions lib/twilio-ruby/credential/credential_provider.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module Twilio
module REST
class CredentialProvider
attr_accessor :auth_type

def initialize(auth_type)
@auth_type = auth_type
end
end
end
end
30 changes: 30 additions & 0 deletions lib/twilio-ruby/credential/orgs_credential_provider.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

require_relative 'credential_provider'
require_relative 'auth_type'
require_relative './../http/org_token_manager'
require_relative './../auth_strategy/token_auth_strategy'
module Twilio
module REST
class OrgsCredentialProvider < CredentialProvider
attr_accessor :grant_type, :client_id, :client_secret, :orgs_token, :auth_strategy

def initialize(client_id, client_secret, orgs_token = nil)
super(AuthType::ORGS_TOKEN)
raise ArgumentError, 'client_id and client_secret are required' if client_id.nil? || client_secret.nil?

@grant_type = 'client_credentials'
@client_id = client_id
@client_secret = client_secret
@orgs_token = orgs_token
@auth_strategy = nil
end

def to_auth_strategy
@orgs_token = OrgTokenManager.new(@grant_type, @client_id, @client_secret) if @orgs_token.nil?
@auth_strategy = TokenAuthStrategy.new(@orgs_token) if @auth_strategy.nil?
@auth_strategy
end
end
end
end
1 change: 0 additions & 1 deletion lib/twilio-ruby/framework/rest/domain.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ def absolute_url(uri)

def request(method, uri, params = {}, data = {}, headers = {}, auth = nil, timeout = nil)
url = uri.match(/^http/) ? uri : absolute_url(uri)

@client.request(
@base_url,
@port,
Expand Down
28 changes: 28 additions & 0 deletions lib/twilio-ruby/http/client_token_manager.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module Twilio
module REST
class ClientTokenManager
attr_accessor :grant_type, :client_id, :client_secret, :code, :redirect_uri, :audience, :refresh_token, :scope

def initialize(grant_type, client_id, client_secret, code = nil, redirect_uri = nil, audience = nil,
refresh_token = nil, scope = nil)
raise ArgumentError, 'client_id and client_secret are required' if client_id.nil? || client_secret.nil?

@grant_type = grant_type
@client_id = client_id
@client_secret = client_secret
@code = code
@redirect_uri = redirect_uri
@audience = audience
@refresh_token = refresh_token
@scope = scope
end

def fetch_access_token
client = Twilio::REST::Client.new
token_instance = client.preview_iam.v1.token.create(grant_type: @grant_type,
client_id: @client_id, client_secret: @client_secret)
token_instance.access_token
end
end
end
end
9 changes: 9 additions & 0 deletions lib/twilio-ruby/http/http_client.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

require 'faraday'
require 'faraday/middleware'

module Twilio
module HTTP
Expand Down Expand Up @@ -79,9 +80,17 @@ def send(request)
end

def request(host, port, method, url, params = {}, data = {}, headers = {}, auth = nil, timeout = nil)
headers['Authorization'] = auth if jwt_token?(auth)
request = Twilio::Request.new(host, port, method, url, params, data, headers, auth, timeout)
_request(request)
end

def jwt_token?(auth)
return false unless auth.is_a?(String)

parts = auth.split('.')
parts.length == 3
end
end
end
end
28 changes: 28 additions & 0 deletions lib/twilio-ruby/http/org_token_manager.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module Twilio
module REST
class OrgTokenManager
attr_accessor :grant_type, :client_id, :client_secret, :code, :redirect_uri, :audience, :refresh_token, :scope

def initialize(grant_type, client_id, client_secret, code = nil, redirect_uri = nil, audience = nil,
refresh_token = nil, scope = nil)
raise ArgumentError, 'client_id and client_secret are required' if client_id.nil? || client_secret.nil?

@grant_type = grant_type
@client_id = client_id
@client_secret = client_secret
@code = code
@redirect_uri = redirect_uri
@audience = audience
@refresh_token = refresh_token
@scope = scope
end

def fetch_access_token
client = Twilio::REST::Client.new
token_instance = client.preview_iam.v1.token.create(grant_type: @grant_type,
client_id: @client_id, client_secret: @client_secret)
token_instance.access_token
end
end
end
end
18 changes: 11 additions & 7 deletions lib/twilio-ruby/rest/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ def preview
@preview ||= Preview.new self
end
##
# Access the Preview Iam Twilio Domain
def preview_iam
@preview_iam ||=PreviewIam.new self
end
# Access the Pricing Twilio Domain
def pricing
@pricing ||= Pricing.new self
Expand Down Expand Up @@ -234,7 +238,7 @@ def authorized_connect_apps(connectAppSid=:unset)
def available_phone_numbers(countryCode=:unset)
self.api.v2010.account.available_phone_numbers(countryCode)
end

##
# @param [string] sid The SID of the Call resource to fetch.

Expand Down Expand Up @@ -283,8 +287,8 @@ def keys(sid=:unset)
def messages(sid=:unset)
self.api.v2010.account.messages(sid)
end


##
# @param [string] sid The Twilio-provided string that uniquely identifies the Notification resource to fetch.

Expand Down Expand Up @@ -332,8 +336,8 @@ def short_codes(sid=:unset)
def signing_keys(sid=:unset)
self.api.v2010.account.signing_keys(sid)
end


##
# @param [string] sid The Twilio-provided string that uniquely identifies the Transcription resource to fetch.

Expand All @@ -342,8 +346,8 @@ def signing_keys(sid=:unset)
def transcriptions(sid=:unset)
self.api.v2010.account.transcriptions(sid)
end



##
# Provide a user friendly representation
Expand Down
15 changes: 15 additions & 0 deletions lib/twilio-ruby/rest/preview_iam.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module Twilio
module REST
class PreviewIam < PreviewIamBase
def account
self.organizations.accounts
end
def role_assignment
self.organizations.role_assignments
end
def user
self.organizations.users
end
end
end
end
Loading

0 comments on commit e4e5199

Please sign in to comment.