diff --git a/Authentication/ConfigBasedAuthenticatorFactory.cs b/Authentication/ConfigBasedAuthenticatorFactory.cs index e61cba5..e9d8101 100644 --- a/Authentication/ConfigBasedAuthenticatorFactory.cs +++ b/Authentication/ConfigBasedAuthenticatorFactory.cs @@ -22,11 +22,14 @@ using IBM.Cloud.SDK.Authentication.NoAuth; using IBM.Cloud.SDK.Utilities; using System.Collections.Generic; +using System; namespace IBM.Cloud.SDK.Authentication { public class ConfigBasedAuthenticatorFactory { + public static string ErrorMessageAuthTypeUnknown = "Unrecognized authentication type: {0}"; + public static Authenticator GetAuthenticator(string serviceName) { Authenticator authenticator = null; @@ -77,29 +80,29 @@ private static Authenticator CreateAuthenticator(Dictionary prop authType = Authenticator.AuthTypeIam; } - switch (authType) + if (authType.Equals(Authenticator.AuthTypeNoAuth, StringComparison.InvariantCultureIgnoreCase)) { - case Authenticator.AuthTypeNoAuth: - authenticator = new NoAuthAuthenticator(props); - break; - - case Authenticator.AuthTypeBasic: - authenticator = new BasicAuthenticator(props); - break; - - case Authenticator.AuthTypeIam: - authenticator = new IamAuthenticator(props); - break; - - case Authenticator.AuthTypeCp4d: - authenticator = new CloudPakForDataAuthenticator(props); - break; - - case Authenticator.AuthTypeBearer: - authenticator = new BearerTokenAuthenticator(props); - break; - default: - break; + authenticator = new NoAuthAuthenticator(props); + } + else if (authType.Equals(Authenticator.AuthTypeBasic, StringComparison.InvariantCultureIgnoreCase)) + { + authenticator = new BasicAuthenticator(props); + } + else if (authType.Equals(Authenticator.AuthTypeIam, StringComparison.InvariantCultureIgnoreCase)) + { + authenticator = new IamAuthenticator(props); + } + else if (authType.Equals(Authenticator.AuthTypeCp4d, StringComparison.InvariantCultureIgnoreCase)) + { + authenticator = new CloudPakForDataAuthenticator(props); + } + else if (authType.Equals(Authenticator.AuthTypeBearer, StringComparison.InvariantCultureIgnoreCase)) + { + authenticator = new BearerTokenAuthenticator(props); + } + else + { + throw new ArgumentException(string.Format(ErrorMessageAuthTypeUnknown, authType)); } return authenticator; diff --git a/Authentication/Iam/IamAuthenticator.cs b/Authentication/Iam/IamAuthenticator.cs index 6fdfed0..c7877f7 100644 --- a/Authentication/Iam/IamAuthenticator.cs +++ b/Authentication/Iam/IamAuthenticator.cs @@ -73,7 +73,6 @@ public IamAuthenticator(Dictionary config) config.TryGetValue(PropNameClientSecret, out string clientSecret); config.TryGetValue(PropNameDisableSslVerification, out string disableSslVerficiationString); bool.TryParse(disableSslVerficiationString, out bool disableSslVerification); - Log.Debug("IamAuthenticator:{0} {1} {2} {3}", apikey); Init(apikey, url, clientId, clientSecret, disableSslVerification); } @@ -168,19 +167,6 @@ bool RequestToken(Callback callback) if (callback == null) throw new ArgumentNullException("successCallback"); - // Use bx:bx as default auth header creds. - var clientId = "bx"; - var clientSecret = "bx"; - - // If both the clientId and secret were specified by the user, then use them. - if (!string.IsNullOrEmpty(ClientId) && !string.IsNullOrEmpty(ClientSecret)) - { - Log.Debug("not null: {0}", ClientId); - - clientId = ClientId; - clientSecret = ClientSecret; - } - RESTConnector connector = new RESTConnector(); connector.URL = Url; if (connector == null) @@ -190,7 +176,11 @@ bool RequestToken(Callback callback) req.Callback = callback; req.HttpMethod = UnityWebRequest.kHttpVerbGET; req.Headers.Add("Content-type", "application/x-www-form-urlencoded"); - req.Headers.Add("Authorization", Utility.CreateAuthorization(clientId, clientSecret)); + // If both the clientId and secret were specified by the user, then use them. + if (!string.IsNullOrEmpty(ClientId) && !string.IsNullOrEmpty(ClientSecret)) + { + req.Headers.Add("Authorization", Utility.CreateAuthorization(ClientId, ClientSecret)); + } req.OnResponse = OnRequestIamTokenResponse; req.DisableSslVerification = DisableSslVerification; req.Forms = new Dictionary(); @@ -250,9 +240,10 @@ public override void Validate() throw new ArgumentException(string.Format(ErrorMessagePropInvalid, "url")); } - if (string.IsNullOrEmpty(ClientSecret) || string.IsNullOrEmpty(ClientId)) + if (!string.IsNullOrEmpty(ClientSecret) && string.IsNullOrEmpty(ClientId) || string.IsNullOrEmpty(ClientSecret) && !string.IsNullOrEmpty(ClientId)) { - Log.Warning("IamTokenManager():", "Warning: Client ID and Secret must BOTH be given, or the defaults will be used."); + + throw new ArgumentException("Client ID and Secret must BOTH be provided."); } } } diff --git a/BaseService.cs b/BaseService.cs index 8f6c2e3..cadd5f3 100644 --- a/BaseService.cs +++ b/BaseService.cs @@ -26,8 +26,12 @@ namespace IBM.Cloud.SDK { public class BaseService { - protected Authenticator authenticator; - protected string url; + #region Authenticator + /// + /// Gets and sets the authenticator of the service. + public Authenticator Authenticator { get; set; } + #endregion + protected string serviceUrl; public string ServiceId { get; set; } protected Dictionary customRequestHeaders = new Dictionary(); public static string PropNameServiceUrl = "URL"; @@ -39,32 +43,24 @@ public BaseService(string versionDate, Authenticator authenticator, string servi public BaseService(Authenticator authenticator, string serviceId) { ServiceId = serviceId; - this.authenticator = authenticator ?? throw new ArgumentNullException(ErrorMessageNoAuthenticator); - + Authenticator = authenticator ?? throw new ArgumentNullException(ErrorMessageNoAuthenticator); // Try to retrieve the service URL from either a credential file, environment, or VCAP_SERVICES. Dictionary props = CredentialUtils.GetServiceProperties(serviceId); props.TryGetValue(PropNameServiceUrl, out string url); if (!string.IsNullOrEmpty(url)) { - SetEndpoint(url); + SetServiceUrl(url); } } - protected void SetAuthentication(RESTConnector connector) + public void SetServiceUrl(string url) { - if (authenticator != null) - { - authenticator.Authenticate(connector); - } - else - { - throw new ArgumentException("Authentication information was not properly configured."); - } + serviceUrl = url; } - public void SetEndpoint(string endpoint) + public string GetServiceUrl() { - url = endpoint; + return serviceUrl; } /// @@ -72,7 +68,7 @@ public void SetEndpoint(string endpoint) /// public Authenticator GetAuthenticator() { - return authenticator; + return Authenticator; } public void WithHeader(string name, string value) diff --git a/Connection/RESTConnector.cs b/Connection/RESTConnector.cs index 0b2349f..eca60fa 100644 --- a/Connection/RESTConnector.cs +++ b/Connection/RESTConnector.cs @@ -260,15 +260,28 @@ public bool? DisableSslVerification /// /// Authenticator used to authenticate service. /// The name of the function. + /// Service Url to connect to. /// Returns a RESTConnector object or null on error. /// - public static RESTConnector GetConnector(Authenticator authenticator, string function) + public static RESTConnector GetConnector(Authenticator authenticator, string function, string serviceUrl) { + if (string.IsNullOrEmpty(serviceUrl)) + { + throw new ArgumentNullException("The serviceUrl must not be empty or null."); + } + + if (Utility.HasBadFirstOrLastCharacter(serviceUrl)) + { + throw new ArgumentException("The serviceUrl property is invalid. Please remove any surrounding {{, }}, or \" characters."); + } + RESTConnector connector = new RESTConnector { - URL = authenticator.Url + function, + URL = serviceUrl + function, Authentication = authenticator }; + + authenticator.Authenticate(connector); return connector; } diff --git a/Connection/WSConnector.cs b/Connection/WSConnector.cs index 4beeea1..55940a7 100644 --- a/Connection/WSConnector.cs +++ b/Connection/WSConnector.cs @@ -25,10 +25,10 @@ using System.Security.Authentication; using IBM.Cloud.SDK.Authentication; using System.Threading; +using System; #if !NETFX_CORE using UnitySDK.WebSocketSharp; #else -using System; using System.Threading.Tasks; using Windows.Networking.Sockets; using Windows.Security.Credentials; @@ -322,18 +322,30 @@ public static string FixupURL(string URL) } /// - /// Create a WSConnector for the given service and function. + /// Create a WSConnector for the given service and function. /// /// The authenticator for the service. /// The name of the function to connect. /// Additional function arguments. + /// Service Url to connect to. /// The WSConnector object or null or error. - public static WSConnector CreateConnector(Authenticator authenticator, string function, string args) + public static WSConnector CreateConnector(Authenticator authenticator, string function, string args, string serviceUrl) { + if (string.IsNullOrEmpty(serviceUrl)) + { + throw new ArgumentNullException("The serviceUrl must not be empty or null."); + } + + if (Utility.HasBadFirstOrLastCharacter(serviceUrl)) + { + throw new ArgumentException("The serviceUrl property is invalid. Please remove any surrounding {{, }}, or \" characters."); + } + WSConnector connector = new WSConnector(); connector.Authentication = authenticator; - connector.URL = FixupURL(authenticator.Url) + function + args; + connector.URL = FixupURL(serviceUrl) + function + args; + authenticator.Authenticate(connector); return connector; }