rono23

Appleでサインインのトークン検証

セットアップ

# Gemfile
gem "jwt"

# クライアントから送られてきたパラメータ
token = "identityToken"
code = "authorizationCode"

署名検証

url = "https://appleid.apple.com/auth/keys"
jwks = JSON.parse(open(url).read, symbolize_names: true)
algorithms = jwks[:keys].map { |key| key[:alg] } # or tokenのHeaderの:alg
decoded_token = JWT.decode(token, nil, true, algorithms: algorithms, jwks: jwks).first.with_indifferent_access

# 1つのJWKだけ検証したいとき
jwk = jwks[:keys].first
public_key = JWT::JWK.import(jwk).keypair.public_key # or `JWT::JWK::RSA.import(jwk).public_key`
JWT.decode(token, public_key, true, algorithm: "RS256")

# 期限は10分なので注意
JWT.decode(...) #=> JWT::ExpiredSignature: Signature has expired

authorizationCodeの検証

# https://openid.net/specs/openid-connect-core-1_0.html#CodeValidation
digest = Digest::SHA256.digest(code)
c_hash = Base64.urlsafe_encode64(digest[0, digest.size/2], padding: false)
decoded_token[:c_hash] == c_hash

nonceの検証

クライアントの実装はfirebase/quickstart-iosが参考になるかも。
iOS 13からCryptoKitが導入されたので、quickstart-ios的なnonceの生成は以下みたいな感じでもOKかな 🤔

# クライアント
import CryptoKit

let uuid = CFUUIDCreateString(nil, CFUUIDCreate(nil))!
let rawNonce = NSString(string: uuid).replacingOccurrences(of: "-", with: "")
let data = rawNonce.data(using: .utf8)!
request.nonce = SHA256.hash(data: data).compactMap { String(format: "%02x", $0) }.joined()

# サーバー
decoded_token[:nonce] == Digest::SHA256.hexdigest(rawNonce)

iOS 12以下をサポートしている場合、weak linkする必要があるので忘れずに。

Targets > APP > Build Settings > Other Linker Flags に -weak_framework CryptoKit を追加

リンク


➡️ Appleでサインインのアクセストークンとリフレッシュトークンの取得に続く

Post a comment on GitHub