Middleware to modify Tyk auth response

I am trying to set up Tyk to use it with my next project and so far I think it’s a really good software. I did set up OIDC with Keycloak successfully and I am happy it was pretty simple to do so (I think you could mention somewhere that the auth token AUD field must contain the client ID though to make things even simpler).

To do some testing I did put a website that serves HTML behind Tyk + OpenID authentication. Now I want to modify the default Tyk unauthenticated response:

{
    "error": "Key not authorised"
}

Can I modify this response to be something else? I tried to use “response” midddleware, but it only modifies the upstream response. Is there any way to modify the Tyk response? Ideally I would want to check if there is a “Accept: text/html” header in the request and if so I would like to be able to serve HTML page that redirects to the login page. If there is “Accept: application/json” header in the request I would like to either preserve Tyk response or use my own JSON response.

2 Likes

Hey, thanks for the recommendation on OIDC documentation. I’ll pass the recommendation on to the documentation team at Tyk.

I’m not sure on your query and will leave others to answer it :slight_smile:

I tried with plugins, but it seems that is no way to modify response sent back from Tyk Gateway no matter which lifecycle hook I was using. It seems that plugins can only modify the upstream response. Is that correct?

The solution I found is to setup the Nginx server (or something similar) in front of Tyk (Nginx → Tyk Gateway → Upstream) and serve custom response via Nginx in case Tyk returns it’s response. It seems far from perfect and I would love to hear if there is some better solution.

In case anyone else needs something similar. If you want to use this exact config you need to configure tyk (in tyk.conf by default) to listen to the 8000 port ("listen_port": 8000) with no SSL enabled.

It is also important to use proxy_intercept_errors on; directive in the Nginx config, because otherwise it will not intercept error codes from Tyk.

Nginx config:

map $http_accept $accept_extension {
  default      json;
  '~text/html' html;
}

map $http_upgrade $connection_upgrade {
  default upgrade;
  ''      close;
}

server {
  listen 443 ssl;
  listen [::]:443 ssl;

  charset utf-8;

  root /opt/tyk-gateway/templates;

  server_name example.com;

  ssl_certificate /etc/ssl/certs/tyk.crt;
  ssl_certificate_key /etc/ssl/private/tyk.key;

  error_page 401 @unauthorized;

  location = /favicon.ico { access_log off; log_not_found off; }
  location = /robots.txt  { access_log off; log_not_found off; }

  location ~ /\.(?!well-known).* {
    deny all;
  }

  location / {
    proxy_http_version 1.1;
    proxy_intercept_errors on;
    proxy_set_header Host $http_host;
    proxy_set_header Scheme $scheme;
    proxy_set_header SERVER_PORT $server_port;
    proxy_set_header REMOTE_ADDR $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    proxy_pass http://127.0.0.1:8000;
  }

  location @unauthorized {
    internal;

    try_files /error_page_401.$accept_extension =401;
  }
}

Then you can put error_page_401.html and error_page_401.json in /opt/tyk-gateway/templates.

1 Like

Just found this thread.

In general, you can modify errors by modifying the error template. But you can’t modify headers, and template do not have too much variables for conditional logic.

The error you see is coming from Tyk itself, and not even reach upstream - thats why plugins did not worked. Alternative to nginx will be having second keyless API which is put on top of your original one, and plugins attached to it should do what you want.