Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

marathon namer: refresh token before expiration #782

Open
siggy opened this issue Oct 28, 2016 · 0 comments
Open

marathon namer: refresh token before expiration #782

siggy opened this issue Oct 28, 2016 · 0 comments
Labels

Comments

@siggy
Copy link
Member

siggy commented Oct 28, 2016

currently, the marathon namer waits until it sees an Unauthorized (401) before attempting to refresh it's auth token. it could be a bit smarter by checking the token's expiration, and preemptively refreshing the token.

a couple relevant code snippets:

checking for expiration

Jwt.decode(tempToken, privateKey, Seq[JwtAlgorithm.RS256])

import com.fasterxml.jackson.databind.annotation.JsonDeserialize

case class TokenClaim(@JsonDeserialize(contentAs = classOf[java.lang.Long]) exp: Option[Long])

val claimStr = Jwt.decode(token, JwtOptions(signature=false,expiration=false)).get

val expiresAt = Api.readJson[TokenClaim](Buf.Utf8(claimStr)) match {
  case Return(TokenClaim(Some(exp))) =>
    exp
  case Throw(e) =>
    throw e
  case _ =>
    val e = new Exception(s"unexpected format for $claimStr")
    throw e
}

val tokenRefreshThreshold = 60
val now = System.currentTimeMillis / 1000
if (expiresAt < (now + tokenRefreshThreshold)) {
  refreshToken()
}

better use of types in token encode/decode

--- a/namer/marathon/src/main/scala/io/buoyant/namer/marathon/Authenticator.scala
+++ b/namer/marathon/src/main/scala/io/buoyant/namer/marathon/Authenticator.scala
@@ -5,20 +5,22 @@ import com.twitter.util.{Future, Promise, Return, Throw, Time}
 import io.buoyant.marathon.v2.Api
 import java.net.URL
 import java.util.concurrent.atomic.AtomicReference
-import pdi.jwt.{Jwt, JwtAlgorithm}
+import pdi.jwt.{Jwt, JwtAlgorithm, JwtClaim, JwtHeader}
 import scala.annotation.tailrec

 object Authenticator {

   case class AuthRequest(
     loginEndpoint: String,
-    uid: String,
-    privateKey: String,
+    val uid: String,
+    val privateKey: String,
     algorithm: JwtAlgorithm = JwtAlgorithm.RS256
   ) {
     val path: String = new URL(loginEndpoint).getPath
     val jwt: String = {
-      val token = Jwt.encode(s"""{"uid":"$uid"}""", privateKey, algorithm)
+      val header = JwtHeader(algorithm)
+      val claim = JwtClaim(s"""{"uid":"$uid"}""").issuedNow
+      val token = Jwt.encode(header, claim, privateKey)
       s"""{"uid":"$uid","token":"$token"}"""
     }
   }
@@ -45,7 +47,12 @@ object Authenticator {
         } else apply(req) // try again on race

       case s0@Authenticating(tokenF) =>
-        tokenF.flatMap(issueAuthed(req, _)).rescue {
+        tokenF.flatMap( token =>
+          // if token is about to expire, kick off an asynchronous update
+          refreshToken(token)
+
+          issueAuthed(req, token)
+        ).rescue {
           case UnauthorizedResponse(rsp) =>
             // If a request is unauthorized even though we have a
             // token, it may have expired. If another request hasn't

motivated by: #759 (comment)

Tim-Brooks pushed a commit to Tim-Brooks/linkerd that referenced this issue Dec 20, 2018
This is a fairly minor refactor to the proxy telemetry tests. b07b554 added a `Fixture` in the Destination service labeling tests added in linkerd#661 to reduce the repetition of copied and pasted code in those tests. I've refactored most of the other telemetry tests to also use the test fixture. Significantly less code is copied and pasted now.

Signed-off-by: Eliza Weisman <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants