Box App Userの検索または作成
Box App Userの検索または作成
この時点で、アプリケーションコードが作成されています。このコードでは、ユーザーアクセスからのトラフィックを処理し、これらをログインのためにOktaに転送して、Oktaのユーザー情報を提供した後、最終的にはBoxのハンドラ (現時点で未作成) に渡します。
このセクションでは、以下のようにBoxの最終的なコンポーネントを取り上げます。
- Oktaユーザーに、関連付けられたBox App Userアカウントがあるかどうかを検証します。
- (関連付けられているアカウントがない場合は) 関連付けられているOktaレコードに新しいアプリユーザーを作成します。
- Boxユーザーのトークンを取得してユーザー固有のAPIコールを実行します。
Create Platform App Users
ユーザーを検証する前に、関連付けられたBoxユーザーアカウントがOktaユーザーにない場合のために、そのアカウントを作成する方法が必要です。
ローカルアプリケーションディレクトリで、手順1で作成したserver.js
ファイルを読み込みます。
次のbox
オブジェクトをファイルに追加し、保存します。
const box = (() => {
const configJSON = JSON.parse(fs.readFileSync(path.resolve(__dirname, './config.json')));
const sdk = boxSDK.getPreconfiguredInstance(configJSON);
const client = sdk.getAppAuthClient('enterprise');
let oktaRecord = {};
let userId = '';
let userClient;
function validateUser(userInfo, res) {
// TODO: VALIDATE USER
}
function createUser(res) {
// TODO: CREATE USER
}
return {
validateUser,
createUser
};
})();
このオブジェクトはいくつかの項目を定義します:
- 構成: Box Node SDKの新しいインスタンスがインスタンス化され、多数の変数と共にオブジェクト関数で使用可能になります。
validateUser
関数: 関連付けられたOktaユーザーにBoxユーザーが存在するかどうかを検証するためのコードを保持します。createUser
関数: 関連付けられたOktaユーザーIDにバインドされる新しいBoxユーザーを作成します。
この構造を定義したら、// TODO: CREATE USER
セクションを以下のコードに置き換えます。
const spaceAmount = 1073741824; // ~ 1gb
client.enterprise.addAppUser(
this.oktaRecord.name,
{
space_amount: spaceAmount,
external_app_user_id: this.oktaRecord.sub
}
).then(appUser => {
res.send(`New user created: ${appUser.name}`);
});
このコードにより、新しいBox App Userが作成され、ユーザーオブジェクトのexternal_app_user_id
パラメータが一意のOktaユーザーIDに設定されます。これで、2つのユーザーレコード間のバインドが定義されます。
ローカルアプリケーションディレクトリで、手順1で作成した/src/main/java/com/box/sample/Application.java
ファイルを読み込みます。別のアプリケーション名を使用している場合は、同等のディレクトリを読み込みます。
public class Application
の定義内に、以下のメソッドを追加します。
static String validateUser(OidcUser user) throws IOException {
// TODO: VALIDATE USER
}
static String createUser(OidcUser user) {
// TODO: CREATE USER
}
これらのメソッドはBoxユーザーの検証と作成を処理します。各メソッドの詳細は以下のとおりです。
validateUser
: 関連付けられたOktaユーザーにBoxユーザーが存在するかどうかを検証するためのコードを保持します。createUser
: 関連付けられたOktaユーザーIDにバインドされる新しいBoxユーザーを作成します。
これらのメソッドを定義したら、# TODO: CREATE USER
を以下のコードに置き換えます。
String oktaName = (String) user.getAttributes().get("name");
Object oktaSub = user.getAttributes().get("sub");
CreateUserParams params = new CreateUserParams();
params.setExternalAppUserId((String) oktaSub);
BoxUser.Info createdUserInfo = BoxUser.createAppUser(api, oktaName, params);
return "New User Created: " + createdUserInfo.getName();
このコードにより、新しいBox App Userが作成され、ユーザーオブジェクトのexternal_app_user_id
パラメータが一意のOktaユーザーIDに設定されます。これで、2つのユーザーレコード間のバインドが定義されます。
ローカルアプリケーションディレクトリで、手順1で作成したserver.py
ファイルを読み込みます。
既存のコードのルート定義の下に、以下のBox
クラスオブジェクトを追加します。
# Box user class
class Box(object):
def __init__(self):
# Instantiate Box Client instance
auth = JWTAuth.from_settings_file('../config.json')
self.box_client = Client(auth)
# Validate if Box user exists
def validateUser(self, g):
# TODO: VALIDATE USER
# Create new Box user
def createUser(self, ouser):
# TODO: CREATE USER
このクラスで定義する内容は以下のとおりです。
init
: 初期化時に、Box Python SDKの新しいインスタンスがインスタンス化され、オブジェクトのメソッドで使用可能になります。validateUser
メソッド: ユーザーオブジェクトを入力として受け取り、関連付けられたOktaユーザーにBoxユーザーが存在するかどうかを検証するためのコードを保持します。createUser
メソッド: ユーザーオブジェクトを入力として受け取り、関連付けられたOktaユーザーIDにバインドされる新しいBoxユーザーを作成します。
このクラスを定義したら、# TODO: CREATE USER
セクションを以下のコードに置き換えます。
user_name = f'{ouser.profile.firstName} {ouser.profile.lastName}'
uid = ouser.id
space = 1073741824
user = self.box_client.create_user(user_name, None, space_amount=space, external_app_user_id=uid)
return f'New user created: {user_name}'
このコードにより、新しいBox App Userが作成され、ユーザーオブジェクトのexternal_app_user_id
パラメータが一意のOktaユーザーIDに設定されます。これで、2つのユーザーレコード間のバインドが定義されます。
Controllers
> AccountController.cs
ファイル内で、関連付けられたAccountController
クラスの中に以下のメソッドを追加します。
static async Task validateUser(string name, string sub)
{
// Configure Box SDK instance
var reader = new StreamReader("config.json");
var json = reader.ReadToEnd();
var config = BoxConfig.CreateFromJsonString(json);
var sdk = new BoxJWTAuth(config);
var token = sdk.AdminToken();
BoxClient client = sdk.AdminClient(token);
// Search for matching Box app user for Okta ID
BoxCollection<BoxUser> users = await client.UsersManager.GetEnterpriseUsersAsync(externalAppUserId:sub);
System.Diagnostics.Debug.WriteLine(users.TotalCount);
if (users.TotalCount > 0)
{
// TODO: VALIDATE USER
}
else
{
// TODO: CREATE USER
}
}
このコードブロック内では、手順2でダウンロードしたconfig.json
ファイルを使用して新しいBox .NET SDKクライアントが作成されます。このコードサンプルの場合、そのconfig.json
ファイルはローカルアプリケーションディレクトリのルートに格納されます。
その後、Oktaの一意のID sub
がexternalAppUserId
検索パラメータとして渡され、クライアントを使用して、Boxに登録されている会社内のすべてのユーザーが検索されます。その後、返されるユーザーの数を確認すると、有効なユーザーが検出されたかどうかがわかります。
この構造を定義したら、// TODO: CREATE USERセクションを以下のコードに置き換えます。
var userRequest = new BoxUserRequest()
{
Name = name,
ExternalAppUserId = sub,
IsPlatformAccessOnly = true
};
var user = await client.UsersManager.CreateEnterpriseUserAsync(userRequest);
System.Diagnostics.Debug.WriteLine("New user created: " + user.Name);
このコードにより、新しいBox App Userが作成され、ユーザーオブジェクトのexternal_app_user_id
パラメータが一意のOktaユーザーIDに設定されます。これで、2つのユーザーレコード間のバインドが定義されます。
その後、新しいユーザーが作成されたことを示す診断メッセージが書き戻されます。
Oktaユーザーの検証
ここまで、ユーザーを作成する機能を定義してきました。次に定義するコードでは、Boxを使用する会社の全ユーザーを検索して関連付けられたexternal_app_user_id
を探すことで、Oktaユーザーレコードに関連付けられたBoxユーザーレコードが存在するかどうかを検証します。
// TODO: VALIDATE USER
コメントを以下の内容に置き換えます。
this.oktaRecord = userInfo
client.enterprise.getUsers({ "external_app_user_id": this.oktaRecord.sub })
.then((result) => {
if (result.total_count > 0) {
// TODO: MAKE AUTHENTICATED USER CALL
} else {
// User not found - create user
this.createUser();
}
});
Box Node SDKを使用した場合、enterprise.getUsers
を呼び出して会社の全ユーザーを検索し、一意のOktaユーザーIDをexternal_app_user_id
値として渡すことで、そのユーザーに特化した検索を行います。
見つかった場合 (つまり、レコードの数が1以上だった場合) は、そのユーザーレコードを使用して、Box APIに対して認証済みの呼び出しを実行できます。これは次のセクションで定義します。
見つからなかった場合は、1つ前のセクションで定義したcreateUser
関数を呼び出して、そのexternal_app_user_id
と関連付けられた新しいBoxユーザーを作成します。
// TODO: VALIDATE USER
コメントを以下の内容に置き換えます。
// Set up Box enterprise client
Reader reader = new FileReader("config.json");
BoxConfig config = BoxConfig.readFrom(reader);
api = BoxDeveloperEditionAPIConnection.getAppEnterpriseConnection(config);
// Get Okta user sub for unique ID attachment to Box user
Object oktaSub = user.getAttributes().get("sub");
// Check enterprise users for matching external_app_user_id against Okta sub
URL url = new URL("https://api.box.com/2.0/users?external_app_user_id=" + oktaSub);
BoxAPIRequest request = new BoxAPIRequest(api, url, "GET");
BoxJSONResponse jsonResponse = (BoxJSONResponse) request.send();
JsonObject jsonObj = jsonResponse.getJsonObject();
JsonValue totalCount = jsonObj.get("total_count");
// Set return string
String outputString = "";
if (totalCount.asInt() > 0) {
// TODO: MAKE AUTHENTICATED USER CALL
} else {
outputString = createUser(user);
}
return outputString;
Box Java SDKの汎用リクエストメソッドを使用した場合、https://api.box.com/2.0/users
エンドポイントを直接呼び出して会社のユーザーを検索し、一意のOktaユーザーIDをexternal_app_user_id
値として渡すことで、そのユーザーに特化した検索を行います。
見つかった場合 (つまり、レコードの数が1以上だった場合) は、そのユーザーレコードを使用して、Box APIに対して認証済みの呼び出しを実行できます。これは次のセクションで定義します。
見つからなかった場合は、1つ前のセクションで定義したcreateUser
関数を呼び出して、そのexternal_app_user_id
と関連付けられた新しいBoxユーザーを作成します。
# TODO: VALIDATE USER
コメントを以下の内容に置き換えます。
# Fetch Okta user ID
uid = g.user.id
# Validate is user exists
url = f'https://api.box.com/2.0/users?external_app_user_id={uid}'
response = self.box_client.make_request('GET', url)
user_info = response.json()
# If user not found, create user, otherwise fetch user token
if (user_info['total_count'] == 0):
self.createUser(g.user)
else:
# TODO: MAKE AUTHENTICATED USER CALL
Box Python SDKの汎用リクエストメソッドを使用した場合、https://api.box.com/2.0/users
エンドポイントを直接呼び出して会社のユーザーを検索し、一意のOktaユーザーIDをexternal_app_user_id
値として渡すことで、そ のユーザーに特化した検索を行います。
見つかった場合 (つまり、レコードの数が1以上だった場合) は、そのユーザーレコードを使用して、Box APIに対して認証済みの呼び出しを実行できます。これは次のセクションで定義します。
見つからなかった場合は、1つ前のセクションで定義したcreateUser
関数を呼び出して、そのexternal_app_user_id
と関連付けられた新しいBoxユーザーを作成します。
// TODO: VALIDATE USER
コメントを以下の内容に置き換えます。
var userId = users.Entries[0].Id;
var userToken = sdk.UserToken(userId);
BoxClient userClient = sdk.UserClient(userToken, userId);
// TODO: MAKE AUTHENTICATED USER CALL
有効なユーザーが見つかった場合、Box IDが抽出されます。このIDは、アプリケーションではなく明確にそのユーザーのスコープに設定されたBox SDKクライアントの生成に使用されます。
認証済みのBoxユーザーの呼び出し
Oktaユーザーの関連付けられたBoxユーザーが検出されたら、明確にそのユーザーのスコープに設定されたアクセストークンを生成してBox APIコールを実行します。その後、現在のユーザーを取得するための呼び出しを実行して、すべてが機能していることと有効なユーザーアクセストークンがあることを確認します。
1つ前のセクションの// TODO: MAKE AUTHENTICATED USER CALL
を次の内容に置き換えます。
this.userId = result.entries[0].id;
this.userClient = sdk.getAppAuthClient('user', this.userId);
this.userClient.users.get(this.userClient.CURRENT_USER_ID)
.then(currentUser => {
res.send(`Hello ${currentUser.name}`);
});
見つかったユーザーのBoxユーザーIDをキャプチャし、そのユーザーのスコープに設定されたユーザークライアントオブジェクトを生成します。最後に、このユーザークライアントオブジェクトを使 用して現在のユーザーを取得する呼び出しを実行すると、Oktaに関連付けられたBox App Userのユーザープロフィール情報が返されます。
1つ前のセクションの// TODO: MAKE AUTHENTICATED USER CALL
を次の内容に置き換えます。
// User found, authenticate as user
// Fetch user ID
JsonArray entries = (JsonArray) jsonObj.get("entries");
JsonObject userRecord = (JsonObject) entries.get(0);
JsonValue userId = userRecord.get("id");
// Get user scoped access token and fetch current user with it
BoxDeveloperEditionAPIConnection userApi = BoxDeveloperEditionAPIConnection.getAppUserConnection(userId.asString(), config);
BoxUser currentUser = BoxUser.getCurrentUser(userApi);
BoxUser.Info currentUserInfo = currentUser.getInfo();
outputString = "Hello " + currentUserInfo.getName();
見つかったユーザーのBoxユーザーIDをキャプチャし、そのユーザーのスコープに設定されたユーザークライアントオブジェクトを生成します。最後に、このユーザークライアントオブジェクトを使用して現在のユーザーを取得する呼び出しを実行すると、Oktaに関連付けられたBox App Userのユーザープロフィール情報が返されます。
1つ前のセクションの# TODO: MAKE AUTHENTICATED USER CALL
を次の内容に置き換えます。
# Create user client based on discovered user
user = user_info['entries'][0]
user_to_impersonate = self.box_client.user(user_id=user['id'])
user_client = self.box_client.as_user(user_to_impersonate)
# Get current user
current_user = user_client.user().get()
return f'Hello {current_user.name}'
見つかったユーザーのBoxユーザーIDをキャプチャし、そのユーザーのスコープに設定されたユーザークライアントオブジェクトを生成します。最後に、このユーザークライアントオブジェクトを使用して現在のユーザーを取得する呼び出しを実行すると、Oktaに関連付けられたBox App Userのユーザープロフィール情報が返されます。
1つ前のセクションの// TODO: MAKE AUTHENTICATED USER CALL
を次の内容に置き換えます。
BoxUser currentUser = await userClient.UsersManager.GetCurrentUserInformationAsync();
System.Diagnostics.Debug.WriteLine("Current user name: " + currentUser.Name);
このユーザーのスコープに設定されたクライアントを使用すると、Boxから現在のユーザーレコードが抽出され、現在のユーザー名を含む診断メッセージが書き戻されます。
まとめ
- OktaユーザーがBoxユーザーとして存在するかどうかを検証しました。
- 存在しない場合は新しいアプリユーザーを作成しました。
- 既存のBoxユーザーに対してBox APIコールを実行しました。