`
sillycat
  • 浏览: 2501781 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

OAuth Login Solution(2)Scala and Callback URLs

 
阅读更多
OAuth Login Solution(2)Scala and Callback URLs

OauthService.scala Codes to Generate AuthURL/Fetch RefreshToken/Fetch Profile
package services
import java.util.Arrays;
import com.google.api.client.googleapis.auth.oauth2.{GoogleTokenResponse, GoogleAuthorizationCodeRequestUrl}
import com.jobs2careers.util.IncludeLogger
import models.{ AccountProfileResponse}
import play.api.libs.json.Json
import play.api.libs.ws.{WSResponse, WS}
import utils.IncludeOauthConfig
import scala.concurrent.duration._
import scala.concurrent.Await
import scala.concurrent.Future
import play.api.Play.current
import com.google.api.client.auth.oauth2.Credential
import com.google.api.client.auth.oauth2.TokenResponse
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow
import com.google.api.client.http.GenericUrl
import com.google.api.client.http.HttpRequest
import com.google.api.client.http.HttpRequestFactory
import com.google.api.client.http.HttpTransport
import com.google.api.client.http.javanet.NetHttpTransport
import com.google.api.client.json.JsonFactory
import com.google.api.client.json.jackson2.JacksonFactory
import com.google.api.services.gmail.GmailScopes

object OauthService extends IncludeOauthConfig with IncludeLogger{
  implicit val accountProfileResponseWrites = Json.writes[AccountProfileResponse]
  implicit val accountProfileResponseReads = Json.reads[AccountProfileResponse]

  val callbackURL = OAUTH_CALLBACK_URI
  val USER_INFO_URL = "https://www.googleapis.com/auth/userinfo.profile"
  val EMAIL_INFO_URL = "https://www.googleapis.com/auth/userinfo.email"
  val USER_PROFILE_URL = "https://www.googleapis.com/oauth2/v1/userinfo"
  val JSON_FACTORY:JsonFactory = new JacksonFactory()
  val HTTP_TRANSPORT:HttpTransport = new NetHttpTransport()

  def generateAuthURL(accountCode:String):String = {
    val flow:GoogleAuthorizationCodeFlow = new GoogleAuthorizationCodeFlow.Builder(
      HTTP_TRANSPORT, JSON_FACTORY, OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET,
      Arrays.asList(GmailScopes.MAIL_GOOGLE_COM, GmailScopes.GMAIL_READONLY, USER_INFO_URL, EMAIL_INFO_URL))
      .setAccessType("offline")
      .setApprovalPrompt("force")
      .build()
    val url:GoogleAuthorizationCodeRequestUrl = flow.newAuthorizationUrl()
    val url_str =  url.setRedirectUri(callbackURL).setState(accountCode).build()
    //url_str = url_str + "&login_hint=ipply@jobs2careers.com";
    return url_str
  }

  def fetchRefreshToken(accessToken:String):String = {
    val flow:GoogleAuthorizationCodeFlow = new GoogleAuthorizationCodeFlow.Builder(
      HTTP_TRANSPORT, JSON_FACTORY, OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET,
      Arrays.asList(GmailScopes.MAIL_GOOGLE_COM, GmailScopes.GMAIL_READONLY, USER_INFO_URL, EMAIL_INFO_URL))
      .setAccessType("offline")
      .setApprovalPrompt("force")
      .build()
    val response:GoogleTokenResponse = flow.newTokenRequest(accessToken)
      .setRedirectUri(callbackURL).execute()
    val refreshToken = response.getRefreshToken()
    logger.debug("Refresh token system get = " + refreshToken)
    return refreshToken
  }

  def fetchEmail(refreshToken:String): Option[String] = {
    val flow:GoogleAuthorizationCodeFlow = new GoogleAuthorizationCodeFlow.Builder(
      HTTP_TRANSPORT, JSON_FACTORY, OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET,
      Arrays.asList(GmailScopes.MAIL_GOOGLE_COM, GmailScopes.GMAIL_READONLY, USER_INFO_URL, EMAIL_INFO_URL))
      .setAccessType("offline")
      .setApprovalPrompt("force")
      .build()
    logger.debug("Refresh Token = " + refreshToken)
    val tokenResponse:TokenResponse = new TokenResponse()
    tokenResponse.setRefreshToken(refreshToken)
    val credential:Credential = flow.createAndStoreCredential(tokenResponse, null)
    val requestFactory:HttpRequestFactory = HTTP_TRANSPORT.createRequestFactory(credential)
    // Make an authenticated request
    val  genericUrl:GenericUrl = new GenericUrl(USER_INFO_URL)
    val  request:HttpRequest = requestFactory.buildGetRequest(genericUrl)
    request.getHeaders().setContentType("application/json")
    request.execute()
    val accessToken = credential.getAccessToken()
    logger.debug("System get the new Access Token = " + accessToken)
//    {
//      "id": "114122167329329897934",
//      "email": “luohuazju@gmail.com",
//      "verified_email": true,
//      "name": “Sillycat Mobile",
//      "given_name": “sillycat",
//      "family_name": "Mobile",
//      "picture": "https://lh3.googleusercontent.com/-XdUIqdMkCWA/AAAAAAAAAAI/AAAAAAAAAAA/4252rscbv5M/photo.jpg",
//      "locale": "en",
//      "hd": “gmail.com"
//    }
    val url = USER_PROFILE_URL + "?alt=json&access_token=" + accessToken
    logger.debug("URL = " + url)
    val future:Future[WSResponse] = WS.url(url).get()
    val result = Await.result(future, 20 seconds)
    logger.debug("Fetching the profile response = " + result.json + " accessToken = " + accessToken)
    val email = result.json.asOpt[AccountProfileResponse].map { profile =>
      logger.info("Fetching the profile information = " + profile)
      profile.email
    }
    return email
  }
}

The Callback URL who handle the Callback
  def addSource = Action { request =>

    logger.debug("The request body = " + request.body)

    val accessToken = request.getQueryString("code").getOrElse("")
    val accountCode = request.getQueryString("state").getOrElse("")

    logger.debug("First access token system get = " + accessToken)

    if(accessToken.isEmpty || accountCode.isEmpty){
      val warn_msg = "Callback add source fail, request params accountCode = " + accountCode
      logger.warn(warn_msg)
      BadRequest(Json.obj("status" -> "Fail", "message" -> warn_msg))
    }else{
      val refreshToken = OauthService.fetchRefreshToken(accessToken)
      val email = OauthService.fetchEmail(refreshToken).getOrElse("")
      if(email.isEmpty){
        val warn_msg = "Callback add source fail, fail to fetch email with refreshToken."
        logger.warn(warn_msg)
        BadRequest(Json.obj("status" -> "Fail", "message" -> warn_msg))
      }else{
        //call actor to ContextIO to add source
       sillycatIOthrottler ! AccountSourceMessage(
          accountCode, //accountCode
          email, //email system fetch from profile
          email, //username, same as email for google
          refreshToken //refreshToken
        )
        Ok(Json.obj("status" -> "OK"))
      }
    }
  }

The dependencies in build.sbt
"com.google.api-client" % "google-api-client" % "1.20.0",
"com.google.oauth-client" % "google-oauth-client" % "1.20.0",
"com.google.apis" % "google-api-services-gmail" % "v1-rev36-1.20.0",

References:
http://sillycat.iteye.com/blog/2274258
分享到:
评论

相关推荐

    【案例】某企业人力资源盘点知识.docx

    【案例】某企业人力资源盘点知识.docx

    AUTOSAR-SWS-SAEJ1939NetworkManagement.pdf

    AUTOSAR_SWS_SAEJ1939NetworkManagement.pdf

    基于java的毕业生离校管理系统源码.zip

    提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

    onnxruntime-1.16.0-cp310-cp310-linux_armv7l.whl.zip

    onnxruntime-1.16.0-cp310-cp310-linux_armv7l.whl.zip

    某二层小型独栋别墅建筑施工图立面.dwg

    某二层小型独栋别墅建筑施工图立面.dwg

    Java毕业设计-ssm基于移动端的选课系统的设计与实现演示录像(高分期末大作业).rar

    Java毕业设计-ssm基于移动端的选课系统的设计与实现演示录像(高分期末大作业)

    Java毕业设计-疫情防控演示0307-224719(高分期末大作业).zip

    此资源为完整项目部署后演示效果视频,可参考后再做项目课程决定。 包含:项目源码、数据库脚本、项目说明等,有论文参考,该项目可以直接作为毕设使用。 技术实现: ​后台框架:SpringBoot框架 或 SSM框架 ​数据库:MySQL 开发环境:JDK、IDEA、Tomcat 项目都经过严格调试,确保可以运行! 博主可有偿提供毕设相关的技术支持 如果您的开发基础不错,可以在此代码基础之上做改动以实现更多功能。 其他框架项目设计成品不多,请根据情况选择,致力于计算机专业毕设项目研究开发。

    onnxruntime-1.5.3-cp38-cp38-linux_armv7l.whl.zip

    onnxruntime-1.5.3-cp38-cp38-linux_armv7l.whl.zip

    AUTOSAR-EXP-LayeredSoftwareArchitecture.pdf

    AUTOSAR_EXP_LayeredSoftwareArchitecture.pdf

    onnxruntime-1.2.0-cp38-cp38-linux_armv7l.whl.zip

    onnxruntime-1.2.0-cp38-cp38-linux_armv7l.whl.zip

    月夜行舟是一首中国古代诗歌.docx

    "月夜行舟"是一首中国古代诗歌,由唐代诗人张若虚创作。这首诗表现了诗人在月光下乘船游湖的情景,通过描绘自然景色和表达内心情感,展现了诗人对自然、生命和人生的感悟。以下是对这首诗的详细介绍: 诗歌原文 月明星稀,乌鹊南飞。 绕树三匝,何枝可依? 山峦倒碎风前浪,一片孤城万仞山。 羌笛何须怨楼台,春风不度玉门关。 解读 月明星稀: 诗歌开篇即描绘了明亮的月光和繁星点点的夜空,为整首诗营造出安静、幽远的氛围。 乌鹊南飞: 乌鹊南飞是秋天的标志,也象征着季节的变迁和时光的流逝。 绕树三匝,何枝可依: 诗人在此描绘了乌鸦盘旋于树上的景象,表现了孤寂和迷茫之情。 山峦倒碎风前浪,一片孤城万仞山: 这两句表现了山峦起伏、波涛汹涌的景象,将自然景色与内心的孤独、无助相结合。 羌笛何须怨楼台,春风不度玉门关: 最后两句表达了诗人对于人生的感悟,提倡超脱世俗和物欲,表现出超然的境界和淡泊的态度。 艺术特点 意境深远: 通过对自然景色的描绘和内心感悟的表达,诗歌营造出了超脱世俗、清新脱俗的意境。 意象鲜明: 诗中的乌鹊、树影、山峦等意象生动鲜明,展现了诗人对自然景色的敏锐观察和抒发。 情感真挚: 诗人在诗

    基于Java的学生成绩管理系统源码.zip

    提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

    Java毕业设计-ssm基于移动端的校园请假系统的设计与实现演示录像(高分期末大作业).zip

    此资源为完整项目部署后演示效果视频,可参考后再做项目课设决定。 包含:项目源码、数据库脚本、项目说明等,有论文参考,该项目可以直接作为毕设使用。 技术实现: ​后台框架:SpringBoot框架 或 SSM框架 ​数据库:MySQL 开发环境:JDK、IDEA、Tomcat 项目都经过严格调试,确保可以运行! 博主可有偿提供毕设相关的技术支持 如果您的开发基础不错,可以在此代码基础之上做改动以实现更多功能。 其他框架项目设计成品不多,请根据情况选择,致力于计算机专业毕设项目研究开发。

    Java毕业设计-ssm基于Java智能选课系统的设计与实现演示录像(高分期末大作业).zip

    此资源为完整项目部署后演示效果视频,可参考后再做项目课设决定。 包含:项目源码、数据库脚本、项目说明等,有论文参考,该项目可以直接作为毕设使用。 技术实现: ​后台框架:SpringBoot框架 或 SSM框架 ​数据库:MySQL 开发环境:JDK、IDEA、Tomcat 项目都经过严格调试,确保可以运行! 博主可有偿提供毕设相关的技术支持 如果您的开发基础不错,可以在此代码基础之上做改动以实现更多功能。 其他框架项目设计成品不多,请根据情况选择,致力于计算机专业毕设项目研究开发。

    Java毕业设计-ssm家校通小程序演示录像(1)(高分期末大作业).zip

    此资源为完整项目部署后演示效果视频,可参考后再做项目课设决定。 包含:项目源码、数据库脚本、项目说明等,有论文参考,该项目可以直接作为毕设使用。 技术实现: ​后台框架:SpringBoot框架 或 SSM框架 ​数据库:MySQL 开发环境:JDK、IDEA、Tomcat 项目都经过严格调试,确保可以运行! 博主可有偿提供毕设相关的技术支持 如果您的开发基础不错,可以在此代码基础之上做改动以实现更多功能。 其他框架项目设计成品不多,请根据情况选择,致力于计算机专业毕设项目研究开发。

    基于springboot的B2B平台的医疗病历交互系统.zip

    在一个组织里,信息已作为人力、物力、财力之外的第四种资源,占有重要的地位。然而,信息是一种非物质的,有别于基本资源的新形式的资源。信息也是管理的对象,必须进行管理和控制。本基于B2B平台的医疗病历交互系统是将IT技术用于医疗病历信息的管理, 它能够收集与存储学习的档案信息,提供更新与检索学习信息档案的接口;提高工作效率。 本系统是基于JAVA平台开发的一套基于B2B平台的医疗病历交互系统。系统采用Java为编程语言,后台主要采用Spring Boot框架。数据库采用Mysql建立数据之间的转换。论文主要介绍了本课题的开发背景,所要完成的功能和开发的过程。重点的说明了系统设计的重点、设计思想、难点技术和解决方案。 关键词:基于B2B平台的医疗病历交互系统;Spring Boot框架;计算机;信息 管理员角色:医院管理、医院注册、医院文章、医生信息 用户角色:医院注册、医疗安排 医院角色:院区注册、医院公告 医生角色:医院工作人员、病人病历

    B2113 输出亲朋字符串.cpp

    B2113 输出亲朋字符串

    京瓷方式人才培养制度第二部分.docx

    京瓷方式人才培养制度第二部分.docx

    B2023 空格分隔输出.exe

    B2023 空格分隔输出

Global site tag (gtag.js) - Google Analytics