【Auth0】SAML + AWS SDK for JavaScriptを使って静的HTMLからS3へファイルアップロードを試してみた

【Auth0】SAML + AWS SDK for JavaScriptを使って静的HTMLからS3へファイルアップロードを試してみた

Clock Icon2017.04.11

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは植木和樹@上越妙高オフィスです。本日はGmailで認証したユーザーがS3にファイルアップロードできるスタティックHTMLなアプリケーションを作成してみました。

以前のブログではAWSが公開しているFacebook認証による静的HTMLのサンプルを写経しました。今回はそれをベースにしつつ、Gmailでの認証にはAuth0を利用してみました。

参考ページ

今回は下記のページを参考にページを作成しました。

GoogleでAuth0 AWS JavaScriptで検索するとたくさんのページが表示されます。しかし情報が古いページがいくつかあり、そのまま試してもうまくいかないケースが見つけられました。

  • getProfileはAuth0 API v8以降obsoleteなので、getUserProfileを使う
  • 上記に関連してidTokenの取得方法が変わっている(lock.on("authenticated")のイベントハンドラを利用する)
  • getDelegationToken の引数としてRole ARN, ID Provider ARNを指定するのではなく、ClientのAWS Addonsを有効にして、RulesでARNを指定する

が主に異なる点です。

また上記 Amazon API Gateway Tutorial Introduction ではページ作成にAngularJS(v1.3.0)を利用しており、動作確認のサンプルとしてやや難解でした。そのため今回は2ファイル(HTML本体+設定用JavaScriptファイル)で動作確認できるページを用意しました。

設定とサンプルコード

動作には下記のものが必要になります

  1. Auth0の設定(Client, Connection, Rule)
  2. AWSのリソース(IAM Role, ID Provider, ファイルアップロード先のS3バケット)
  3. AWS SDK for JavaScriptを組み込んだHTMLファイル

まずは前回のAWS SDK for JavaScriptのGetting Startedを写経して静的HTMLからS3へファイルアップロードを試してみた | Developers.IOと共通点も多いため、前回のブログを参考にS3バケット等を用意しておくと良いでしょう。

1. Auth0の設定

Amazon API Gateway Tutorial - Step 2 - Adding Security and Deployingを参考にClientsConnectionsRulesを作成します。

Client設定はほぼ初期設定のままです。Allowed Callback URLsにはS3にアップロードしたsample.htmlのURLを設定してください。

20170411_auth0_aws_001

ページで紹介されている通りAmazon Web Services Addonを有効にしておきましょう。これによりAuth0LockインスタンスのgetDelegationTokenメソッドで、idTokenからAWSのアクセスキー、シークレットアクセスキー、セッショントークンへの変換を行ってくれます。

20170411_auth0_aws_003

Connectionsは認証に利用するID Providerを指定します。今回はGoogle Appsを指定しました。

20170411_auth0_aws_002

Ruleでは利用するAWS側のIAM RoleとID Providerのマッピングを設定します。コードはこの後にご紹介します。

2. AWSのリソース

Setup AWS for Delegated Authentication with APIs を参考にIAM RoleとID Provider設定を行います。

20170411_auth0_aws_006

20170411_auth0_aws_007

3. AWS SDK for JavaScriptを組み込んだHTMLファイル

サンプルコードは gist にあげました。

auth0_ruleに記載したJavaScriptコードはAuth0のRuleに貼り付けます。。AUTH0_CLIENT_IDには作成したClientのClient IDを入力し、特定Clientでのみ適用されるようにします。またprincipalroleのARNを作成したID ProviderとIAM RoleのARNに修正してください。修正したら適当な名前で保存します。

アプリケーションの各種設定値は config.js にまとめていますので環境にあわせて修正してください。

