ios - 苹果单点登录 : Why I am getting a 'unsupported_grant_type' error?

标签 ios macos oauth single-sign-on

问题

当我尝试验证从 Apple SSO 客户端流程返回的 code 时,我不断收到 unsupported_grant_type 400 错误。

docs假设当经过身份验证的客户端无权使用授权类型时,将返回 unsupported_grant_type 我已在 App Id、Service Id 上启用 Apple SSO,并且甚至验证了我的支持电子邮件域。我缺少什么?我还需要完成其他审批步骤才能获得授权吗?

我尝试从验证请求中删除参数,但仍然收到相同的错误代码。

详细信息

SSO 重定向为我提供了一个表单编码的 POST 正文,如下所示:{"state"=>"x", "code"=>"y", "id_token"=>"z"}.

然后,我尝试通过调用 validate_auth_token 来验证 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团队ID。 retrieve_secret_cert 只是获取用于生成客户端 key 的证书文件正文。

考虑到这一切,我预计 TokenResponse ,但不断收到相同的错误 {"error"=>"unsupported_grant_type"} 且没有任何其他解释。

最佳答案

token 验证请求需要采用form编码,而不是json编码。此外,当我在 JWT 中包含 alg header 时,请求无法正确验证,但在删除它后可以正常工作。

这是更新后的代码:

    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用于指出编码错误。

关于ios - 苹果单点登录 : Why I am getting a 'unsupported_grant_type' error?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57861466/

相关文章:

java - 加载 JNI 库时出现 Unsatisfied Link 错误

linux - Electron-builder - 如何在安装应用程序之后/之前运行脚本

jquery - 安全休息 API

java - 如何将 Dropbox API 的 OAuth1 token / secret 对迁移到 OAuth2 访问 token ?

iphone - UITableViewCell 内旋转的 UITableView 未显示 initWithFrame : says to

ios - cocos2d/box2d 麻烦

ios - 以不同的持续时间永远重复 Action

javascript - 为 "single-page"webapp 禁用惯性滚动

php - 使用 Twitter OAuth 进行自动状态更新

cocoa-touch - willAnimateRotationToInterfaceOrientation 在 vi​​ewWillAppear 之前被调用