Skip to content

Instantly share code, notes, and snippets.

@styrken
Last active August 9, 2024 17:33
Show Gist options
  • Save styrken/78ca9e32e1227620700d5d2749458704 to your computer and use it in GitHub Desktop.
Save styrken/78ca9e32e1227620700d5d2749458704 to your computer and use it in GitHub Desktop.
class AppleSignInController < ApplicationController
APPLE_PEM_URL = "https://appleid.apple.com/auth/keys"
# /api/apple/validate
def validate
name = params[:name]
userIdentity = params[:userIdentity]
jwt = params[:jwt]
begin
header_segment = JSON.parse(Base64.decode64(jwt.split(".").first))
alg = header_segment["alg"]
kid = header_segment["kid"]
apple_response = Net::HTTP.get(URI.parse(APPLE_PEM_URL))
apple_certificate = JSON.parse(apple_response)
keyHash = ActiveSupport::HashWithIndifferentAccess.new(apple_certificate["keys"].select {|key| key["kid"] == kid}[0])
jwk = JWT::JWK.import(keyHash)
token_data = JWT.decode(jwt, jwk.public_key, true, {algorithm: alg})[0]
if token_data.has_key?("sub") && token_data.has_key?("email") && userIdentity == token_data["sub"]
puts "Name: " + name + " is validated."
# TODO: Create a user in ur rails app and generate an auth token for future requests. Remember to use the "userIdentity" as the
# primary user key - this because the email address will change all the time
# TODO: Render response to app
else
# TODO: Render error to app
end
rescue StandardError => e
# TODO: Render error to app
end
end
end
@hdchinh
Copy link

hdchinh commented Jul 10, 2021

Thank you, save me a lot of time 👍

@joaomarceloods
Copy link

joaomarceloods commented Aug 8, 2024

If the mobile app doesn't Base64-decode the JWT it sends, the server needs to do it:

decoded_jwt = Base64.decode64(jwt)
header_segment = JSON.parse(Base64.decode64(decoded_jwt.split('.').first))
...
token_data = JWT.decode(decoded_jwt, jwk.public_key, true, { algorithm: alg })[0]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment