Skip to content

Instantly share code, notes, and snippets.

@yossy6954
Last active May 6, 2020 06:10
Show Gist options
  • Save yossy6954/f66205d3eeab16b4ba5d6961fdac4563 to your computer and use it in GitHub Desktop.
Save yossy6954/f66205d3eeab16b4ba5d6961fdac4563 to your computer and use it in GitHub Desktop.
JWT検証(Ruby on rails)
require 'open-uri'
class ApplicationController < ActionController::API
OPENID_CONFIGURATION_URL = '{your_openid_configuration_url}'
APPLICATION_ID = '{your_application_id}'
def initialize
openid_configuration = JSON.parse(open(OPENID_CONFIGURATION_URL).read)
@jwks ||= JSON.parse(open(openid_configuration['jwks_uri']).read)
end
def openssl_bn(n)
n = n + '=' * (4 - n.size % 4) if n.size % 4 != 0
decoded = Base64.urlsafe_decode64 n
unpacked = decoded.unpack('H*').first
OpenSSL::BN.new unpacked, 16
end
def public_key(jwk)
modulus = openssl_bn(jwk[0]['n'])
exponent = openssl_bn(jwk[0]['e'])
sequence = OpenSSL::ASN1::Sequence.new(
[OpenSSL::ASN1::Integer.new(modulus),
OpenSSL::ASN1::Integer.new(exponent)]
)
return OpenSSL::PKey::RSA.new(sequence.to_der)
end
def jwt_authenticate
unless jwt_bearer_token
render json: { errors: [ { message: 'Unauthorized' }]}, status: :unauthorized
return
end
unless jwt_decoded_token
render json: { errors: [ { message: 'Invalid token' } ] }, status: :unauthorized
return
end
end
def jwt_bearer_token
@jwt_bearer_token ||= if request.headers['Authorization'].present?
scheme, token = request.headers['Authorization'].split(' ')
(scheme == 'Bearer' ? token : nil)
end
end
def jwt_decoded_token
begin
# 一旦バリデーション無しでデコード
decode = JWT.decode(jwt_bearer_token, nil, false)
# audチェック
if decode[0]['aud'] != APPLICATION_ID then
raise JWT::VerificationError.new('Invalid aud')
end
# jwks から kid が一致するキーから public_key を生成
kid = decode[1]['kid']
jwk = @jwks['keys'].select {|key| key['kid'] == kid}
public_key = public_key(jwk)
# バリデーション有りでデコード
@jwt_decoded_token ||= JWT.decode(
jwt_bearer_token, public_key, true, algorithm: decode[1]['alg'])
# ペイロード部分のみ取り出し
@jwt_payload ||= @jwt_decoded_token[0]
rescue JWT::DecodeError, JWT::VerificationError, JWT::InvalidIatError => e
# エラーの詳細をクライアントには伝えないため、常に nil を返す
logger.error(e.message)
nil
end
end
end
class DebugController < ApplicationController
before_action :jwt_authenticate
def me
render :json => @jwt_payload
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment