问题
当我尝试验证从Apple SSO客户端流返回的code
时,我不断收到unsupported_grant_type
400错误。
docs说unsupported_grant_type
将在我The authenticated client is not authorized to use the grant type.
在应用程序ID,服务ID上启用Apple SSO并甚至已验证我的支持电子邮件域时返回。我想念什么?要获得授权,我还需要完成其他批准步骤吗?
我尝试从验证请求中删除参数,但仍然会得到相同的错误代码。
详细信息
SSO重定向为我提供了一个表单编码的POST正文,看起来像这样:{"state"=>"x", "code"=>"y", "id_token"=>"z"}
。
然后我尝试通过调用validate_auth_token
来验证令牌。
def validate_auth_token(token, is_refresh = false)
uri = URI.parse('https://appleid.apple.com/auth/token')
https = Net::HTTP.new(uri.host, uri.port)
https.use_ssl = true
headers = { 'Content-Type': 'text/json' }
request = Net::HTTP::Post.new(uri.path, headers)
request_body = {
client_id: @client_id,
client_secret: retreive_client_secret
}
if is_refresh
request_body[:grant_type] = 'refresh_token'
request_body[:refresh_token] = token
else
request_body[:grant_type] = 'authorization_code'
request_body[:code] = token
request_body[:redirect_uri] = "https://#{Rails.application.secrets.backend_host_port}/apple"
end
request.body = request_body.to_json
response = https.request(request)
p JSON.parse response.body
end
def retreive_client_secret
cert = retreive_secret_cert
ecdsa_key = OpenSSL::PKey::EC.new cert
algorithm = 'ES256'
headers = {
'alg': algorithm,
'kid': @key_id
}
claims = {
'iss': @team_id,
'iat': Time.now.to_i,
'exp': Time.now.to_i + 5.months.to_i,
'aud': 'https://appleid.apple.com',
'sub': @client_id
}
token = JWT.encode claims, ecdsa_key, algorithm, headers
token
end
@client_id是我在初始SSO请求中提交的“服务ID”,@ key_id是从Apple Key仪表板下载的私钥的ID,@ team_id是我们的Apple Team ID。 retrieve_secret_cert
只是获取用于生成客户端机密的cert文件主体。
鉴于所有这些,我希望得到一个TokenResponse,但会不断收到相同的错误{"error"=>"unsupported_grant_type"}
,而无需其他说明。
答案 0 :(得分:0)
令牌验证请求需要使用 form 编码,而不是 json 编码。另外,当我在JWT中包含一个alg
头时,该请求无法正确验证,但是在删除请求后,该请求就可以正常工作。
这是更新的代码:
def validate_auth_token(token, is_refresh = false)
uri = URI.parse('https://appleid.apple.com/auth/token')
https = Net::HTTP.new(uri.host, uri.port)
https.use_ssl = true
request_body = {
client_id: @client_id,
client_secret: retreive_client_secret
}
if is_refresh
request_body[:grant_type] = 'refresh_token'
request_body[:refresh_token] = token
else
request_body[:grant_type] = 'authorization_code'
request_body[:code] = token
request_body[:redirect_uri] = "https://#{Rails.application.secrets.backend_host_port}/auth"
end
request = Net::HTTP::Post.new(uri.path)
request.set_form_data(request_body)
response = https.request(request)
JSON.parse response.body
end
def retreive_client_secret
cert = retreive_secret_cert
ecdsa_key = OpenSSL::PKey::EC.new cert
algorithm = 'ES256'
headers = {
'kid': @key_id
}
claims = {
'iss': @team_id,
'iat': Time.now.to_i,
'exp': Time.now.to_i + 5.minutes.to_i,
'aud': 'https://appleid.apple.com',
'sub': @client_id
}
token = JWT.encode claims, ecdsa_key, algorithm, headers
token
end
感谢sudhakar19指出编码错误。