プログラマーのメモ書き

伊勢在住のプログラマーが気になることを気ままにメモったブログです

Cognito ユーザープールのトークンと保管場所について

Cognito ユーザープール、なかなか便利そうですね。

blog.mori-soft.com

上記を元に、いろいろと試してみて、気づいたことがいくつかあったのでまとめておきます。

更新トークンの有効期限

ユーザープールで認証をした際にはトークンが3種類発行されます。

docs.aws.amazon.com

そのうちの更新トークン(リフレッシュトークン)の有効期限は、ユーザープール作成時に指定できるのですがデフォルトだと30日になります。

ユーザープールのトークンの使用 - Amazon Cognito

もし、変更したい場合は、Cognito ユーザープール のコンソールを開いて、『アプリクライアント』->『詳細を表示』とすると

f:id:junichim:20180817224001p:plain

『トークンの有効期限を更新(日)』とあるので、ここで適切な日数に変更できます。

ブラウザのストレージ

また、ユーザープールで認証した際に、これらのトークンはローカルストレージに保存されるようです。なので、明示的にログアウトせず、ブラウザを落としただけだと、更新トークンが活きていて、簡単にセッションを貼りなおせるという問題があるそうです。

qiita.com

これへの対策として、トークンをセッションストレージに保存する、というのがあるようです。

確かめてみましょう。 ブラウザ(ここでは Firefox を使いました)で一度Cognito ユーザープールを使ったアプリにログインして、ローカルストレージを見ると

f:id:junichim:20180817225836p:plain

