Cookie + Authorization Bearer

Is there any way to make Tyk check both Authorization-header (Bearer token) and a specified Cookie?

My API is intended to be consumed both by Mobile Apps and the Web so I will be using Auth-header with JWT token in the mobile app and a Cookie for the web. My upstream service is able to create the accessToken for both usecases but Tyk does not allow my requests to pass through from the web (cookie).

The relevant parts of my API config (Tyk CE):

"auth": {
    "use_param": false,
    "param_name": "",
    "use_cookie": true,
    "cookie_name": "access_token",
    "auth_header_name": "Authorization",
    "use_certificate": false
  },
  "use_basic_auth": false,
  "use_mutual_tls_auth": false,
  "client_certificates": [],
  "upstream_certificates": {},
  "pinned_public_keys": null,
  "enable_jwt": true,
  "use_standard_auth": false,
  "enable_coprocess_auth": false,
  "jwt_signing_method": "hmac",
  "jwt_source": "{{ JWT_SOURCE }}",
  "jwt_identity_base_field": "sub",
  "jwt_client_base_field": "",
  "jwt_policy_field_name": "policy",

Will this be possible or am I stuck actually having to proxy all my web API-requests in front of tyk to get cookies to work?

2 Likes

I think the best way here is to create a simple JSVM PRE middleware, which read value from Cookie, and adds it to a header.

Cheers.

Thank you, that is actually what I started doing, so thanks for the pointer that I was aiming for the right thing.

For future references this is what I ended up with (feel free to constructively criticize):

/* --- rewriteCookie.js --- */

var pairSplitRegExp = /; */;

var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;

function parse(str, options) {
  if (typeof str !== "string") {
    throw new TypeError("argument str must be a string");
  }

  var obj = {};
  var opt = options || {};
  var pairs = str.split(pairSplitRegExp);
  var dec = opt.decode || decodeURIComponent;

  for (var i = 0; i < pairs.length; i++) {
    var pair = pairs[i];
    var eq_idx = pair.indexOf("=");

    // skip things that don't look like key=value
    if (eq_idx < 0) {
      continue;
    }

    var key = pair.substr(0, eq_idx).trim();
    var val = pair.substr(++eq_idx, pair.length).trim();

    // quoted values
    if ('"' == val[0]) {
      val = val.slice(1, -1);
    }

    // only assign once
    if (undefined == obj[key]) {
      obj[key] = tryDecode(val, dec);
    }
  }

  return obj;
}

function tryDecode(str, decode) {
  try {
    return decode(str);
  } catch (e) {
    return str;
  }
}

function strip(str) {
  var re = /^[s:]*([A-Za-z0-9-_=]+\.[A-Za-z0-9-_=]+\.?[A-Za-z0-9-_+\/=]*)/;
  if (!str) {
    return;
  }
  var result = str.match(re);
  if (result) {
    return result[1];
  }
}

function find(array, fn) {
  for (var i = 0; i < array.length; i += 1) {
    if (fn(array[i])) {
      return array[i];
    }
  }
}

// Create your middleware object
var rewriteCookie = new TykJS.TykMiddleware.NewMiddleware({});

// Initialise it with your functionality by passing a closure that accepts two objects
// into the NewProcessRequest() function:
rewriteCookie.NewProcessRequest(function(request, session, spec) {
  try {
    var cookies = request.Headers.Cookie.map(function(c) {
      return parse(c);
    });
    if (cookies.length) {
      var cookie = find(cookies, function(c) {
        return c.access_token;
      });
      var accessToken = strip(cookie.access_token);
      if (accessToken) {
        request.SetHeaders["Authorization"] = "Bearer " + accessToken;
      }
    }
  } catch (error) {
    console.error(error);
  }

  // You MUST return both the request and session metadata
  return rewriteCookie.ReturnData(request, session.meta_data);
});

2 Likes

If you want to share it😀

Done, and done! (cleaned it up a bit)
Link:

3 Likes

Thank you John :1st_place_medal: