Akka-http & scribe for linkedin API: set/get cookie without session (scala) - scala

I am using akka-http for bulding a REST API. (I am new to build REST web services).
I don't know how I can get and set cookie without using a session. This cookie must contain encrypt token access. I don't use Play or spray.
My code for the moment is:
lazy val signin = path("signin") {
get {
/* create the OAuthService object with a callback URL*/
val service = buildService()
/* get the request token*/
val requestToken = service.getRequestToken
/* create the cookie */
val jwtCookieEncrypted = tokenUtil.createLinkedinTokenSecret(requestToken)
val cookie = HttpCookie("jwtTokenCookie", jwtCookieEncrypted)
/* making the user validate our requestToken by redirecting him to the following URL*/
val authURL = service.getAuthorizationUrl(requestToken)
redirect(authURL, StatusCodes.TemporaryRedirect)
}
}
lazy val callback = path("callback") {
// extract cookie with the jwtTokenCookie name
cookie("jwtTokenCookie") { cookiePair =>
complete(s"The logged in user is '${cookiePair.name}'")
}
get {
parameters('code, 'state) { (code, state) => // must come from cookie and not request parameters
/* create the OAuthService object with a callback URL*/
val service = buildService()
/* get the request token*/
val requestToken = new Token(code, state)
if(state == tokenUtil.decryptLinkedinToken(requestToken.getSecret).getOrElse("")) "continue" else "throw error"
val verifier = new Verifier(state)
/* get the access token
(need to exchange requestToken and verifier for an accessToken which is the one used to sign requests)*/
val accessToken = service.getAccessToken(requestToken, verifier)
logger.debug(accessToken.getRawResponse)
/* sign request*/
val ResourceUrl = Settings.LinkedIn.ResourceUrl
val request = new OAuthRequest(Verb.GET, ResourceUrl)
service.signRequest(accessToken, request)
val response = request.send
if (response.getCode == StatusCodes.OK.intValue) complete(response.getBody)
else complete(int2StatusCode(response.getCode))
}
}
}
signin ~ callback

Check the akka doc. In your response you can include the header. In your case, maybe with redirect it´s not so simple. But you could complete the signing request returning a 308 Http code with the Location Header pointing to your oauth2 Auth server.

Is it better ?
path("signin") {
get {
val service = buildService()
val requestToken = service.getRequestToken
val authURL = service.getAuthorizationUrl(requestToken)
val requestTokenCrypted = tokenUtil.createLinkedinToken(requestToken)
val cookie = HttpCookie("abcde", requestTokenCrypted.getSecret)
setCookie(cookie) {
complete(HttpResponse(
status = StatusCodes.TemporaryRedirect,
headers = List(Location(authURL))
))
}
}
}

Related

Retrofit2 post request is successful but I'm not able to retrieve token from response body

So I'm trying to making a login(post) request to an API (https://reqres.in/api/login) with retrofit 2. The connection was successful as the response code is 200, when I did the same on Postman I received a response which contains a token string which I want but in android studio when I log the response body it gives different output. I am new to kotlin so I think I must be doing something wrong while retrieving response.
Output I'm receiving:
Response{protocol=h2, code=200, message=, url=https://reqres.in/api/login}
Output I want (token field)
{
"token": "QpwL5tke4Pnpja7X4"
}
Retrofit Builder
val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(apiUrl)
.build()
val api : reqresAPI = retrofit.create(reqresAPI::class.java)
API Interface
interface reqresAPI {
// FOR REFERENCE
// https://reqres.in/api/login
// ANNOTATE WITH POST TO SEND DATA
#POST(value = "login")
fun sendData(
#Body user: User
): Call<ResponseModel> // CALL IS USED TO MAKE AN API CALL
}
Response Model
class ResponseModel{
val token : String = ""
get() = field
}
User model with 2 parameters email and password
class User (
val email :String,
val password :String
)
Calling API
val call = api.sendData(user)
call.enqueue(object : Callback<ResponseModel>{
override fun onResponse(call: Call<ResponseModel>, response: Response<ResponseModel>) {
Log.d("LOGGER", response.toString())
}
override fun onFailure(call: Call<ResponseModel>, t: Throwable) {
Log.d("LOGGER", "ERROR "+t.message.toString())
}
})
Please change this
class ResponseModel{
val token : String = ""
get() = field
}
to this
class ResponseModel{
#SerializedName("token")
val token : String
}

how can i have two barer token in header using akka http

i have an app in akka http i am using its header directive for using accessToken as barer token everything is working fine , now i want to have two barer token instead of one, first should be accessToken and second should be a refreshToken
here is my working code for one barer token
private def bearerToken: Directive1[Option[String]] =
for {
authBearerHeader <- optionalHeaderValueByType(classOf[Authorization]).map(extractBearerToken)
xAuthCookie <- optionalCookie("X-Authorization-Token").map(_.map(_.value))
} yield authBearerHeader.orElse(xAuthCookie)
private def extractBearerToken(authHeader: Option[Authorization]): Option[String] =
authHeader.collect {
case Authorization(OAuth2BearerToken(token)) => token
}
a route defined in my main controller
def accessProtectedResource: server.Route =
path("access-protected-resource") {
get {
bearerToken { accessToken =>
accessToken match {
case Some(token) =>
case Failure(e)=>failWith(ex)
}
}
}
and from postman i added barer token in Authorization tab of postman
can anyone please guide what changes i need to make if i need to pass two barer token (accessToken and refreshToken)

I am not able to log in into the app using Gatling

I am new to Gatling facing some trouble while log in into the application.
There is an API which provides a random no and public key, I have to save these values so that I can parse them to next step.
Next step is a post request for entering User-id and password, password gets encrypted.
Also I have to save XSRF token from the cookie to maintain the session.
Then there is O.T.P authentication which I have to fetch from Rest API.
how do i need to perform all the above in sequence
object Actions {
def retrieveAuthData(session: Session, datakey: String): AuthData = {
// get response as a string
val t: String = session.get(datakey).as[String];
// retrieve parameters from json
val publicKey: String = a("PublicKey").asInstanceOf[String];
val random: String = a("Random").asInstanceOf[String];
val ds3: Boolean = a("DS3").asInstanceOf[Boolean];
val twoFA: Boolean = a("TwoFa").asInstanceOf[Boolean];
return new AuthData(publicKey, random, ds3, twoFA);
}
}

Setting Cookies using Http4s Client

I am using Http4s library to make HTTP calls to a REST web service. the rest web service requires me to set an authentication cookie.
I have written the following code to set this cookie.
val client = PooledHttp1Client()
val uri = Uri.uri("http://localhost/restService")
val req = Request(GET, uri)
req.headers.put(`Content-Type`(MediaType.`application/json`))
val cookie = org.http4s.Cookie("foo_session", getLoginSessionId, domain = Some("localhost"), path=Some("/"))
req.headers.put(org.http4s.headers.Cookie(cookie))
val task = client.expect[Response](req)
val list = task.run
list.response.foreach(println)
client.shutdownNow()
When I run this code I get a 401 error, meaning that the web service does not recognize that the cookie was set.
Now If I write the same code using apache http client. then everything works fine. The code below is doing exactly the same thing as above.
val get = new HttpGet(s"http://localhost/restService")
get.setHeader("Content-type", "application/json")
val client = new DefaultHttpClient()
val respHandler = new BasicResponseHandler
val cookieStore = new BasicCookieStore()
val cookie1 = new BasicClientCookie("foo_session", getLoginSessionId)
cookie1.setDomain("localhost")
cookie1.setPath("/")
cookieStore.addCookie(cookie1)
val localContext = new BasicHttpContext()
localContext.setAttribute(HttpClientContext.COOKIE_STORE, cookieStore)
localContext
val responseString = client.execute(get, respHandler, cookieContext)
val list = parse(responseString).extract[Response]
list.response.foreach(println)
list.response
It seems that your cookie is not used into response.
Did you try to use the following approach :
val cookie = org.http4s.ResponseCookie("token", su.token.getOrElse("No token"), httpOnly = true, secure = true)
Ok("resp").map(_.addCookie(cookie))
if you want to attach the cookie server sent to your client, you can try Cookie Jar. https://github.com/http4s/http4s/blob/main/client/src/main/scala/org/http4s/client/middleware/CookieJar.scala
Http4s strictly check the cookie from server so chance are that some cookie entries are not replied. if it is the case, you may try this one:
https://github.com/chenharryhua/nanjin/blob/master/http/src/main/scala/com/github/chenharryhua/nanjin/http/client/middleware/package.scala#L39

Accessing session information inside a custom PartHandler in Play! Framework 2.0

In order to achieve a streaming upload I have written a custom PartHandler (Thread here ).
I now need to access a value that is stored inside the play! session inside the PartHandler.
How can I do that ?
Code sample:
def uploadFile() =
Action( parse.multipartFormData(myPartHandler) )
{ request =>
request.session.get("myValue") // <-- Recovering value is fine here
Ok("Done") }
def myPartHandler: BodyParsers.parse.Multipart.PartHandler[MultipartFormData.FilePart[Result]] = {
parse.Multipart.handleFilePart {
case parse.Multipart.FileInfo(partName, filename, contentType) =>
// ** Need to access a value in session here **
//request.session.get("myValue")...
// Handle part ...
Thanks!
With the help of other users of the play! framework google group, here is how to access the request inside a custom partHandler.
//Create a body parser
val myBodyParser = BodyParser { request =>
parse.multipartFormData(myPartHandler(request)).apply(request)
}
def uploadFile() = Action(myBodyParser)
{request =>Ok("Done")}
def myPartHandler(request: RequestHeader) : BodyParsers.parse.Multipart.PartHandler[MultipartFormData.FilePart[Result]] = {
parse.Multipart.handleFilePart {
case parse.Multipart.FileInfo(partName, filename, contentType) =>
println(request.session.get("myValueKey"));