Firebase token verification with Micronaut

Spring Boot is nice. It turned the creation of a service into something fun. Although I prefer Vert.x nowadays, Spring Boot was for a long time my favorite. So, I was at work this week and I was told about Micronaut. Just like all curious people, I went searching and reading and trying Micronaut over the weekend. The verdict: I believe it is about time to replace Spring Boot as my second favorite Java framework.

Micronaut

Micronaut is a full-stack framework. It focuses on modularity, minimal memory footprint and fast startup time. It is meant for the cloud and with that in mind, we are able to write serverless applications that will performance impressively well on AWS lambdas and alike services. The best thing: you can code using Java or Kotlin or Groovy.

One of the main advantages of using Micronaut is that there are no runtime penalties for holding metadata for configuration and dependency injection. No reflection at runtime. Everything is handled by using AST processors leveraging JSR-330. So, whether you are moving from Spring Boot or Spring Boot with Spring Cloud enabled, Micronaut is pretty similar to it and it can be reactive by default.

Testability is a big plus when using Micronaut as well.

Specificity

Micronaut is cool and I am willing to write more about it, but the reason why this post was created is to show how to secure your service using Firebase token. I didn't find it in the documentation and that is another reason why I am writing it here.

Like mentioned before, Micronaut is quite similar to Spring Boot, so the way you configure it is similar as well. First, to enable JWT security in your service, you need to add the security dependecies to your project:

<dependency>
  <groupId>io.micronaut</groupId>
  <artifactId>micronaut-security</artifactId>
</dependency>
<dependency>
  <groupId>io.micronaut</groupId>
  <artifactId>micronaut-security-jwt</artifactId>
</dependency>

With the dependencies in place, we need to enable it within our configuration file called application.yml, like this:

micronaut:
  application:
    name: a-service
  security:
    enabled: true
    intercept-url-map:
      -
        pattern: /**
        access:
          - isAuthenticated()
    token:
      jwt:
        enabled: true

Once you did that, you only need two more things: 1) an extension of Authentication to tell Micronaut security all the information it needs; 2) a extension of TokenValidator so it can check whether the token you are passing over Authorization header is valid or not.

FirebaseAuthentication

public class FirebaseAuthentication implements Authentication {

  private FirebaseToken firebaseToken;

  FirebaseAuthentication(FirebaseToken firebaseToken) {
    this.firebaseToken = firebaseToken;
  }

  @Override
  public Map<String, Object> getAttributes() {
    return Collections.unmodifiableMap(firebaseToken.getClaims());
  }

  @Override
  public String getName() {
    return firebaseToken.getUid();
  }
}

FirebaseTokenValidator

@Singleton
public class FirebaseTokenValidator implements TokenValidator {

  @Override
  public Publisher<Authentication> validateToken(String token) {
    try {
      FirebaseToken firebaseToken = FirebaseAuth.getInstance().verifyIdToken(token);
      return Flowable.just(new FirebaseAuthentication(firebaseToken));
    } catch (FirebaseAuthException ex) {
      return Flowable.empty();
    }
  }
}

With the steps above set, you are good to go.

Conclusion

So far, I am really enjoying Micronaut and I hope you give it a try. I hope to write more about it in the future as I dig into it, but let's see how that comes along.

See ya!