简体   繁体   中英

How Silhouette JWT token keeps valid in stateless mode?

I am developing one project and using Silhouette authentication framework. For regular requests from the browser UI I use CookieAuthenticator and for REST API requests I use JWTAuthenticator. Here is a part of Silhouette source code with documentation which makes me feel I do not completely understand how this thing really works:

/**
 * The service that handles the JWT authenticator.
 *
 * If the authenticator DAO is deactivated then a stateless approach will be used. But note
 * that you will loose the possibility to invalidate a JWT.
 *
 * @param settings The authenticator settings.
 * @param dao The DAO to store the authenticator. Set it to None to use a stateless approach.
 * @param idGenerator The ID generator used to create the authenticator ID.
 * @param clock The clock implementation.
 * @param executionContext The execution context to handle the asynchronous operations.
 */
class JWTAuthenticatorService(
  settings: JWTAuthenticatorSettings,
  dao: Option[AuthenticatorDAO[JWTAuthenticator]],
  idGenerator: IDGenerator,
  clock: Clock)(implicit val executionContext: ExecutionContext)
  extends AuthenticatorService[JWTAuthenticator]
  with Logger {

Notice this part of the doc

If the authenticator DAO is deactivated then a stateless approach will be used. But note * that you will loose the possibility to invalidate a JWT.

So it works precisely as they say. When I pass None as a value of the dao parameter then generated tokens keep valid even if I shut down the app. But without a backing store how these tokens keep valid? When I start the app again and use the same token it authenticates the user. And I don't know how it does this. Could you explain?

It's very simple. You encode the the contents of a token with a known salt and algorithm combo. JWT tokens have known structure, encoded with HMAC or RSA. The server can decrypt the tokens in a stateless fashion, so long as they know the encoding key(secret key for HMAC) and keypair for RSA, for example.

You can even make your own if you want to get clever and check out the internals. JWT is standardised, and the account is usually available under an iss field by convention. In Google Cloud for instance, the iss is your Google Service Account email, so they can know who you are.

Exploring further, you can make your own session object and encode that to a token.

case class Session(user: UUID, timestamp: String, email: String)

// This is roughly the process used.
object TokenEncoder {
  val secret = Play.current.configuration.getString("encryption.key")
  def encode(session: Session): String = { 
    // The below line is just to make a point.
    AES.encrypt(Json.toJson(session), someSharedKey)
  }

  def decode(str: String): Option[Session] = {
    Json.parse(AES.decrypt(str, someSharedKey)).asOpt[Session]
  }
}

The string value of this token can then be used inside a cookie or a header in case of a cross server request, and every server can statelessly validate a token and extract user information so long as they know the value of someSharedKey , the secret that was used to perform the encoding.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM