Skip to content

Commit c536b63

Browse files
committed
feat(icp4d): refactor iam token manager and add icp4d support
1 parent 082b4ae commit c536b63

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+4602
-393
lines changed

Authentication/IamTokenManager.cs

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
/**
2+
* Copyright 2019 IBM Corp. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
using IBM.Cloud.SDK.Connection;
19+
using IBM.Cloud.SDK.Utilities;
20+
using System;
21+
using System.Collections.Generic;
22+
using UnityEngine.Networking;
23+
using Newtonsoft.Json;
24+
using System.Text;
25+
using Utility = IBM.Cloud.SDK.Utilities.Utility;
26+
27+
28+
namespace IBM.Cloud.SDK.Authentication
29+
{
30+
public class IamTokenManager : JwtTokenManager
31+
{
32+
private string iamApikey;
33+
private string iamClientId;
34+
private string iamClientSecret;
35+
private string iamDefaultUrl = "https://iam.cloud.ibm.com/identity/token";
36+
37+
private const string CLIENT_ID_SECRET_WARNING = "Warning: Client ID and Secret must BOTH be given, or the defaults will be used.";
38+
39+
public IamTokenManager(IamTokenOptions options) : base(options)
40+
{
41+
if (string.IsNullOrEmpty(url))
42+
{
43+
if (!string.IsNullOrEmpty(options.IamUrl))
44+
{
45+
url = options.IamUrl;
46+
}
47+
else
48+
{
49+
url = iamDefaultUrl;
50+
}
51+
}
52+
53+
if (!string.IsNullOrEmpty(options.IamApiKey))
54+
{
55+
iamApikey = options.IamApiKey;
56+
}
57+
58+
if (!string.IsNullOrEmpty(options.IamAccessToken))
59+
{
60+
userAccessToken = options.IamAccessToken;
61+
}
62+
63+
if (!string.IsNullOrEmpty(options.IamClientId))
64+
{
65+
iamClientId = options.IamClientId;
66+
}
67+
68+
if (!string.IsNullOrEmpty(options.IamClientSecret))
69+
{
70+
iamClientSecret = options.IamClientSecret;
71+
}
72+
73+
if (string.IsNullOrEmpty(options.IamClientSecret) || string.IsNullOrEmpty(options.IamClientId))
74+
{
75+
Log.Warning("IamTokenManager():", CLIENT_ID_SECRET_WARNING);
76+
}
77+
}
78+
79+
public void SetIamAuthorizationInfo(string IamClientId, string IamClientSecret)
80+
{
81+
iamClientId = IamClientId;
82+
iamClientSecret = IamClientSecret;
83+
if (string.IsNullOrEmpty(iamClientSecret) || string.IsNullOrEmpty(iamClientId))
84+
{
85+
Log.Warning("SetIamAuthorizationInfo():", CLIENT_ID_SECRET_WARNING);
86+
}
87+
}
88+
89+
#region Request Token
90+
/// <summary>
91+
/// Request an IAM token using an API key.
92+
/// </summary>
93+
/// <param name="callback">The request callback.</param>
94+
/// <param name="error"> The request error.</param>
95+
/// <returns></returns>
96+
override protected bool RequestToken(Callback<TokenData> callback)
97+
{
98+
if (callback == null)
99+
throw new ArgumentNullException("successCallback");
100+
101+
RESTConnector connector = new RESTConnector();
102+
connector.URL = url;
103+
if (connector == null)
104+
return false;
105+
106+
RequestIamTokenRequest req = new RequestIamTokenRequest();
107+
req.Callback = callback;
108+
req.HttpMethod = UnityWebRequest.kHttpVerbGET;
109+
req.Headers.Add("Content-type", "application/x-www-form-urlencoded");
110+
req.Headers.Add("Authorization", "Basic Yng6Yng=");
111+
req.OnResponse = OnRequestIamTokenResponse;
112+
req.DisableSslVerification = DisableSslVerification;
113+
req.Forms = new Dictionary<string, RESTConnector.Form>();
114+
req.Forms["grant_type"] = new RESTConnector.Form("urn:ibm:params:oauth:grant-type:apikey");
115+
req.Forms["apikey"] = new RESTConnector.Form(iamApikey);
116+
req.Forms["response_type"] = new RESTConnector.Form("cloud_iam");
117+
118+
return connector.Send(req);
119+
}
120+
121+
private class RequestIamTokenRequest : RESTConnector.Request
122+
{
123+
public Callback<TokenData> Callback { get; set; }
124+
}
125+
126+
private void OnRequestIamTokenResponse(RESTConnector.Request req, RESTConnector.Response resp)
127+
{
128+
DetailedResponse<TokenData> response = new DetailedResponse<TokenData>();
129+
response.Result = new TokenData();
130+
foreach (KeyValuePair<string, string> kvp in resp.Headers)
131+
{
132+
response.Headers.Add(kvp.Key, kvp.Value);
133+
}
134+
response.StatusCode = resp.HttpResponseCode;
135+
136+
try
137+
{
138+
string json = Encoding.UTF8.GetString(resp.Data);
139+
response.Result = JsonConvert.DeserializeObject<TokenData>(json);
140+
response.Response = json;
141+
}
142+
catch (Exception e)
143+
{
144+
Log.Error("Credentials.OnRequestIamTokenResponse()", "Exception: {0}", e.ToString());
145+
resp.Success = false;
146+
}
147+
148+
if (((RequestIamTokenRequest)req).Callback != null)
149+
((RequestIamTokenRequest)req).Callback(response, resp.Error);
150+
}
151+
#endregion
152+
}
153+
154+
public class IamTokenOptions : JwtTokenOptions
155+
{
156+
private string iamApiKey;
157+
[JsonProperty("iamApiKey", NullValueHandling = NullValueHandling.Ignore)]
158+
public string IamApiKey
159+
{
160+
get
161+
{
162+
return iamApiKey;
163+
}
164+
set
165+
{
166+
if (!Utility.HasBadFirstOrLastCharacter(value))
167+
{
168+
iamApiKey = value;
169+
}
170+
else
171+
{
172+
throw new IBMException("The credentials shouldn't start or end with curly brackets or quotes. Be sure to remove any {} and \" characters surrounding your credentials");
173+
}
174+
}
175+
}
176+
[JsonProperty("iamAcessToken", NullValueHandling = NullValueHandling.Ignore)]
177+
public string IamAccessToken { get; set; }
178+
[JsonProperty("iamUrl", NullValueHandling = NullValueHandling.Ignore)]
179+
public string IamUrl { get; set; }
180+
public string IamClientId { get; set; }
181+
public string IamClientSecret { get; set; }
182+
}
183+
}

Authentication/Icp4dTokenManager.cs

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/**
2+
* Copyright 2019 IBM Corp. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
using IBM.Cloud.SDK.Connection;
19+
using IBM.Cloud.SDK.Utilities;
20+
using System;
21+
using System.Net.Http;
22+
using System.Collections.Generic;
23+
using UnityEngine.Networking;
24+
using Newtonsoft.Json;
25+
using System.Text;
26+
using Utility = IBM.Cloud.SDK.Utilities.Utility;
27+
28+
29+
namespace IBM.Cloud.SDK.Authentication
30+
{
31+
public class Icp4dTokenManager : JwtTokenManager
32+
{
33+
private string username;
34+
private string password;
35+
36+
public Icp4dTokenManager(Icp4dTokenOptions options) : base(options)
37+
{
38+
tokenName = "accessToken";
39+
40+
if (!string.IsNullOrEmpty(url))
41+
{
42+
url = url + "/v1/preauth/validateAuth";
43+
}
44+
else if (string.IsNullOrEmpty(userAccessToken))
45+
{
46+
// url is not needed if the user specifies their own access token
47+
throw new ArgumentNullException("`url` is a required parameter for Icp4dTokenManagerV1");
48+
}
49+
50+
// username and password are required too, unless there's access token
51+
if (!string.IsNullOrEmpty(options.Username))
52+
{
53+
username = options.Username;
54+
}
55+
if (!string.IsNullOrEmpty(options.Password))
56+
{
57+
password = options.Password;
58+
}
59+
}
60+
61+
/// <summary>
62+
/// Create basic authentication header data for REST requests.
63+
/// </summary>
64+
/// <returns>The authentication data base64 encoded.</returns>
65+
public string CreateAuthorization()
66+
{
67+
return "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(username + ":" + password));
68+
}
69+
70+
71+
override protected bool RequestToken(Callback<TokenData> callback)
72+
{
73+
if (callback == null)
74+
throw new ArgumentNullException("successCallback");
75+
76+
RESTConnector connector = new RESTConnector();
77+
connector.URL = url;
78+
if (connector == null)
79+
return false;
80+
81+
RequestIcp4dTokenRequest req = new RequestIcp4dTokenRequest();
82+
req.Callback = callback;
83+
req.HttpMethod = UnityWebRequest.kHttpVerbGET;
84+
req.Headers.Add("Content-type", "application/x-www-form-urlencoded");
85+
req.Headers.Add("Authorization", CreateAuthorization());
86+
req.OnResponse = OnRequestIcp4dTokenResponse;
87+
req.DisableSslVerification = DisableSslVerification;
88+
req.Forms = new Dictionary<string, RESTConnector.Form>();
89+
90+
return connector.Send(req);
91+
}
92+
93+
private class RequestIcp4dTokenRequest : RESTConnector.Request
94+
{
95+
public Callback<TokenData> Callback { get; set; }
96+
}
97+
98+
private void OnRequestIcp4dTokenResponse(RESTConnector.Request req, RESTConnector.Response resp)
99+
{
100+
DetailedResponse<TokenData> response = new DetailedResponse<TokenData>();
101+
response.Result = new TokenData();
102+
foreach (KeyValuePair<string, string> kvp in resp.Headers)
103+
{
104+
response.Headers.Add(kvp.Key, kvp.Value);
105+
}
106+
response.StatusCode = resp.HttpResponseCode;
107+
108+
try
109+
{
110+
string json = Encoding.UTF8.GetString(resp.Data);
111+
response.Result = JsonConvert.DeserializeObject<TokenData>(json);
112+
response.Response = json;
113+
}
114+
catch (Exception e)
115+
{
116+
Log.Error("Credentials.OnRequestIamTokenResponse()", "Exception: {0}", e.ToString());
117+
resp.Success = false;
118+
}
119+
if (((RequestIcp4dTokenRequest)req).Callback != null)
120+
((RequestIcp4dTokenRequest)req).Callback(response, resp.Error);
121+
}
122+
}
123+
124+
public class Icp4dTokenOptions : JwtTokenOptions
125+
{
126+
private string username;
127+
public string Username
128+
{
129+
get { return username; }
130+
set
131+
{
132+
if (!Utility.HasBadFirstOrLastCharacter(value))
133+
{
134+
username = value;
135+
}
136+
else
137+
{
138+
throw new ArgumentException("The username shouldn't start or end with curly brackets or quotes. Be sure to remove any {} and \" characters surrounding your username");
139+
}
140+
}
141+
}
142+
143+
private string password;
144+
public string Password
145+
{
146+
get { return password; }
147+
set
148+
{
149+
if (!Utility.HasBadFirstOrLastCharacter(value))
150+
{
151+
password = value;
152+
}
153+
else
154+
{
155+
throw new ArgumentException("The password shouldn't start or end with curly brackets or quotes. Be sure to remove any {} and \" characters surrounding your password");
156+
}
157+
}
158+
}
159+
160+
public bool disableSslVerification { get; set; }
161+
}
162+
}

0 commit comments

Comments
 (0)