function (user, context, callback) {
if (context.clientID === 'AUTH0_CLIENT_ID') {
// set AWS settings
context.addonConfiguration = context.addonConfiguration || {};
context.addonConfiguration.aws = context.addonConfiguration.aws || {};
context.addonConfiguration.aws.principal = 'arn:aws:iam::123456789012:saml-provider/auth0-test';
context.addonConfiguration.aws.role = 'arn:aws:iam::123456789012:role/cm-js-sample-role@auth0';
}
callback(null, user, context);
}
view raw auth0_rule hosted with ❤ by GitHub
window.config = {
client_id: 'AUTH0_CLIENT_ID',
domain: 'YOUR_DOMAIN.auth0.com',
bucket: 'YOUR_UPLOAD_BUCKET',
region: 'ap-northeast-1'
};
view raw config.js hosted with ❤ by GitHub
<!DOCTYPE html>
<html>
<head>
<title>AWS SDK for JavaScript - Sample Application</title>
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js "></script>
<script src="https://cdn.auth0.com/js/lock/10.8/lock.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<script src="./config.js"></script>
</head>
<body>
<input type="file" id="file-chooser" />
<button id="upload-button" style="display:none">Upload to S3</button>
<div id="results"></div>
<div id="fb-root"></div>
<script type="text/javascript">
var lock = new Auth0Lock(window.config.client_id, window.config.domain);
var bucketName = window.config.bucket;
AWS.config.region = window.config.region;
var auth0UserId;
var bucket = new AWS.S3({
params: {
Bucket: bucketName
}
});
var fileChooser = document.getElementById('file-chooser');
var button = document.getElementById('upload-button');
var results = document.getElementById('results');
button.addEventListener('click', function () {
var file = fileChooser.files[0];
if (file) {
results.innerHTML = '';
//Object key will be auth0-USERID#/FILE_NAME
var objKey = 'auth0-' + auth0UserId + '/' + file.name;
var params = {
Key: objKey,
ContentType: file.type,
Body: file,
ACL: 'public-read'
};
bucket.putObject(params, function (err, data) {
if (err) {
results.innerHTML = 'ERROR: ' + err;
} else {
listObjs();
}
});
} else {
results.innerHTML = 'Nothing to upload.';
}
}, false);
function listObjs() {
var prefix = 'auth0-' + auth0UserId;
bucket.listObjects({
Prefix: prefix
}, function (err, data) {
if (err) {
results.innerHTML = 'ERROR: ' + err;
} else {
var objKeys = "";
data.Contents.forEach(function (obj) {
objKeys += obj.Key + "<br>";
});
results.innerHTML = objKeys;
}
});
};
lock.on("authenticated", function(authResult) {
console.log("authResult: " + JSON.stringify(authResult));
lock.getUserInfo(authResult.accessToken, function(error, profile) {
if (error) {
console.log('Error loading the Profile', error)
return;
}
console.log("Profile:" + JSON.stringify(profile));
auth0UserId = profile.nickname;
var auth0 = new Auth0({
clientID: window.config.client_id,
domain: window.config.domain,
callbackURL: 'dummy'
});
var aws_creds;
var options = {
id_token: authResult.idToken,
api: 'aws'
};
auth0.getDelegationToken(options, function(err, result) {
if (err) {
console.log(err);
return;
}
aws_creds = result.Credentials; // AWS temp credentials
console.log("aws_creds: " + JSON.stringify(aws_creds));
bucket.config.credentials = new AWS.Credentials({
accessKeyId: aws_creds.AccessKeyId,
secretAccessKey: aws_creds.SecretAccessKey,
sessionToken: aws_creds.SessionToken});
});
button.style.display = 'block';
});
});
(function () {
if (location.hash == '') {
lock.show();
}
}());
</script>
</body>
</html>
view raw sample.html hosted with ❤ by GitHub

sample.htmlとconfig.jsの2つのファイルをStatic Webhosting設定したS3バケットにアップロードしブラウザでアクセスしてください。Auth0による認証画面が表示されます。

20170411_auth0_aws_004

認証後に、適当なファイルをアップロードしファイル名が画面に表示されれば成功です。

20170411_auth0_aws_005

まとめ

今回はAWS SDK for JavaScriptを使ってS3バケットへのアップロードを行いました。Gmailで認証+静的HTMLなアプリケーションだとこんな点でうれしいことがあります。

  • AWS利用者毎にIAMユーザーを作成する必要がない
  • ユーザー認証をGmail(GSuite)に任せることができる(会社ドメインのメールアドレスを持っていれば利用可能など)
  • 静的HTMLなのでEC2等でサーバーを用意する必要がない
  • AWSに不慣れな人にも機能を限定した画面を用意して簡単に操作してもらえる

つまりAWSに詳しくない管理部の人でも簡単にS3へファイルをアップロードできるアプリケーションが作れます。また応用すればAPIが公開されている各種サービスについても静的HTMLだけでカスタム管理画面が作れそうですね。

なによりHTML + JavaScriptファイルだけで作れるのでサーバーを用意しなくて良く、運用の手間が減るのがうれしいです。Auth0のようなIdPサービスを使うことで、認証まで含めたアプリケーションを簡単にサーバーレスで利用するのが主流になりそうですね。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.