のようにローカルストレージに各種トークンが保存されていることがわかります。 ログアウトせずに一旦ブラウザを落として、再度同じサイト(ここでは http://localhost:9000 )にアクセスすると、ログイン前なのに上記と同じトークンの値が存在しているのを確認できました(画像貼っても同じなので省略しました)。

これだと、更新トークン(デフォルトで有効期限が30日)を使えば、IDトークン、アクセストークンの再取得ができちゃいますね(処理書く必要はありますが)。

ということで、ブラウザ側でユーザープールにアクセスする際に、

morisoftsample.poolData = {
    UserPoolId: 'ap-northeast-1_xxxxxxxxxxxxxx',
    ClientId: 'yyyyyyyyyyyyyyyyyyyyyyy',
    Storage: sessionStorage
};
morisoftsample.UserPool = new AmazonCognitoIdentity.CognitoUserPool(morisoftsample.poolData);

のようにしたら、セッションストレージに保存されるとのことです。

こちらも試してみます。

f:id:junichim:20180817230406p:plain

今度はセッションストレージに格納されていることが分かります。 このままログアウトせずに、一度ブラウザを落として、再度立ち上げると、

f:id:junichim:20180817230547p:plain

のように、きれいに消えてなくなっています。

これだと少しは安心ですね。

Cognito ユーザープール : メールアドレスの変更と確認について

Cognito ユーザープール、少しづつですが使ってみています。

今回はメールアドレスの変更をやってみました。基本的には、ドキュメントにある通り処理をすればOKです。

メールアドレスも属性の一つなので、属性の更新を行えば更新できます。 ただ、同じページのサンプルに『属性の確認』というのがあります。

言葉からすると、きっとメールアドレスを変更した場合はこれで再度確認をしないといけないんだろうな、と想像がつきます。が、いまひとつよくわかりません。 なので、いろいろと試した結果を、自分用のメモとしてまとめておきます。

前提

いま試しているユーザープールの設定は、

  • エイリアスは指定していない
  • ログインは、ユーザー名のみを許可
  • 属性として、 メールアドレス、preferred_username を追加

となっています。このあたりの設定が異なると、以下の挙動も違うかもしれませんのでご注意ください(特に確認していません)。

メールアドレスの変更で起きること

まず試しにメールアドレスを変更してみます。 変更前は、こんな感じだったのが、

f:id:junichim:20180817084816p:plain

メールアドレスを変更すると、こんな感じになりました(属性の確認は未実施)。

f:id:junichim:20180817084917p:plain

  • アカウントそのものは CONFIRMED の状態のまま
  • email_verified のステータスが false となる
  • アカウントに対するメールアドレスは変更済み(黒塗りでわからないですが、変わってます)

つまり、確認され有効なアカウントに対して、メールアドレスを変更すると、メールアドレスの確認が取れていないが、登録メールアドレスそのものは変更されている、という状態になります。 また、メールアドレスの変更時は、存在しないメールアドレスや別のアカウントで使っている重複するメールアドレスを指定しても変更ができました。なお、重複するメールアドレスの扱いはエイリアス指定があるときっと挙動が変わってくると推測されるところです。

この状態(メールアドレスだけ変更して、属性の確認は未実施)だと、なにができてできないかを調べたところ

  • ログイン:できる
  • パスワードのリセット:できない
  • メールアドレスの再変更:できる

となりました。登録メールアドレスが未確認の状態でも、パスワードでログイン等をする分には問題ないようです。 また、間違ったメールアドレスを入力してしまった、という場合でも、再度メールアドレスの変更ができるのでなんとかなるようです。

ということで、この状態でこまるのが、パスワードのリセットですね。 下記の記事にも、困ってしまった話が載っていました。

wp-kyoto.net

メールアドレスの確認

では、ということで、『属性の確認』を行えば、メールアドレスの確認ができるのだろうと考え、メールアドレスの確認処理を実装してみました。 となるのですが、公式のサンプルがちょっとわかりにくかったので、少し自分で修正してみました。

公式のサンプルだと、確認コードの取得(登録メールアドレスに送信)と確認コードの検証が一緒になったサンプルになっているようです。 なので、

morisoftsample.getAttributeVerificationCode = function(cognitouser) {
    return new Promise(function(resolve, reject) {
        cognitouser.getAttributeVerificationCode('email', {
            onSuccess: function(result) {
                console.log('success getAttributeVerificationCode');
                resolve(result);
            },
            onFailure: function(err) {
                console.log('failed getAttributeVerificationCode: ' + JSON.stringify(err));
                reject(err);
            }
        });
    });
}

という確認コードの取得(登録メールアドレスに送信)する関数と

morisoftsample.verifyAttribute = function(cognitouser, vericode) {
    return new Promise(function(resolve, reject) {
        cognitouser.verifyAttribute('email', vericode, {
            onSuccess: function(result){
                console.log('email verification success');
                resolve(result);
            },
            onFailure: function(err) {
                console.log('email verification failed');
                reject(err);
            }
        });
    });
}

という、取得した確認コードでメールアドレスをverifyする関数に分離してみました。 なお、上記のサンプルでは、それぞれの処理を Promise でラップしていますので、Promise を使わない場合は適当に読み替えてください。あと、cognitouser というのは、

で取得したログイン済みのユーザーになります。

この関数を呼び出すように、クライアント側のjavascriptを書くと、めでたく、確認コードの取得と確認コードのverifyを分けて扱うことができました。

ちなみに、Githubのリポジトリのほうのサンプルの Use Case 6 に少しだけ説明が載っていますので、ご参考までに。

github.com

はてなブログを https に対応しました (2/2)

はてなブログを https に対応させた話の続きです。

blog.mori-soft.com

Mixed Contents の修正

HTTPS Checker で Mixed Contest ありと指摘された ページを順次みていき、修正していきます。 自分のサイトの場合は、次のような点について修正しました。

はてなfotolifeの画像

幸い、はてなブログを使い始めたのが最近(2016/8頃、移行の顛末はこちら)だったためか、特に記事の更新をせずとも、https になっていました。 はてなブログへ移行時にインポートした記事も同様です。

これは助かりましたね。

埋め込みリンクの修正

他のサイトや自分の過去の記事にリンクを貼る際に、リンク先が http でかつ埋め込みでリンクを貼っていると、埋め込みが iframe のため、 Actice Mixed Contents として扱われます。

これは、地道に https に直していきます。この時、リンク先のサイトが https に対応していない場合は、URLが https のままとなるのは仕方ないので、埋め込みではなく『タイトル』等のリンク方法に変更します。

Tex 記法

テストサイトでは Tex記法 を含む記事は Passive Mixed Contents となっていました。 で、この Tex 記法を含む記事は、編集画面で更新をしてやると、Mixed Contents が解消されていました。

とはいうものの、テストサイトで、 Mixed Contents となっていたのですが、https 化した本ブログで記事が Mixed Contents か否かを確認する前に、 Tex 記法を含む記事を更新してしまったので、何もしない状態で Mixed Contents だったのかはいまとなってはわからないです。

まあ、少なくとも、記事の更新すれば問題なくなるとはいえるかもしれません。

にしても、確認忘れ、しまったなー。

dropxbox

この部分は、直接的には Mixed Contents とは無関係なのですが、一緒に作業したので備忘録として残しておきます。

はてなブログに移行した際の設定で、画像以外のファイルは、 dropbox から配信するようにしていました(こちらの記事を参照)。

今回、Mixed Contents の確認作業でたまたま気づいたのですが、 dropbox ってファイルをホスティングして公開する機能を廃止していたようです。

単にリンク先からファイルをダウンロードするだけなら今でも使えますが、html や javascript のコンテンツとして扱おうとするとできなくなっていました。

なので、これらのファイルをホストする場所を変更します。 どこがいいかな?と考えたのですが、いろいろと面倒がなさそうだということで、 S3 を使うことにします。

ということで、dropbox で公開していたコンテンツを S3 に移行します。 併せて、URL を dropbox のものから S3 のものに変更します。

なお、 S3 側の公開方法は ウェブサイトホスティングを使うのではなく、ファイルごとにパブリックアクセスを行うという方法をとることにします。

qiita.com

というのも、ウェブサイトホスティングにすると、CloudFront 経由の設定にしないと https でアクセスできなくなるためです。 ホストしているコンテンツもそんなに多くないので、そこまでしなくても、というのが本音です。

OpenLayers

本ブログ中で OpenLayers のサンプルについて書いたものがいくつかありました。 で、記事に埋め込む形で、実際に動作するサンプルを載せていました。 記事作成当時は、ライブラリ自体も http での配信だったので当然記事中でも https でURLを指定しています。

まずはこれを https で取得する必要があります。単純に http -> https でいけるかと思いきやダメでした。困ったなと思って調べていると、CDNで配信していることがわかりました。

ちょうど、記事作成当時、使っていた 2.13.1が配信されていたので、

cdnjs.com

こちらの一覧から、必要なライブラリのURLを取得して、それを指定します。

また、サンプルの js ファイルを dropbox から配信していたこともあり、前節のとおり、 https 化以前から動いていなかったようです。 そこで、必要な js ファイルを S3 から取得するように変更します。

最後に、タイルサーバーを指定します。OpenLayers (少なくともこのバージョン)では何も指定がなければ、デフォルトの openstreetmap.org のサーバーを http で使うようです。

gis.stackexchange.com

これについて、上記記事にかかれているように、

   map.addLayer(new OpenLayers.Layer.OSM(
            "OpenStreetMap", 
            // Official OSM tileset as protocol-independent URLs
            [
                '//a.tile.openstreetmap.org/${z}/${x}/${y}.png',
                '//b.tile.openstreetmap.org/${z}/${x}/${y}.png',
                '//c.tile.openstreetmap.org/${z}/${x}/${y}.png'
            ],
            null)
        );

のように、タイルサーバーを指定するようにしました。

その他

Mixed Contents とは少し違うのですが、 https 化の際に気になった点を書いておきます。

Slideshare

Slideshare については、CORS でエラーが出るようです。

とりあえず、対策はないようです。困りましたね。とりあえずは現状のままとしておきます。

はてなブログのログイン画面

こちらの記事に載っていたのですが、

https://atn.hateblo.jp/entry/2017/11/23/105121atn.hateblo.jp

はてなブログのログイン画面って、ブラウザの横幅を小さくしていくと、アドレスバーに注意のアイコンがつき、『この接続は安全ではありません」が表示されるようになります。 手元のFirefoxで試してみたら、見事に再現しました。

f:id:junichim:20180802105850p:plain

f:id:junichim:20180802105901p:plain

こんなこともあるんですね。なかなか https 化は難しいようです。

さいごに

一応、これで Mixed Contents も解消したはずです。とはいうものの HTTPS Checker で漏れなくチェックできているかちょっとわかりません。現に、 OpenLayers 関係の記事でチェックから漏れているものがいくつかありました。まあ、あとは問題を見つけ次第適宜修正するというのが良いのかな。

とりあえず一段落です。