Skip to content

Commit c1337fc

Browse files
authored
feat: BoxCCGAuth add User and Admin clients factory methods without initial token (#883)
* feat: `BoxCCGAuth` add User and Admin clients factory methods without initial token * fix: add configure awaits * fix: 👌 configure await * docu(CCG): add new admin/client factory method examples * docu: fix invalid links * docu: 👌 typo
1 parent 84bb80c commit c1337fc

File tree

5 files changed

+87
-13
lines changed

5 files changed

+87
-13
lines changed

Box.V2.Test/BoxCCGAuthTest.cs

+22
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,17 @@ public void UserClient_ShouldReturnUserClientWithSession()
100100
Assert.IsNotNull(userClient.Auth.Session);
101101
}
102102

103+
[TestMethod]
104+
public void UserClient_WithoutInitialToken_ShouldReturnUserClient()
105+
{
106+
// Act
107+
var userClient = _ccgAuth.UserClient("22222");
108+
109+
// Assert
110+
Assert.IsInstanceOfType(userClient, typeof(BoxClient));
111+
Assert.IsInstanceOfType(userClient.Auth, typeof(CCGAuthRepository));
112+
}
113+
103114
[TestMethod]
104115
public void AdminClient_ShouldReturnAdminClientWithSession()
105116
{
@@ -111,5 +122,16 @@ public void AdminClient_ShouldReturnAdminClientWithSession()
111122
Assert.IsInstanceOfType(adminClient.Auth, typeof(CCGAuthRepository));
112123
Assert.IsNotNull(adminClient.Auth.Session);
113124
}
125+
126+
[TestMethod]
127+
public void AdminClient_WithoutInitialToken_ShouldReturnAdminClient()
128+
{
129+
// Act
130+
var adminClient = _ccgAuth.AdminClient("22222", true);
131+
132+
// Assert
133+
Assert.IsInstanceOfType(adminClient, typeof(BoxClient));
134+
Assert.IsInstanceOfType(adminClient.Auth, typeof(CCGAuthRepository));
135+
}
114136
}
115137
}

Box.V2/CCGAuth/BoxCCGAuth.cs

+27
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,20 @@ public IBoxClient AdminClient(string adminToken, string asUser = null, bool? sup
4949
return adminClient;
5050
}
5151

52+
/// <summary>
53+
/// Create admin BoxClient
54+
/// </summary>
55+
/// <param name="asUser">The user ID to set as the 'As-User' header parameter; used to make calls in the context of a user using an admin token</param>
56+
/// <param name="suppressNotifications">Whether or not to suppress both email and webhook notifications. Typically used for administrative API calls. Your application must have “Manage an Enterprise” scope, and the user making the API calls is a co-admin with the correct "Edit settings for your company" permission.</param>
57+
/// <returns>BoxClient that uses CCG authentication</returns>
58+
public IBoxClient AdminClient(string asUser = null, bool? suppressNotifications = null)
59+
{
60+
var authRepo = new CCGAuthRepository(this);
61+
var adminClient = new BoxClient(_boxConfig, authRepo, asUser: asUser, suppressNotifications: suppressNotifications);
62+
63+
return adminClient;
64+
}
65+
5266
/// <summary>
5367
/// Create user BoxClient using a user access token
5468
/// </summary>
@@ -64,6 +78,19 @@ public IBoxClient UserClient(string userToken, string userId)
6478
return userClient;
6579
}
6680

81+
/// <summary>
82+
/// Create user BoxClient
83+
/// </summary>
84+
/// <param name="userId">Id of the user</param>
85+
/// <returns>BoxClient that uses CCG authentication</returns>
86+
public IBoxClient UserClient(string userId)
87+
{
88+
var authRepo = new CCGAuthRepository(this, userId);
89+
var userClient = new BoxClient(_boxConfig, authRepo);
90+
91+
return userClient;
92+
}
93+
6794
/// <summary>
6895
/// Get admin token by posting data to auth url
6996
/// </summary>

