Skip to content
This repository has been archived by the owner on Jan 20, 2024. It is now read-only.

Commit

Permalink
Added OAuth2 authentication support
Browse files Browse the repository at this point in the history
Added OAuth2 authentication support
  • Loading branch information
sfdrogojan authored May 21, 2019
1 parent 36a933f commit b4babd6
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 27 deletions.
10 changes: 6 additions & 4 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
sfmc-fuelsdk-ruby (1.1.0)
sfmc-fuelsdk-ruby (1.2.0)
json (~> 1.8, >= 1.8.1)
jwt (~> 1.0, >= 1.0.0)
savon (= 2.2.0)
Expand All @@ -16,6 +16,7 @@ GEM
coderay (1.1.2)
diff-lcs (1.3)
ffi (1.9.25)
ffi (1.9.25-x64-mingw32)
ffi (1.9.25-x86-mingw32)
formatador (0.2.5)
guard (1.8.3)
Expand All @@ -39,9 +40,9 @@ GEM
rb-kqueue (>= 0.2)
lumberjack (1.0.13)
method_source (0.9.0)
mini_portile2 (2.3.0)
nokogiri (1.8.5)
mini_portile2 (~> 2.3.0)
mini_portile2 (2.4.0)
nokogiri (1.10.1-x64-mingw32)
mini_portile2 (~> 2.4.0)
nori (2.1.0)
pry (0.11.3)
coderay (~> 1.1.0)
Expand Down Expand Up @@ -76,6 +77,7 @@ GEM

PLATFORMS
ruby
x64-mingw32
x86-mingw32

DEPENDENCIES
Expand Down
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,29 @@ ExactTarget Fuel SDK / SalesforceMarektingCloudSDK for Ruby
## Overview ##
The Fuel SDK for Ruby provides easy access to ExactTarget's Fuel API Family services, including a collection of REST APIs and a SOAP API. These APIs provide access to ExactTarget functionality via common collection types such as array/hash.


