3-legged OAuth と言うと、Web サーバーでコールバック URL を実装するのが一般的と思いますが、クラウアントとの直接コミュニケーションを目指した Design Automation API の WebSocket API では、少し矛盾があるように感じてしまいます。そこで、前回のブログ記事で「Implicit Grant も含め」としたのは、Web サーバー実装を伴う動的 Web ページではなく、静的 Web ページでの利用を意識したためです。
常に同じコンテンツを配信することになる静的 Web ページ、極端な例えと思いますが、クラウド ストレージでパブリック共有してしまうと、Web ページの配信が出来てしまいます。ただ、クラウド ストレージ サービスの制限で、スクリプトを含む可能性のある HTML ファイルの共有やプレビューが制限されてしまい、すぐにテストが出来ないかと思います。
VS Code でフォルダを開いて静的 Web ページを選択後、マウスの右クリックで「Open with Live Server」を選択すると、ローカル コンピュータで既定のポート番号 5500 を利用したページのテストが出来るようになります。
次のような HTML ページ(index.html)を用意して、Forge アプリの Callback URL を http://localhost:5500 しておけば、Das.WorkitemSigner ツールで署名した Activity と 3-legged OAuth で、WebSocket による WorkItwm の起動と通知をテストすることが出来ます。
<html>
<head>
<title>DA4A WebSocket Test</title>
<link type="text/css" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
</head>
<body onload="MyStuff.onLoad()">
<script>
var MyStuff = {
"SOCKET": "",
"access_token": "",
"LogIn": ["Log In", "Logged In"],
"onLoad": function () {
console.log("onLoad")
var url = new URL(window.location.href.replace('#', '?'))
var query_string = url.search
var search_params = new URLSearchParams(query_string)
MyStuff.access_token = search_params.get('access_token')
let logInButton = document.getElementById("LogIn")
logInButton.innerText = (MyStuff.access_token) ? MyStuff.LogIn[1] : MyStuff.LogIn[0]
console.log(MyStuff.access_token)
},
"getUserInfo": function () {
console.log("getUserInfo")
if (MyStuff.access_token === "")
return
fetch('https://developer.api.autodesk.com/userprofile/v1/users/@me', {
headers: {
'Authorization': `Bearer ${MyStuff.access_token}`
}
})
.then(res => res.text())
.then(data => {
let json = JSON.parse(data)
let pretty = JSON.stringify(json, null, 2)
MyStuff.showInfo(pretty)
console.log(data)
})
},
"logIn": function () {
console.log("logIn")
let clientId = <Client Id>
let scopes = "code:all"
let redirectUri = encodeURI("http://localhost:5500")
window.open(`https://developer.api.autodesk.com/authentication/v1/authorize` +
`?response_type=token&client_id=${clientId}&redirect_uri=${redirectUri}&scope=${scopes}`, "_self")
},
"doit": function () {
var msg = JSON.stringify(
{
"action": "post-workitem",
"data":
{
"activityId": "Autodesk_Japan.Hello+dev",
"signatures": {
"activityId": <署名済 Activity Id>
}
},
"headers":
{
"Authorization": "Bearer " + MyStuff.access_token
}
})
console.log(msg)
SOCKET.send(msg)
SOCKET.onmessage = function (event) {
console.log("通知" + event.data)
$("#message").text(event.data)
}
SOCKET.onerror = function (error) {
console.log("エラー" + error.data)
$("#message").text(error.data)
}
},
"connect": function () {
SOCKET = new WebSocket('wss://websockets.forgedesignautomation.io')
SOCKET.onopen = function (event) {
console.log("接続" + event.data)
$("#message").text("接続")
}
},
"disconnect": function () {
SOCKET.close()
SOCKET.onclose = function () {
console.log("切断")
$("#message").text("切断")
}
}
}
</script>
<button id="LogIn" class="btn btn-outline-primary ml-3 my-2" onclick="MyStuff.logIn()">Log In</button>
<p></p>
<button id="connect" class="btn btn-outline-dark ml-3 my-2" onclick="MyStuff.connect()">WebSocket 接続</button>
<button id="doit" class="btn btn-outline-dark ml-3 my-2" onclick="MyStuff.doit()">WorkItem 実行</button>
<button id="disconnect" class="btn btn-outline-dark ml-3 my-2" onclick="MyStuff.disconnect()">WebSocket 切断</button>
<p></p>
<label id="message" class="ml-3 my-2" style="width:90%"></label>
</div>
</body>
</html>
実際の Forge アプリは、Forge Viewer や他のサーバー実装を使った動的 Web ページを利用することが多いので、あまり利用する機会はないかもしれませんが、知っておくと便利です。
コメント
コメントフィードを購読すればディスカッションを追いかけることができます。