JWT(+JWS)について調べた (JWTの検証)
前回、こちらでHMAC SHA256で署名したJWT(+JWS)を作成していきましたが、今回はその検証を行っていきます。
rfc7519
に検証手順があるので、それを参考にしつつ流れを確認しました。
- JWTをheader、payload、signatureに分割
- 分割したheader、payload、signatureをBASE64urlでデコード
- headerから署名アルゴリズムを確認する
- 確認した署名方法でJWTの検証を行なう
これに加えて有効期限の検証も行っていきます。
とにかくコードを書いていきます。 今回はコードの中で説明をしていく形になりますが、順番的にはこんな感じで検証していくのが良いかと思われます。
# -*- coding: utf-8 -*- require 'base64' require 'json' require 'openssl' jwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImV4cCI6MTU0MDY1MjQwMH0.a2xzydhHuo2UREDRIdcyKmlihl_1gl_BYCxdQEKmgTE' # JWTをheader、payload、signatureに分割 encoded_header, encoded_payload, encoded_signature = jwt.split('.') # 分割したheader、payload、signatureをBASE64urlでデコード decoded_header = Base64.urlsafe_decode64(encoded_header) # パディングがなくてもよしなにデコードしてくれる decoded_payload = Base64.urlsafe_decode64(encoded_payload) decoded_signature = Base64.urlsafe_decode64(encoded_signature) # headerから署名アルゴリズムを確認する # 今回は形式はJWTでHS256以外のものは対応しないので、それ以外は処理しないようにします header = JSON.parse(decoded_header) payload = JSON.parse(decoded_payload) unless header['typ'] == 'JWT' && header['alg'] == 'HS256' puts 'error: 対象外の形式です。' return end # 確認した署名方法でJWTの検証を行なう secret = 'secret' verification_signature = OpenSSL::HMAC.digest( OpenSSL::Digest::SHA256.new, secret, "#{encoded_header}.#{encoded_payload}" ) if decoded_signature != verification_signature puts 'error: 検証が失敗しました。' return end # 有効期限を設けていれば、その検証も行なう unless Time.now.to_i < payload['exp'] puts 'error: 有効期限が過ぎています。' return end puts '検証OK'