krakend / krakend-ce

KrakenD Community Edition: High-performance, stateless, declarative, API Gateway written in Go.
https://www.krakend.io
Apache License 2.0
1.98k stars 452 forks source link

Use request headers to get token from oauth #307

Closed juanvasquezreyes closed 3 years ago

juanvasquezreyes commented 3 years ago

I'm trying to use krakend and connect it to an oauth2 instance, but I dont want to hardcode the clientid and clientsecret in the config and I have different clientids depending on the request

will be nice to send those in a header and in krakend when making the oauth call use the values from those headers

"extra_config": {
                "github.com/devopsfaith/krakend-oauth2-clientcredentials": {
                    "client_id": "CLIENT_ID_HEADER",
                    "client_secret": "CLIENT_SECRET_HEADER",
                    "token_url": "oauth_server",
                    "endpoint_params": {
                        "client_id": ["CLIENT_ID_HEADER"],
                        "client_secret": ["CLIENT_SECRET_HEADER"]
                    }
                }
            }

curl call example curl -H "CLIENT_ID_HEADER=client_id" -H "CLIENT_SECRET_HEADER=secret" http://krakend.example.com

kpacha commented 3 years ago

the oauth2-clientcredentials module adds an extra level of security and it's intended to authenticate and authorize the gateway itself, not the client.

if you want delegate the authorization of the client's request to the backend, you can just forward the authorization header: https://www.krakend.io/docs/endpoints/parameter-forwarding/#headers-forwarding or just move to client JWT

juanvasquezreyes commented 3 years ago

@kpacha This is what I'm trying to do

user will send a put request with a json body and some headers client_id and client_secret header, I want krakend to extract the headers and send a POST request to another endpoint using those headers to get the token and append that token to the original put request

I have the logic almost completed with lua, but the post call its not working because in the post call need to send my body as "Content-Type: application/x-www-form-urlencoded" based on the keycloak documentation https://developers.redhat.com/blog/2020/01/29/api-login-and-jwt-token-generation-using-keycloak#test_your_new_client

{
    "version": 2,
    "timeout": "5s",
    "cache_ttl": "300s",
    "port": 8000,
    "extra_config": {
        "github_com/devopsfaith/krakend-cors": {
            "allow_origins": ["http://localhost:8080", "http://localhost:3000", "http://192.168.99.100:3000"],
            "allow_methods": ["POST", "GET", "PUT"],
            "allow_headers": ["Origin", "Authorization", "Content-Type"],
            "expose_headers": ["Content-Length"],
            "max_age": "12h"
        }
    },
    "endpoints": [{}, {
        "endpoint": "/test",
        "method": "PUT",
        "headers_to_pass": ["*"],
        "timeout": "5s",
        "extra_config": {
            "github.com/devopsfaith/krakend-lua/proxy": {
                "pre": "print('Juan'); local r = http_response.new('https://keycloak.com/token', 'POST','client_id=test&client_secret=clientsecret&grant_type=client_credentials'); print(r:body());",
                "post": "local resp = response.load(); local responseData = resp:data(); local token = responseData:get('access_token');resp:headers('Token',token);",
                "live": true,
                "allow_open_libs": true
            }
        },
        "backend": [{
            "url_pattern": "/api/call",
            "method": "PUT",
            "encoding": "json",
            "host": ["http://myapiserver.com"]
        }]
    }]
}

is what I'm trying to do even possible?

kpacha commented 3 years ago

maybe the keycloak server is expecting a content-type header?

local headers = {["Content-Type"] = "application/x-www-form-urlencoded"}
local body = 'client_id=test&client_secret=clientsecret&grant_type=client_credentials'
local r = http_response.new('https://keycloak.com/token', 'POST', body, headers)
juanvasquezreyes commented 3 years ago

maybe the keycloak server is expecting a content-type header?

local headers = {["Content-Type"] = "application/x-www-form-urlencoded"}
local body = 'client_id=test&client_secret=clientsecret&grant_type=client_credentials'
local r = http_response.new('https://keycloak.com/token', 'POST', body, headers)

Thank you, it works!!

also the whole flow that I wanted it

github-actions[bot] commented 2 years ago

This issue was marked as resolved a long time ago and now has been automatically locked as there has not been any recent activity after it. You can still open a new issue and reference this link.