Box.V2/CCGAuth/CCGAuthRepository.cs

+12-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public class CCGAuthRepository : IAuthRepository
2525
public string UserId { get; private set; }
2626

2727
/// <summary>
28-
/// Event fired when session is invalidated
28+
/// Event fired when session is invalidated
2929
/// </summary>
3030
public event EventHandler SessionInvalidated;
3131

@@ -47,6 +47,16 @@ public CCGAuthRepository(OAuthSession session, BoxCCGAuth boxCCGAuth, string use
4747
UserId = userId;
4848
}
4949

50+
/// <summary>
51+
/// Constructor CCG auth repository
52+
/// </summary>
53+
/// <param name="boxCCGAuth">CCG authentication</param>
54+
/// <param name="userId">Id of the user</param>
55+
public CCGAuthRepository(BoxCCGAuth boxCCGAuth, string userId = null)
56+
: this(null, boxCCGAuth, userId)
57+
{
58+
}
59+
5060
/// <summary>
5161
/// Not used for this type of authentication
5262
/// </summary>
@@ -67,7 +77,7 @@ public Task LogoutAsync()
6777
}
6878

6979
/// <summary>
70-
/// Retrieves a new access token using BoxCCGAuth
80+
/// Retrieves a new access token using BoxCCGAuth
7181
/// </summary>
7282
/// <param name="accessToken">This input is not used. Could be set to null</param>
7383
/// <returns>OAuth session</returns>

Box.V2/Managers/BoxResourceManager.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
using System.Collections.Generic;
1515
using System.Globalization;
1616
using System.Reflection;
17-
using System.Text;
1817
using System.Text.RegularExpressions;
1918
using System.Threading.Tasks;
2019

