Spring cloud Zuul pass JWT downstream

1.9k views Asked by At

I've read a bunch of questions around this but none seem to be similar to my edge-case where I already have my JWT.

I'm using the Auth0 (note auth-zero, not Oauth) in my frontend to gain a JWT which is loaded with scopes and authentication for my backend. When I login to my frontend client I get a nice JWT with an access_token. If I copy that token I can make a direct curl request to my backend microservices

curl -X GET -H "Authorization: Bearer TOKEN_HERE" -H "Cache-Control: no-cache" "http://192.168.0.109:39885"

And this works as expected, I get a 200 response. Nice.

Now when I try the same curl request through my Zuul proxy I get a nasty 401.

The configuration I have for my gateway is:

@EnableHystrix
@EnableZuulProxy
@EnableEurekaClient
@SpringBootApplication
public class EdgeServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(EdgeServiceApplication.class, args);
    }
}

Now reading the documentation and this conversation from the brilliant Dr Syer I know I need to allow the headers to go downstream which I've done:

zuul:
  sensitiveHeaders:
  routes:
    instances:
      path: /instances/**
      serviceId: instance-service
    restore:
      path: /restore/**
      serviceId: restore-service

Setting sensitiveHeaders empty should allow everything (for testing of course).

Looking further at the docs I see I need to add @EnableOAuth2Sso to my Zuul configuration. This is where I get confused/things break.

From what I know, @EnableOAuth2Sso is for generating and validating tokens. I don't want to do that. I already have my nice token ready for my microservice (which validates it down there).

How do I tell Zuul to not mess with my JWTs and just send them along?

1

There are 1 answers

0
Chris On BEST ANSWER

I've solved this, there was to many things wrong with my code to detail but the gist of the issue was:

  • I was trying to send the entire JWT to the microservice when I should have just been sending the access_token
  • When I tried sending the access_token, ember-simple-auth0 actually sends the id_token by default
  • I needed to configure Zuul to pass CORS requests straight to the microservices

Once I started sending the access_token rather than the id_token it was easy to start debugging the issue.

To tell ember-simple-auth0 to use the access_token instead add a new authorizer with the following:

// app/authorizers/application.js    
import Ember from 'ember';
    import BaseAuthorizer from 'ember-simple-auth/authorizers/base';
    const {
      isPresent,
      debug
    } = Ember;

    export default BaseAuthorizer.extend({
      authorize(sessionData, block) {
        let userToken = sessionData['accessToken'];

        if (isPresent(userToken)) {
          block('Authorization', `Bearer ${userToken}`);
        } else {
          debug('Could not find the authorization token in the session data for the jwt authorizer.');
        }
      }
    });

Then remember to tell your adapter to use the new authorizer:

export default DS.JSONAPIAdapter.extend(DataAdapterMixin, {
  authorizer: 'authorizer:application',
});

To forward CORS to your microservices use:

spring:
  mvc:
    dispatch-options-request: true

And making sure you're not stripping the headers from the request with:

zuul:
  sensitiveHeaders:
  routes:
    instances:
      path: /instances/**
      serviceId: instance-service
      stripPrefix: false

    restore:
      path: /restore/**
      serviceId: restore-service
      stripPrefix: false

Hopefully someone finds this useful.