剪影和移动应用程序

Posted

技术标签:

【中文标题】剪影和移动应用程序【英文标题】:Silhouette and mobile application 【发布时间】:2015-08-15 15:29:09 【问题描述】:

我以 play-silhouette-angular-seed 为例。 通过 Satellizer 进行授权工作正常。

当我尝试通过 ios 应用授权时,出现下一个错误:

com.mohiva.play.silhouette.impl.exceptions.UnexpectedResponseException: 
[Silhouette][facebook] Cannot build OAuth2Info because of invalid response format: 
List((/access_token,List(ValidationError(List(error.path.missing),WrappedArray()))))

我在 OAuth2Provider.scala 的这个函数中收到错误 400:

protected def getAccessToken(code: String)(implicit request: RequestHeader): Future[OAuth2Info] = 
httpLayer.url(settings.accessTokenURL).withHeaders(headers: _*).post(Map(
  ClientID -> Seq(settings.clientID),
  ClientSecret -> Seq(settings.clientSecret),
  GrantType -> Seq(AuthorizationCode),
  Code -> Seq(code),
  RedirectURI -> Seq(resolveCallbackURL(settings.redirectURL))) ++ settings.accessTokenParams.mapValues(Seq(_))).flatMap  response =>
  logger.debug("[Silhouette][%s] Access token response: [%s]".format(id, response.body))
  Future.from(buildInfo(response))

【问题讨论】:

【参考方案1】:

此错误已出现,因为通过 Facebook 进行身份验证的 Satellizer 向服务器发送“身份验证代码”,而 Silhouette 服务器使用此代码获取 Facebook“访问令牌”并创建用户。

相反,Facebook iOs SDK 获得了“访问令牌”,我尝试将其发送到 Json 中的“代码”字段中的服务器,例如“卫星”。

为了解决这个问题,我在名为“access_token”的 Json 字段中发送了一个“访问令牌”,并使用下一个代码来验证移动应用程序:

class MobileSocialAuthController @Inject() (
  val messagesApi: MessagesApi,
  userService: UserService,
  authInfoRepository: AuthInfoRepository,
  socialProviderRegistry: SocialProviderRegistry,
  val env: Environment[User, JWTAuthenticator])
  extends Silhouette[User, JWTAuthenticator]

  def authenticate(provider: String) = UserAwareAction.async(parse.json) 
    implicit request =>
      provider match 
        case "facebook" =>
          request.body.asOpt[OAuth2Info] match 
            case Some(authInfo) =>
              (socialProviderRegistry.get[FacebookProvider](provider) match 
                case Some(p: FacebookProvider) =>
                  for 
                    profile <-p.retrieveProfile(authInfo)
                    user <- userService.save(profile)
                    authInfo <- authInfoRepository.save(profile.loginInfo, authInfo)
                    authenticator <- env.authenticatorService.create(profile.loginInfo)
                    token <- env.authenticatorService.init(authenticator)
                   yield 
                    env.eventBus.publish(LoginEvent(user, request, request2Messages))
                    Ok(Json.obj("token" -> token))
                  
                case _ => Future.failed(new ProviderException(s"Cannot authenticate with unexpected social provider $provider"))
              ).recover 
                case e: ProviderException =>
                  logger.error("Unexpected provider error", e)
                  Unauthorized(Json.obj("message" -> Messages("could.not.authenticate")))
              
            case _ =>
              Future(BadRequest(Json.obj(
                "message" -> "Bad OAuth2 json.")))
          
        case _ =>
          Future(BadRequest(Json.obj(
            "message" -> "You can use only Facebook account for authentication.")))
      
  

因此,我有一个令牌,我在 ios 应用程序中使用它来获取资源。

【讨论】:

我在尝试使用您的解决方案时收到未记录的Unauthorized 回复。您是否遇到过其他问题?【参考方案2】:

OAuth2Provider 得到一个它无法解析的响应,即任何不成功的响应时,就会发生这种情况。所以这个错误可能有很多原因,例如授权码无效或过期,或者您没有正确配置redirect_uri(检查您在Facebook开发网站上的Facebook应用配置以设置redirect_uri)。

Silhouette 确实记录了它从 Facebook 获得的响应,这应该可以帮助您调试实际问题是什么,要查找的日志行在您提供的 sn-p 中:

logger.debug("[Silhouette][%s] Access token response:...

所以请检查您的日志,在那里您应该会看到来自 Facebook 的响应,其中可能会显示一个错误,说明他们为什么不能给您access_token

【讨论】:

以上是关于剪影和移动应用程序的主要内容,如果未能解决你的问题,请参考以下文章

如何实现多个剪影身份验证器?

Mobilefirst 移动应用和 THyM 移动应用的建议

区分http移动浏览器和移动应用请求

移动应用测试篇——移动应用的发展

移动应用的测试策略与测试架构

移动应用页面可以确定哪个移动应用页面调用它以及选择了什么?