## New Features in Version 1.2.0 ##
- **OAuth2 authentication support** - [More Details](https://developer.salesforce.com/docs/atlas.en-us.mc-app-development.meta/mc-app-development/integration-considerations.htm)

To enable OAuth2 authentication, pass ```use_oAuth2_authentication => true``` in the params argument to the Client's class constructor.

Example of instantiating the Client class:

```
myclient = MarketingCloudSDK::Client.new({
'client' => {
'id' => '<CLIENT_ID>',
'secret' => '<CLIENT_SECRET>',
'request_token_url' => '<AUTH TENANT SPECIFIC ENDPOINT>',
'soap_endpoint' => '<SOAP TENANT SPECIFIC ENDPOINT>',
'base_api_url' => '<REST TENANT SPECIFIC ENDPOINT>',
'use_oAuth2_authentication' => true,
'account_id' => <TARGET_ACCOUNT_ID>,
'scope' => '<PERMISSION_LIST>'
}
})
```

## New Features in Version 1.1.0 ##
- **Added support for your tenant's endpoints - [More Details](https://developer.salesforce.com/docs/atlas.en-us.mc-apis.meta/mc-apis/your-subdomain-tenant-specific-endpoints.htm) **
- **MarketingCloudSDK gem will be available as sfmc-fuelsdk-ruby on ruby gems.
Expand Down Expand Up @@ -42,7 +65,7 @@ gem build marketingcloudsdk.gemspec
Install the newly built gem

```ruby
gem install marketingcloudsdk-1.1.0.gem
gem install marketingcloudsdk-1.2.0.gem
```

If you have not registered your application or you need to lookup your Application Key or Application Signature values, please go to App Center at [Code@: ExactTarget's Developer Community](http://code.exacttarget.com/appcenter "Code@ App Center").
Expand Down
62 changes: 57 additions & 5 deletions lib/marketingcloudsdk/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def unpack raw
class Client
attr_accessor :debug, :access_token, :auth_token, :internal_token, :refresh_token,
:id, :secret, :signature, :base_api_url, :package_name, :package_folders, :parent_folders, :auth_token_expiration,
:request_token_url, :soap_endpoint
:request_token_url, :soap_endpoint, :use_oAuth2_authentication, :account_id, :scope

include MarketingCloudSDK::Soap
include MarketingCloudSDK::Rest
Expand All @@ -103,29 +103,43 @@ def initialize(params={}, debug=false)
self.secret = client_config["secret"]
self.signature = client_config["signature"]
self.base_api_url = !(client_config["base_api_url"].to_s.strip.empty?) ? client_config["base_api_url"] : 'https://www.exacttargetapis.com'
self.request_token_url = !(client_config["request_token_url"].to_s.strip.empty?) ? client_config["request_token_url"] : 'https://auth.exacttargetapis.com/v1/requestToken'
self.request_token_url = client_config["request_token_url"]
self.soap_endpoint = client_config["soap_endpoint"]
self.use_oAuth2_authentication = client_config["use_oAuth2_authentication"]
self.account_id = client_config["account_id"]
self.scope = client_config["scope"]
end

# Set a default value in case no 'client' params is sent
if (!self.base_api_url)
self.base_api_url = 'https://www.exacttargetapis.com'
end

# Leaving this for backwards compatibility
if (!self.request_token_url)
self.request_token_url = params['request_token_url'] ? params['request_token_url'] : 'https://auth.exacttargetapis.com/v1/requestToken'
if (self.request_token_url.to_s.strip.empty?)
if(use_oAuth2_authentication == true)
raise 'request_token_url (Auth TSE) is mandatory when using OAuth2 authentication'
else
self.request_token_url = 'https://auth.exacttargetapis.com/v1/requestToken'
end
end

self.jwt = params['jwt'] if params['jwt']
self.refresh_token = params['refresh_token'] if params['refresh_token']

self.wsdl = params["defaultwsdl"] if params["defaultwsdl"]

self.refresh
end

def refresh force=false
@refresh_mutex.synchronize do
raise 'Require Client Id and Client Secret to refresh tokens' unless (id && secret)

if (self.use_oAuth2_authentication == true)
self.refreshWithOAuth2(force)
return
end

#If we don't already have a token or the token expires within 5 min(300 seconds)
if (self.access_token.nil? || Time.new + 300 > self.auth_token_expiration || force) then
payload = Hash.new.tap do |h|
Expand Down Expand Up @@ -154,6 +168,44 @@ def refresh force=false
end
end

def refreshWithOAuth2 force=false
raise 'Require Client Id and Client Secret to refresh tokens' unless (id && secret)
#If we don't already have a token or the token expires within 5 min(300 seconds)
if (self.access_token.nil? || Time.new + 300 > self.auth_token_expiration || force) then
payload = Hash.new.tap do |h|
h['client_id']= id
h['client_secret'] = secret
h['grant_type'] = 'client_credentials'

if (not self.account_id.to_s.strip.empty?)then
h['account_id'] = account_id
end

if (not self.scope.to_s.strip.empty?)then
h['scope'] = scope
end
end

options = Hash.new.tap do |h|
h['data'] = payload
h['content_type'] = 'application/json'
end

self.request_token_url += '/v2/token'

response = post(request_token_url, options)
raise "Unable to refresh token: #{response['message']}" unless response.has_key?('access_token')

self.access_token = response['access_token']
self.auth_token_expiration = Time.new + response['expires_in']
self.soap_endpoint = response['soap_instance_url'] + 'service.asmx'
self.base_api_url = response['rest_instance_url']
return true
else
return false
end
end

def refresh!
refresh true
end
Expand Down
46 changes: 30 additions & 16 deletions lib/marketingcloudsdk/soap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,18 @@ module Soap
include MarketingCloudSDK::Targeting

def header
raise 'Require legacy token for soap header' unless internal_token
{
'oAuth' => {'oAuthToken' => internal_token},
:attributes! => { 'oAuth' => { 'xmlns' => 'http://exacttarget.com' }}
}
if use_oAuth2_authentication == true then
{
'fueloauth' => {'fueloauth' => access_token},
:attributes! => { 'fueloauth'=>{ 'xmlns' => 'http://exacttarget.com' }}
}
else
raise 'Require legacy token for soap header' unless internal_token
{
'oAuth' => {'oAuthToken' => internal_token},
:attributes! => { 'oAuth' => { 'xmlns' => 'http://exacttarget.com' }}
}
end
end

def debug
Expand All @@ -138,17 +145,24 @@ def wsdl

def soap_client
self.refresh
@soap_client = Savon.client(
soap_header: header,
wsdl: wsdl,
endpoint: endpoint,
wsse_auth: ["*", "*"],
raise_errors: false,
log: debug,
open_timeout:180,
read_timeout: 180,
headers: {'User-Agent' => 'FuelSDK-Ruby-v' + MarketingCloudSDK::VERSION}
)

soap_client_options = {
soap_header: header,
wsdl: wsdl,
endpoint: endpoint,
wsse_auth: ["*", "*"],
raise_errors: false,
log: debug,
open_timeout:180,
read_timeout: 180,
headers: {'User-Agent' => 'FuelSDK-Ruby-v' + MarketingCloudSDK::VERSION}
}

if use_oAuth2_authentication == true then
soap_client_options.delete(:wsse_auth)
end

@soap_client = Savon.client(soap_client_options)
end

def soap_describe object_type
Expand Down
2 changes: 1 addition & 1 deletion lib/marketingcloudsdk/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@
=end

module MarketingCloudSDK
VERSION = "1.1.0"
VERSION = "1.2.0"
end

0 comments on commit b4babd6

Please sign in to comment.