External Oauth2 identity integration

Hi there, first of all well done on your great product! Great job.

We are considering using tyk for our production setup, however can not find a way to integrate it with our external oauth id.

Desired flow:

  • request to proxy

  • proxy validates authorization barrer by calling external id service e.g. api.company.com/oauth/token

  • then token gets cached based on token expiration provided as a response

  • proxy processing configured upstream

  • following calls would not make calls to external id anymore but rely on cached token presence.

Would you be able to assist on how this workflow could be achieved, please?

1 Like

Hi Pawel,

Yes this should be completely possible using custom Tyk Auth middleware plugins.

Here you can have some custom code intercept the request, handle your authorization flow and then allow the request through.

This code can either store a cached version in redis itself using a Tyk-provided API or it can use the identity extractor (cache) to have Tyk do it (this shaves a few nanoseconds off of the latency as the language / plugin barrier does not need to be crossed by the request).

Relevant docs are here:

cc @matiasb (because he knows more about iD extractor and auth MW than I do).

Hi @Martin / @matiasb

Thank you for your response and suggestions.

Looks like exactly what I need:

  • write custom plugin (preferably in go?) doing REST token validation
  • define identity extractor via custom middleware in config
  • bundle using tyk-cli bundler
  • place in bundles directory

Sounds simple enough, however I can’t find any docs of any sample plugins / skeleton in Go?

I am as well very surprised there is no such plugin already :wink:
Feels like a very common use case :wink:

Norbert yet - there was a PoC for a while but it wasn’t really publishable.

Here’s a bunch you can use as a reference though:

1 Like

Thanks @Martin

I have the demo concept of the plugin here:

I am however struggling to load this onto my gateway.

My tyk.conf
"enable_bundle_downloader": true, "bundle_base_url": "https://github.com/sipsynergy/tyk-token-validator-plugin/blob/master/", "global_session_lifetime": 100, "force_global_session_lifetime": false, "max_idle_connections_per_host": 100, "custom_middleware": { "pre": [ { "name": "ExternalTokenValidatorMiddleware", "require_session": true } ], "id_extractor": { "extract_from": "header", "extract_with": "value", "extractor_config": { "header_name": "Authorization" } }, "driver": "python" }

My docker compose (where i placed both plugin directory and build zip):
tyk_gateway: image: tykio/tyk-gateway:latest ports: - "80:8080" - "8080:8080" volumes: - ./tyk.conf:/opt/tyk-gateway/tyk.conf - ./bundles:/opt/tyk-gateway/middleware/bundles networks: - gateway environment: - TYKVERSION=-python

As soon as i switch API to auth custom (plugin), all my proxy calls dying and no response from proxy.

Would you be able to assist please and help me out where I could find any logs / is my configuration correct?

Hi Pawel, I’m working on a sample Go plugin to share with you.

You may check your container logs, see docker ps, and then run docker logs [container-id], in this case it will be useful to get the gateway logs.

Thank you @matiasb

Here are my panic logs:

