Problem using Spring OAuth in standard Java8 environment

My sample app is running on-premises. But it doesn't work in standard Java8 environment. The following project is a sample application project.

https://github.com/nosix/appengine-java8-spring-oauth2

In Java8 standard environment, the following error appears:

Authentication Failed: Could not obtain access token

      

I added logs to the Spring OAuth source code and investigated the reason. The reason for the error is that session data has been lost.

It worked like this:

preservedState

is null in AuthorizationCodeAccessTokenProvider::getParametersForTokenRequest

. Thus, it is InvalidRequestException

thrown away. This is the cause of the error.

setPreservedState

the method is called in OAuth2RestTemplate::acquireAccessToken

. It is preservedState

set to null at this time .

DefaultOAuth2ClientContext

copy has preservedState

. preservedState

instance DefaultOAuth2ClientContext

is null in standard Java8 environment. But in the local environment it is not null.

Instance

DefaultOAuth2ClientContext

is saved in the session. I understand that it is stored in memory in the local environment and in the data store in the standard environment.

From the above, I guessed that the session data was lost.

I'm stuck investigating. Is there information that serves as a clue to a solution?

+3


source to share


1 answer


I had the same problem. Finally, I executed a custom SessionRepository

Spring session like this: ( see also this commit )

Repository class:

class MemcacheSessionRepository(private val memcacheService: MemcacheService) : SessionRepository<MemcacheSession> {
  private val log = LoggerFactory.getLogger(javaClass)
  private val maxInactiveIntervalInSeconds: Int = 3600

  override fun createSession() = MemcacheSession().also { session ->
    session.maxInactiveIntervalInSeconds = maxInactiveIntervalInSeconds
    log.debug("createSession() = {}", session.id)
  }

  override fun save(session: MemcacheSession) {
    log.debug("save({}) with expiration {}", session.id, session.maxInactiveIntervalInSeconds)
    memcacheService.put(session.id, session, Expiration.byDeltaSeconds(session.maxInactiveIntervalInSeconds))
  }

  override fun getSession(id: String): MemcacheSession? =
    (memcacheService.get(id) as? MemcacheSession)?.also { session ->
        session.setLastAccessedTimeToNow()
    }.also { session ->
        log.debug("getSession({}) = {}", id, session?.id)
    }

  override fun delete(id: String) {
    log.debug("delete({})", id)
    memcacheService.delete(id)
  }
}

      



Entity class:

class MemcacheSession : ExpiringSession, Serializable {
  companion object {
    const val serialVersionUID: Long = 1
  }

  private val id: String = UUID.randomUUID().toString()
  private val creationTime: Long = System.currentTimeMillis()
  private var lastAccessedTime: Long = creationTime
  private var maxInactiveIntervalInSeconds: Int = 3600
  private val attributes: MutableMap<String, Any> = mutableMapOf()

  override fun getId() = id

  override fun getCreationTime() = creationTime

  override fun getLastAccessedTime() = lastAccessedTime
  override fun setLastAccessedTime(time: Long) {
    lastAccessedTime = time
  }
  fun setLastAccessedTimeToNow() {
    lastAccessedTime = System.currentTimeMillis()
  }

  override fun getMaxInactiveIntervalInSeconds() = maxInactiveIntervalInSeconds
  override fun setMaxInactiveIntervalInSeconds(interval: Int) {
    maxInactiveIntervalInSeconds = interval
  }

  override fun removeAttribute(key: String) {
    attributes.remove(key)
  }

  override fun getAttributeNames() = attributes.keys

  override fun <T> getAttribute(key: String): T? = attributes[key] as T?

  override fun setAttribute(key: String, value: Any) {
    attributes.put(key, value)
  }

  override fun isExpired() = false
}

      

This currently works well, but only uses Memcache and needs improvement for high availability.

+1


source







All Articles