httpbasic + apikey and multitenancy - multi-tenant

I'm about to implement httpbasic + apikey authentication with multitenancy.
What I mean... I'd like to create procedure with input parameters for username, password and apikey, so that users could use it with their own credentials, not only with stored default creds.
Below is how it works in sql without multitenancy.
EXEC SYSADMIN.createConnection("name" => 'webservice1', "jbossCLITemplateName" => 'name1', "connectionOrResourceAdapterProperties" => 'EndPoint=https://api.example.com/api/,SecurityType=HTTPBasic,AuthUserName=[EMAIL]', "encryptedProperties" => 'AuthPassword=[PASSWORD]') ;;
EXEC SYSADMIN.createDataSource("name" => 'webservice1', "translator" => 'name1', "modelProperties" => '', "translatorProperties" => '', "encryptedModelProperties" => '', "encryptedTranslatorProperties" => '') ;;
exec webservice1.invokeHTTP(endpoint=>'2.0/checks',requestHeaders=> App-Key: myapikey1 ,action=>'GET',requestContentType=>'application/xml')
Now I'm trying to create connection without authusername and authpassword and it does work
EXEC SYSADMIN.createConnection("name" => 'webservice1', "jbossCLITemplateName" => 'name1', "connectionOrResourceAdapterProperties" => 'EndPoint=https://api.example.com/api/,SecurityType=HTTPBasic') ;;
EXEC SYSADMIN.createDataSource("name" => 'webservice1', "translator" => 'name1', "modelProperties" => '', "translatorProperties" => '', "encryptedModelProperties" => '', "encryptedTranslatorProperties" => '') ;;
but then I'm trying to call my webservice with credentials entered manually
exec webservice1.invokeHTTP(endpoint=>'2.0/checks',requestHeaders=> AuthUserName: user1 || AuthPassword: pass1 || App-Key: myapikey1,action=>'GET',requestContentType=>'application/xml')
and receive error:
Server returned HTTP response code: 401 for URL: https://api.example.com/api//2.0/test1** http error stream***{"error":{"statuscode":401,"statusdesc":" Unauthorized","errormessage":"User credentials missing"}}
How do I pass username and password for httpbasic auth properly without need to recreate the connection for different user?
Please advise.

I would like to suggest that despite using the custom basic authorization header, more details should be included like the domain, time stamp, computed signature of the headers so that the validity of the headers and also possibly avoid request replay attacks.
AWS signature model
http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html

Related

Invalid token errors when trying to tweet

I'm using the ThuJohn Twitter package for Laravel and am trying to post tweets as a site user, but keep getting [89] Invalid or expired token. errors.
I know the package is installed correctly because I can send tweets using the website's app credentials; it's when I'm trying to tweet as a site user I run into problems.
I'm using the reconfig method, yet am still encountering issues. I'm wondering if my user credentials are wrong?
Here's the reconfig method:
Twitter::reconfig([
'consumer_key' => env('TWITTER_CONSUMER_KEY'),
'consumer_secret' => env('TWITTER_CONSUMER_SECRET'),
'token' => $user->twitter->token,
'secret' => $user->twitter->secret
]);
And this is how I'm grabbing the user's token and secret inside the callback method. Is this the correct way?
$request_token = [
'token' => Session::get('oauth_request_token'),
'secret' => Session::get('oauth_request_token_secret'),
];

Can't add email to Campaign Monitor API?