@@ -74,7 +73,7 @@ protected async Task<IBoxResponse<T>> ToResponseAsync<T>(IBoxRequest request, bo
7473
where T : class
7574
{
7675
AddDefaultHeaders(request);
77-
AddAuthorization(request);
76+
await AddAuthorizationAsync(request).ConfigureAwait(false);
7877
var response = await ExecuteRequest<T>(request, queueRequest).ConfigureAwait(false);
7978

8079
return converter != null ? response.ParseResults(converter) : response.ParseResults(_converter);
@@ -108,13 +107,14 @@ protected async Task<IBoxResponse<T>> RetryExpiredTokenRequest<T>(IBoxRequest re
108107
{
109108
OAuthSession newSession = await _auth.RefreshAccessTokenAsync(request.Authorization).ConfigureAwait(false);
110109
AddDefaultHeaders(request);
111-
AddAuthorization(request, newSession.AccessToken);
110+
await AddAuthorizationAsync(request, newSession.AccessToken).ConfigureAwait(false);
112111
return await _service.ToResponseAsync<T>(request).ConfigureAwait(false);
113112
}
114113

115-
protected void AddAuthorization(IBoxRequest request, string accessToken = null)
114+
protected async Task AddAuthorizationAsync(IBoxRequest request, string accessToken = null)
116115
{
117-
var auth = accessToken ?? _auth.Session.AccessToken;
116+
var auth = accessToken ??
117+
(_auth.Session ?? await _auth.RefreshAccessTokenAsync(null).ConfigureAwait(false)).AccessToken;
118118

119119
var authString = string.Format(CultureInfo.InvariantCulture, Constants.V2AuthString, auth);
120120

docs/authentication.md

+21-6
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ var client = new BoxClient(config, session);
5050

5151
Server auth allows your application to authenticate itself with the Box API
5252
for a given enterprise. By default, your application has a
53-
[Service Account](https://developer.box.com/en/guides/authentication/user-types/)
53+
[Service Account](https://developer.box.com/guides/getting-started/user-types/service-account/)
5454
that represents it and can perform API calls. The Service Account is separate
5555
from the Box accounts of the application developer and the enterprise admin of
5656
any enterprise that has authorized the app — files stored in that account are
@@ -85,8 +85,7 @@ adminClient.Auth.SessionAuthenticated += delegate(object o, SessionAuthenticated
8585
};
8686
```
8787

88-
App auth applications also often have associated App Users, which are
89-
[created and managed directly by the application](https://developer.box.com/en/guides/authentication/user-types/)
88+
App auth applications also often have associated [App Users](https://developer.box.com/guides/getting-started/user-types/app-users/), which are created and managed directly by the application
9089
— they do not have normal login credentials, and can only be accessed through
9190
the Box API by the application that created them. You may authenticate as the
9291
Service Account to provision and manage users, or as an individual app user to
@@ -115,7 +114,7 @@ Server auth allows your application to authenticate itself with the Box API
115114
for a given enterprise.
116115
Client Credentials Grant (CCG) allows you to authenticate by providing `clientId` and `clientSecret` and `enterpriseId` of your app.
117116
By default, your application has a
118-
[Service Account](https://developer.box.com/en/guides/authentication/user-types/)
117+
[Service Account](https://developer.box.com/guides/getting-started/user-types/service-account/)
119118
that represents it and can perform API calls. The Service Account is separate
120119
from the Box accounts of the application developer and the enterprise admin of
121120
any enterprise that has authorized the app — files stored in that account are
@@ -130,6 +129,10 @@ var boxConfig = new BoxConfigBuilder("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET")
130129
.SetEnterpriseId("YOUR_ENTERPRISE_ID")
131130
.Build();
132131
var boxCCG = new BoxCCGAuth(boxConfig);
132+
```
133+
134+
There are two ways to create an admin client, the first one uses explicit admin token:
135+
```c#
133136
var adminToken = await boxCCG.AdminTokenAsync(); //valid for 60 minutes so should be cached and re-used
134137
IBoxClient adminClient = boxCCG.AdminClient(adminToken);
135138
adminClient.Auth.SessionAuthenticated += delegate(object o, SessionAuthenticatedEventArgs e)
@@ -139,8 +142,12 @@ adminClient.Auth.SessionAuthenticated += delegate(object o, SessionAuthenticated
139142
};
140143
```
141144

142-
App auth applications also often have associated App Users, which are
143-
[created and managed directly by the application](https://developer.box.com/en/guides/authentication/user-types/)
145+
Second way leaves token management (caching) to the `Auth`, a new token is retrieved before the first call. Keep in mind that if you create multiple `adminClient` instances, the token won't be shared, it is expected that the `adminClient` instance is reused.
146+
```c#
147+
IBoxClient adminClient = boxCCG.AdminClient();
148+
```
149+
150+
App auth applications also often have associated [App Users](https://developer.box.com/guides/getting-started/user-types/app-users/), which are created and managed directly by the application
144151
— they do not have normal login credentials, and can only be accessed through
145152
the Box API by the application that created them. You may authenticate as the
146153
Service Account to provision and manage users, or as an individual app user to
@@ -155,6 +162,10 @@ instance as in the above examples, similarly to creating a Service Account clien
155162
var boxConfig = new BoxConfigBuilder("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET")
156163
.Build();
157164
var boxCCG = new BoxCCGAuth(boxConfig);
165+
```
166+
167+
Variant with explicit initial token:
168+
```c#
158169
var userToken = await boxCCG.UserTokenAsync("USER_ID"); //valid for 60 minutes so should be cached and re-used
159170
IBoxClient userClient = boxCCG.UserClient(userToken, "USER_ID");
160171
userClient.Auth.SessionAuthenticated += delegate(object o, SessionAuthenticatedEventArgs e)
@@ -163,6 +174,10 @@ userClient.Auth.SessionAuthenticated += delegate(object o, SessionAuthenticatedE
163174
// cache the new access token
164175
};
165176
```
177+
Variant without initial token:
178+
```c#
179+
IBoxClient userClient = boxCCG.UserClient("USER_ID");
180+
```
166181

167182
### Traditional 3-Legged OAuth2
168183

0 commit comments

Comments
 (0)