しがないエンジニア頑張る

弱々だけどこの界隈でなんとか食らいついていきたい人

DockerでAmazon Linux2にEPELリポジトリ追加

このコマンドを追加すれば良い

sudo yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm

FROM amazonlinux:2

RUN yum update -y \
&& yum clean all \
&& sudo yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm

参考

Turn on EPEL repository for EC2 instances that run CentOS, RHEL, or Amazon Linux | AWS re:Post

offsetを提供しているAPIの裏側がDynamoDBだった時の絶望感

DynamoDBって言ってますが、DynamoDBに限った話ではないです。
よくAPIの設計でページングのためにlimit/offsetを提供することがあると思いますが、これを読んだ方に伝えたい。
その設計は次からやめましょう止めましょう。

is 何故

ページングのためにlimit/offsetをとるAPIはよく見ます。
一般的なRDBでは、OFFSET関数が提供されており、それを利用すれば簡単に実装できますしそれに依存したIFと言ってもいいでしょう。
でも、DynamoDBのようなキーバリューストアのみ場合は実現が困難なため避けましょう。

解決策

RDBを使う。

一番幸せになれます。
しかし、謎の力でDynamoDBから逃れられない時があると思います。
じゃあどうするかというと、、

別案

ロジックで頑張る

Lambdaなどと組み合わせてロジックで解決する。
多分これで解決することになると思います。私もそうでした。
もちろんQueryの利用を前提に、メモリ効率とかを考える必要はありますが。。

Athenaを使う

AthenaもOFFSET関数を提供しているんです。 要件によってはDynamoDBからS3にデータを置いてクエリをかけることで実現できます。
また、コネクタも提供されているのでこちらで直接クエリもかけられるんじゃないかなと思っています。(未検証) Amazon Athena DynamoDB コネクタ - Amazon Athena

IFを変える

limit/offsetの提供をやめちゃいましょう。
具体的には、トークンとページサイズを構えるIFにします。 そうすることで、OFFSET関数に依存したIFを隠蔽することができ、DynamoDBでも所謂カーソル処理的な感じで実現可能です。
ただし、以下のようなトレードオフもありますので注意しましょう。

  • 双方向ページングができない
  • 任意のページの要求に答えられない

この辺りの話は、この本が参考になります。 APIデザイン・パターン | マイナビブックス

クライアントクレデンシャルグラントのリフレッシュトークンについて

クライアントクレデンシャルグラントについて調べると、フローや用途は書かれてますがリフレッシュトークンについては「含めるべきではない。」とまでしか書いてないですよね。
なんで?って思うじゃないですか。それについての考察です。

結論(読むの面倒な人向け)

  • クライアントクレデンシャルグラントの特性上リフレッシュトークンを含めてもあんまり意味がないからだと思う
  • アクセストークン欲しかったら都度トークンエンドポイント叩けばいいんじゃね

クライアントクレデンシャルグラントとは

OAuth 2.0 全フローの図解と動画 - Qiita

素晴らしい記事を参考にして頂ければと思いますが、
アプリケーションに対して権限を委譲しリソースサーバーとやり取りする方式ですね。

認可コードグラントとクライアントクレデンシャルグラントの違い

認可エンドポイント トークンエンドポイント
認可コードグラント
クライアントクレデンシャルグラント ×

わざわざ表にする必要は置いておいて、
そう、クライアントクレデンシャルグラントは認可エンドポイントを必要としないんですね。
つまり、リソースオーナと認可サーバーとのやりとりがないのがポイントです。

リフレッシュトークンおさらい

RFC 6749: The OAuth 2.0 Authorization Framework

ここに書いてある通りなんですが、通常アクセストークンより長い生存期間を持ち、アクセストークンを再取得するために用いられるトークンです。

クライアントクレデンシャルグラントのリフレッシュトークンについて

では、クライアントクレデンシャルグラントでなぜリフレッシュトークンを含めるべきではないのか?
これは、クライアントクレデンシャルグラントの特性上含めてもあんまり意味がないからだと思います。
認可コードグラントではリソースオーナーとのやり取りがあり、リフレッシュトークンがまだ生きていればアプリの権限移譲の確認フローをやらなくても良くなりますね。ユーザ体験の向上とかに効果ありそうです。
クライアントクレデンシャルグラントの場合、アプリが直接権限をもらいに行きます。
そこには、認可コードグラントのような面倒なやり取りはありません。クレデンシャルを渡すだけです。
つまり、リフレッシュトークンを利用する旨味があまりなく、都度トークンエンドポイントを叩けばいいじゃんって感じですね。

まとめ

クライアントクレデンシャルグラントのリフレッシュトークンについてでした。
あんまり意味のなさそうなトークンの管理もしたくないし、トークンエンドポイントを連打しようぜって感じですね。

Q: アクセストークンはどこに保存したらいいですか?

A:保存する場所はどこでもいいです。完。

N番煎じの話題

この話題世の中に無限にありますよね。
ローカルストレージは危険なのでやめましょう!!!
ってのが無限に出てくるし、よく言われるわけですよ。
セキュリティに特別明るいわけじゃないですが(防衛魔法)、私もN番目のポエマーとして電子チラシの裏に書き込むことにしました。

XSSの前には人類は無力なんだよ

「アクセストークンをローカルストレージに保管するのはやめてください!」
強い口調で書かれている記事は無限にあるが、内容はXSSに対して無防備だからという内容。
確かに。わかる。でも人類はXSSされたら無力なので、どこにおこうと情報は漏洩します。
故に、どこでもいいんじゃね?って思うわけですよ。

解決策としてのCookie

「ローカルストレージに保管するのはやめてください!」マンが提示するのはCookieに入れましょう!ですね。
その他もありますが。大抵はこれ。
さらに、セキュアにするためにHttpOnlyとSecurityをつけましょう!までがセット。
確かに、アクセストークンは盗まれないかもだけど、XSSの前に無力なのは変わっていないので解決策じゃなくね?と思うわけですよ。
CSRF攻撃の可能性を広げているけど奴は四天王の中では最弱なのでヨシ。

XSSへの無力さ

ローカルストレージへ保存した場合、XSSによりアクセストークンがローカルストレージから取得されておしまい。
Cookieへ保存した場合した場合、XSSによりそのままリクエストされて情報が取得されておしまい。もちろんSameSiteも意味ないぞ。
なので、そもそもXSS対策頑張りましょうね!なんですよね。

Service Workerという選択肢

最近よく聞きますよね。
DOMと切り離されてるし、Cookieも使わなくて済む!!でもやはりXSSの前には無力。
やっぱり、どこでもいいんだね。

参考

Building secure web apps using Web Workers | Mercari Engineering