I am trying to create some simple Ruby code to add emails using the Campaign Monitor API. Below is my code.
require 'httparty'
require 'json'
def request
url = 'https://api.createsend.com/api/v3.1/subscribers/MYLISTID.json'
auth = {:username => 'MYAPIKEY', :password => 'x'}
response = HTTParty.post(url,
:basic_auth => auth, :body => {
'EmailAddress' => 'mike#hotmail.com',
'Name' => 'Test',
'Resubscribe' => true,
'RestartSubscriptionBasedAutoresponders' => true
})
puts response
puts response.code
end
request
I can connect with the API. However, when I try to add the email I am getting the following response.
{"Code"=>400, "Message"=>"Failed to deserialize your request.
Please check the documentation and try again.
Fields in error: subscriber"}
400
When I change the request to get instead of put
my response is:
{"Code"=>1, "Message"=>"Invalid Email Address"}
I can't understand what I am doing wrong as I have followed the documentation on the Campaign Monitor API
It looks like you have everything setup correctly, you just need to turn the body of the post into a json string.
response = HTTParty.post(url,
:basic_auth => auth, :body => {
'EmailAddress' => 'mike#hotmail.com',
'Name' => 'Test',
'Resubscribe' => true,
'RestartSubscriptionBasedAutoresponders' => true
}.to_json)
I'd like to point out that a Campaign Monitor API gem also exists that will do all of that work for you.
Campaign Monitor API Gem

upload image with soundcloud api

I keep getting an error everytime I try to change the souncloud avatar by uploading, I'm guessing something is wrong with my api wrapper layout? I get a
"`handle_response': HTTP status: 500 Internal Server Error (SoundCloud::ResponseError)"
"HTTP status: 403 Forbidden (SoundCloud::ResponseError)
from /Users/.../.rvm/gems/ruby-2.2.0/gems/soundcloud-0.3.2/lib/soundcloud/client.rb:32:in `post'"
My code:
require 'soundcloud'
user = Soundcloud.new(:client_id => '...',
:client_secret => '...',
:username => '...',
:password => '...')
avatar_data = File.path("/path/to/file/-1.jpg")
user.post('/me').avatar_data
I also tried:
testuser.post('/me/#{avatar_data}')

Google API Ruby Client - single user with OAuth 2.0

the goal is to have one Google (YouTube) account for the web app. Users of the web app will be able to upload videos via this account to the one YouTube channel. After many hours im in the ends. I've found plenty of samples how to implement for Google user <-> web app interaction, but I don't need such comprehensive solution.
I'm trying over OAuth 2.0 (as recommended) and with Google API Ruby Client (https://github.com/google/google-api-ruby-client)
So far I have authorized the Google account (which will have that YouTube channel) with the web app, all necessary scopes included, offline access too and I have mechanism for refreshing access token. So I have access token, refresh token, client id and client secret.
But I don't know how to send a simple authorized request. The result below returns me "Daily Limit for Unauthenticated Use Exceeded." after a while so something wrong - i guess im missing part with client id and client secret.
So the question is: How to send simply authorized request via OAuth 2.0 with Google API Ruby Client, when we work with only one user and we have all necessary ids, secrets and tokens?
Thanks for any help or suggestion.
# Faraday connection
conn = Faraday.new(:url => 'https://accounts.google.com',:ssl => {:verify => false}) do |faraday|
faraday.request :url_encoded
faraday.response :logger
faraday.adapter Faraday.default_adapter
end
# Refresh token
result = conn.post '/o/oauth2/token', {
'refresh_token' => "1/1lDIvifN******************dk9Akuc9ELVKM0",
'client_id' => "61********506.apps.googleusercontent.com",
'client_secret' => "********************g_dLfKmi",
'grant_type' => 'refresh_token'}
#output = ActiveSupport::JSON.decode result.body
#access_token = #output['access_token']
#token_type = #output['token_type']
# Google Client
client = Google::APIClient.new
# YouTube API v3
api = client.discovered_api('youtube', 'v3')
# Retrieve list of playlists (not working)
#result = client.execute(
:api_method => api.playlists.list,
:parameters => {'part' => 'snippet', 'mine' => 'true'},
:authorization => {'token_type' => #token_type, 'access_token' => #access_token}
)
Ok, so I though the :authorization param in the execute request will add HTTP header Authorization: token_type access_token itself, but not and it was a problem.
So this works:
#result = client.execute(
:api_method => api.playlists.list,
:parameters => {'part' => 'snippet', 'mine' => 'true'},
:authorization => {:token_type => #token_type, :access_token => #access_token},
:headers => {:authorization => #token_type + ' ' + #access_token}
)

Authentication headers using Rest Client Ruby Gem

I have already created a basic authentication key, now I am just trying to utilize it. I have tried a few different variations, but none seem to show Authorization in the request headers.
$auth = 'Basic cmFtZXNoQHVzYW1hLmNvbTpyYW1lc2h1JEBtcA=='
#response = resource.post('Authorization' => $auth)
nor
#response = resource.post(:authorization => $auth)
nor
#response = resource.post(:Authorization => $auth)
nor
#response = resource.post(:content_type => :json, :accept => :json, :headers => { 'Authorization:' => $auth })
Unfortunately I am not finding a lot of info in the rdoc that can help me solve this. Does anyone have experience adding auth headers using the Rest Client gem?
For Basic Auth, you should be able to set the user and password in plaintext when you create the resource:
resource = RestClient::Resource.new( 'http://example.com', 'user', 'password' )
But if you really need to set the header directly per request:
#response = resource.post( request_payload, :Authorization => $auth )
should work. If it does not, then you may have set $auth incorrectly. However, I think you just missed adding the request payload, so it was using the hash you supplied for that required param, and not setting any headers at all.
Here's a complete and working example using get (I don't have a test service available with Basic Auth and POST)
require 'rest-client'
require 'base64'
$auth = 'Basic ' + Base64.encode64( 'user:passwd' ).chomp
$url = 'http://httpbin.org/basic-auth/user/passwd'
#resource = RestClient::Resource.new( $url )
#response = #resource.get( :Authorization => $auth )
# => "{\n \"authenticated\": true,\n \"user\": \"user\"\n}"
Note: Though this works, I recommend you use the first and simplest method of supplying user and password to the constructor unless you have good reason not to.
Even though I didn't have a payload to send I was trying to send one without. This ended up being the cause. So I included:
json_str = ''
#response = resource.post(json_str, :content_type => :json, :accept => :json, :Authorization => $auth)
And this worked.
If you don't want to use RestClient::Resource, you can include basic auth in a request like this:
RestClient::Request.execute method: :get, url: url, user: 'username', password: 'secret'
The trick is not to use the RestClient.get (or .post, .put etc.) methods since all options you pass in there are used as headers.
This worked great for me, in case anyone wants to use username/password
RestClient.post("https://USERNAME:PASSWORD#yoursite.com/something", { some: "payload data" })

Resources