Programming

Mocking OpenID Connect in Micronaut Integration Tests

While trying to figure out how to test my Micronaut 2.x application, I couldn’t find any examples integration testing with OpenID Connect. I wanted to mock the token validation part, so that it didn’t need to talk an external OpenID Connect session. Eventually, I found a solution to mocking OpenID Connect in Micronaut Integration Tests. This post should help those find the same thing I spent a long time looking for.

The solution is remarkably simple, provide a mock TokenAuthenticationFetcher. My implementation that is based on the Keycloak response follows.

package `is`.kow.documentmanager2

import `is`.kow.documentmanager2.entities.UserInformation
import io.micronaut.context.annotation.Replaces
import io.micronaut.http.HttpRequest
import io.micronaut.security.authentication.Authentication
import io.micronaut.security.filters.AuthenticationFetcher
import io.micronaut.security.token.TokenAuthenticationFetcher
import io.micronaut.security.token.reader.TokenResolver
import io.reactivex.rxjava3.core.Flowable
import mu.KotlinLogging
import org.reactivestreams.Publisher
import javax.inject.Inject
import javax.inject.Singleton

@Replaces(value = TokenAuthenticationFetcher::class)
@Singleton
class MockTokenAuthenticationFetcher @Inject constructor(
    private val resolver: TokenResolver
) : AuthenticationFetcher {

  override fun fetchAuthentication(request: HttpRequest<*>?): Publisher<Authentication> {

//    My user info is parsed from keycloaks token response
//    return UserInformation(
//        username = attrs["preferred_username"] as String,
//        surname = attrs["family_name"] as String,
//        email = attrs["email"] as String,
//        commonName = attrs["given_name"] as String,
//        issuer = attrs["iss"] as String
//    )

    return Flowable.fromOptional(resolver.resolveToken(request))
        .flatMap { token ->
          when (token) {
            "authorizedToken" -> Flowable.just(object : Authentication {
              override fun getName(): String {
                return "Authenticated User"
              }

              override fun getAttributes(): MutableMap<String, Any> {
                return mutableMapOf(
                    "preferred_username" to "authenticated",
                    "family_name" to "User",
                    "email" to "[email protected]",
                    "given_name" to "Authenticated",
                    "iss" to "TestToken"
                )
              }
            })
            else              -> Flowable.empty()
          }
        }

  }

}

Providing this in a test scope, or in the test classpath, replaces the existing one. Now, it’s absolutely trivial to map a token to whatever Authentication Information you want. All the roles parsing, and other parsing remains the same. This is really all it takes for mocking OpenID Connect in Micronaut Integration Tests. Hope it proves useful to you!

5 1 vote
Article Rating

Related posts

Advent of Code Day 1 and 2 in Scala

David Kowis

Advent of Code 2019 Day 3 in Scala

David Kowis

Advent of Code 2019 in Scala Day 7

David Kowis
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
Adventures in Software Development, Home Labbing, and DevOps
0
Would love your thoughts, please comment.x
()
x