time=“Feb 13 15:52:49” level=info msg=“API reload complete”
2017/02/13 15:52:50 http: panic serving 172.19.0.1:50124: runtime error: invalid memory address or nil pointer dereference
goroutine 53167 [running]:
net/http.(*conn).serve.func1(0xc4207bc080)
/usr/local/go/src/net/http/server.go:1491 +0x12a
panic(0xcc2520, 0xc420012060)
/usr/local/go/src/runtime/panic.go:458 +0x243
main.(*DynamicMiddleware).ProcessRequest(0xc42067c2e0, 0x14c9ce0, 0xc4202a92b0, 0xc420789590, 0xce30a0, 0x0, 0x0, 0x0, 0x0)
/src/github.com/TykTechnologies/tyk/plugins.go:155 +0x5f9
main.CreateMiddleware.func1.1(0x14c9ce0, 0xc4202a92b0, 0xc420789590)
/src/github.com/TykTechnologies/tyk/middleware.go:76 +0x637
net/http.HandlerFunc.ServeHTTP(0xc420310d40, 0x14c9ce0, 0xc4202a92b0, 0xc420789590)
/usr/local/go/src/net/http/server.go:1726 +0x44
main.CreateMiddleware.func1.1(0x14c9ce0, 0xc4202a92b0, 0xc420789590)
/src/github.com/TykTechnologies/tyk/middleware.go:100 +0x83c
net/http.HandlerFunc.ServeHTTP(0xc420310d80, 0x14c9ce0, 0xc4202a92b0, 0xc420789590)
/usr/local/go/src/net/http/server.go:1726 +0x44
main.CreateMiddleware.func1.1(0x14c9ce0, 0xc4202a92b0, 0xc420789590)
/src/github.com/TykTechnologies/tyk/middleware.go:100 +0x83c
net/http.HandlerFunc.ServeHTTP(0xc420310dc0, 0x14c9ce0, 0xc4202a92b0, 0xc420789590)
/usr/local/go/src/net/http/server.go:1726 +0x44
main.CreateMiddleware.func1.1(0x14c9ce0, 0xc4202a92b0, 0xc420789590)
/src/github.com/TykTechnologies/tyk/middleware.go:100 +0x83c
net/http.HandlerFunc.ServeHTTP(0xc420310e00, 0x14c9ce0, 0xc4202a92b0, 0xc420789590)
/usr/local/go/src/net/http/server.go:1726 +0x44
github.com/TykTechnologies/tyk/vendor/github.com/gorilla/mux.(*Router).ServeHTTP(0xc420630b90, 0x14c9ce0, 0xc4202a92b0, 0xc420789590)
/src/github.com/TykTechnologies/tyk/vendor/github.com/gorilla/mux/mux.go:114 +0x10d
net/http.(*ServeMux).ServeHTTP(0xc4203f77d0, 0x14c9ce0, 0xc4202a92b0, 0xc4207893b0)
/usr/local/go/src/net/http/server.go:2022 +0x7f
net/http.serverHandler.ServeHTTP(0xc42014f500, 0x14c9ce0, 0xc4202a92b0, 0xc4207893b0)
/usr/local/go/src/net/http/server.go:2202 +0x7d
net/http.(*conn).serve(0xc4207bc080, 0x14cad20, 0xc4203b0e40)
/usr/local/go/src/net/http/server.go:1579 +0x4b7
created by net/http.(*Server).Serve
/usr/local/go/src/net/http/server.go:2293 +0x44d

Hi, there are a few syntax errors on the Python code, also, for specifying custom authentication checks, you must use the auth_check option -just like the Python sample we have online-.
I did a few modifications on the code you’ve provided, you may check the code here:

Also if you’re interested in Go/gRPC plugins (which could perform much better), I’ve just pushed this sample (hooks.go is the most interesting file here, will extend the README soon):

It should be possible to use this sample by doing go get with the repository URL and building the program. Note that this is the gRPC approach, so your tyk.conf should have this:

  "coprocess_options": {
    "enable_coprocess": true,
    "coprocess_grpc_server": "tcp://127.0.0.1:5000"
  },

You will also need to update your Docker settings to run a standard Tyk build (TYKVERSION isn’t needed).
The coprocess_grpc_server points to the Go server. When a request comes, Tyk will send it to this server and reply with a modified request/response object.
The last step is to use to enable rich plugins authentication for this API, a working API definition looks like this:

{
    "name": "Tyk Test API",
    "api_id": "1",
    "org_id": "default",
    "definition": {
        "location": "",
        "key": ""
    },
    "use_keyless": false,
    "auth": {
        "auth_header_name": ""
    },
    "version_data": {
        "not_versioned": true,
        "versions": {
            "Default": {
                "name": "Default",
                "expires": "3000-01-02 15:04",
                "use_extended_paths": true,
                "extended_paths": {
                    "ignored": [],
                    "white_list": [],
                    "black_list": []
                }
            }
        }
    },
    "proxy": {
        "listen_path": "/quickstart/",
        "target_url": "http://httpbin.org/",
        "strip_listen_path": true
    },
    "custom_middleware_bundle": "test-bundle.zip",
    "enable_coprocess_auth": true,
    "do_not_track": true
}

The most important settings in this spec are:

  • use_keyless: when true, indicates that this is a protected API, access will be denied unless a valid session is provided (by Tyk or your rich plugins).
  • custom_middleware_bundle: is the bundle filename, this will be fetched from your server, using the bundle_base_url specified in your tyk.conf.
  • enable_coprocess_auth: indicates Tyk that you will authorize access access to this API by using rich plugins and not the standard Tyk tokens.

Best.