Freika/dawarich · error · Auth::VerifyAppleToken::InvalidToken
blank token
Error message
blank token
What it means
Auth::VerifyAppleToken raises InvalidToken 'blank token' when the id_token argument is nil or empty before any Apple library call happens. This is a fail-fast precondition: the Sign in with Apple flow always returns a credential containing an id_token (JWT), so a blank one means the client never completed the Apple handshake or the server-side code read the wrong parameter key.
Source
Thrown at app/services/auth/verify_apple_token.rb:14
# frozen_string_literal: true
module Auth
class VerifyAppleToken
class InvalidToken < StandardError; end
def initialize(id_token, nonce: nil, client_id: nil)
@id_token = id_token
@nonce = nonce
@client_id = client_id
end
def call
raise InvalidToken, 'blank token' if @id_token.blank?
raise InvalidToken, 'client_id not configured' if effective_client_id.blank?
decoded = AppleID::IdToken.decode(@id_token)
verify_args = { client: effective_client_id }
verify_args[:nonce] = expected_nonce_hash if @nonce.present?
decoded.verify!(**verify_args)
log_missing_nonce_breadcrumb if @nonce.blank?
{
sub: decoded.sub,
email: decoded.email,
email_verified: decoded.email_verified?,
is_private_email: decoded.is_private_email?
}
rescue AppleID::IdToken::VerificationFailed, JSON::JWT::Exception => e
raise InvalidToken, e.messageView on GitHub (pinned to 97fad417c5)
Solutions
- Confirm the client actually obtained an Apple credential and is sending its identityToken/id_token in the request
- Check the controller passes the correct param key to VerifyAppleToken.new(params[:id_token], ...)
- If the client only has an authorization code, exchange it for tokens first - the code itself is not an id_token
- Ensure the request body content-type matches what the controller parses
Example fix
# before Auth::VerifyAppleToken.new(params[:access_token]).call # wrong token type, often blank # after Auth::VerifyAppleToken.new(params[:id_token]).call # Apple's identity token (JWT)
Defensive patterns
Strategy: validation
Validate before calling
def apple_id_token_present?(params) params[:id_token].present? end # return a 400 with a clear message before entering the OAuth flow when false
Try / catch
begin
result = Auth::VerifyAppleToken.new(id_token, nonce:, client_id:).call
rescue Auth::VerifyAppleToken::InvalidToken => e
render json: { error: e.message }, status: :unauthorized
end Prevention
- Assert the client completed Apple's credential flow and is sending identityToken under the agreed param name
- Do not conflate Apple's authorization code with the id_token - only the latter works here
- Distinguish precondition failures (blank token) from verification failures in logs; they have different fixes
When it happens
Trigger: Apple OAuth callback where params[:id_token] (or the controller's chosen key) is absent - e.g. the mobile/web client sent only an authorization code, the credential was serialized under a different field name, or a user hit the endpoint directly without going through Apple first.
Common situations: Client confusion between Apple's authorization code flow and id_token flow (code needs a different exchange endpoint before any token exists), frontends sending credential/identityToken under a mismatched param name, POST body parsing dropping the token (form-encoded vs JSON mismatch), Apple returning an error the caller ignored before POSTing.
Related errors
AI-assisted analysis of Freika/dawarich@97fad417c5 (2026-08-21).
Data as JSON: /api/errors/8e5754c04ee8fddd.
Report an issue: GitHub.